summaryrefslogtreecommitdiffstats
path: root/src/H5VLint.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5VLint.c')
-rw-r--r--src/H5VLint.c2390
1 files changed, 2390 insertions, 0 deletions
diff --git a/src/H5VLint.c b/src/H5VLint.c
new file mode 100644
index 0000000..861629f
--- /dev/null
+++ b/src/H5VLint.c
@@ -0,0 +1,2390 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: The Virtual Object Layer as described in documentation.
+ * The pupose is to provide an abstraction on how to access the
+ * underlying HDF5 container, whether in a local file with
+ * a specific file format, or remotely on other machines, etc...
+ */
+
+
+/****************/
+/* Module Setup */
+/****************/
+
+#include "H5VLmodule.h" /* This source code file is part of the H5VL module */
+
+
+/***********/
+/* Headers */
+/***********/
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Aprivate.h" /* Attributes */
+#include "H5CXprivate.h" /* API Contexts */
+#include "H5Dprivate.h" /* Datasets */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* Files */
+#include "H5FLprivate.h" /* Free lists */
+#include "H5Gprivate.h" /* Groups */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Mprivate.h" /* Maps */
+#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 */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/* Object wrapping context info */
+typedef struct H5VL_wrap_ctx_t {
+ unsigned rc; /* Ref. count for the # of times the context was set / reset */
+ H5VL_t *connector; /* VOL connector for "outermost" class to start wrap */
+ 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 */
+/********************/
+
+
+/********************/
+/* 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);
+static int64_t H5VL__conn_inc_rc(H5VL_t *connector);
+static int64_t H5VL__conn_dec_rc(H5VL_t *connector);
+static void *H5VL__object(hid_t id, H5I_type_t obj_type);
+static herr_t H5VL__free_vol_wrapper(H5VL_wrap_ctx_t *vol_wrap_ctx);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* Package initialization variable */
+hbool_t H5_PKG_INIT_VAR = FALSE;
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* VOL ID class */
+static const H5I_class_t H5I_VOL_CLS[1] = {{
+ H5I_VOL, /* ID class value */
+ 0, /* Class flags */
+ 0, /* # of reserved IDs for class */
+ (H5I_free_t)H5VL__free_cls /* Callback routine for closing objects of this class */
+}};
+
+/* Declare a free list to manage the H5VL_class_t struct */
+H5FL_DEFINE_STATIC(H5VL_class_t);
+
+/* Declare a free list to manage the H5VL_t struct */
+H5FL_DEFINE(H5VL_t);
+
+/* Declare a free list to manage the H5VL_object_t struct */
+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_phase1
+ *
+ * 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
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_init_phase1(void)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* FUNC_ENTER() does all the work */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* 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)
+
+ /* Initialize all packages for VOL-managed objects */
+ if(H5T_init() < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to initialize datatype interface")
+ if(H5D_init() < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to initialize dataset interface")
+ if(H5F_init() < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to initialize file interface")
+ if(H5G_init() < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to initialize group interface")
+ if(H5A_init() < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to initialize attribute interface")
+ if(H5M_init() < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to initialize map interface")
+
+ /* 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() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__init_package
+ *
+ * Purpose: Initialize interface-specific information
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__init_package(void)
+{
+ 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)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to initialize H5VL interface")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__init_package() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_term_package
+ *
+ * Purpose: Terminate various H5VL objects
+ *
+ * Return: Success: Positive if anything was done that might
+ * affect other interfaces; zero otherwise.
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5VL_term_package(void)
+{
+ int n = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ if(H5_PKG_INIT_VAR) {
+ 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 {
+ if(H5I_nmembers(H5I_VOL) > 0) {
+ /* Unregister all VOL connectors */
+ (void)H5I_clear_type(H5I_VOL, TRUE, 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 */
+
+ FUNC_LEAVE_NOAPI(n)
+} /* end H5VL_term_package() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__free_cls
+ *
+ * Purpose: Frees a file VOL class struct and returns an indication of
+ * success. This function is used as the free callback for the
+ * virtual object layer object identifiers
+ * (c.f.: H5VL_init_interface).
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__free_cls(H5VL_class_t *cls)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(cls);
+
+ /* Shut down the VOL connector */
+ if(cls->terminate && cls->terminate() < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEOBJ, FAIL, "VOL connector did not terminate cleanly")
+
+ /* Release the class */
+ H5MM_xfree_const(cls->name);
+ H5FL_FREE(H5VL_class_t, cls);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__free_cls() */
+
+
+/*-------------------------------------------------------------------------
+ * 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_by_name(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_by_name(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, TRUE, H5P_VOL_INITIALIZE_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
+ * match the VOL connector stack for the file.
+ *
+ * Return: Success: Wrapped object pointer
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * Friday, October 7, 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL__wrap_obj(void *obj, H5I_type_t obj_type)
+{
+ H5VL_wrap_ctx_t *vol_wrap_ctx = NULL; /* Object wrapping context */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check arguments */
+ HDassert(obj);
+
+ /* Retrieve the VOL object wrapping context */
+ if(H5CX_get_vol_wrap_ctx((void **)&vol_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "can't get VOL object wrap context")
+
+ /* If there is a VOL object wrapping context, wrap the object */
+ if(vol_wrap_ctx) {
+ /* Wrap object, using the VOL callback */
+ if(NULL == (ret_value = H5VL_wrap_object(vol_wrap_ctx->connector->cls, vol_wrap_ctx->obj_wrap_ctx, obj, obj_type)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "can't wrap object")
+ } /* end if */
+ else
+ ret_value = obj;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__wrap_obj() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__new_vol_obj
+ *
+ * Purpose: Creates a new VOL object, to use when registering an ID.
+ *
+ * Return: Success: VOL object pointer
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * Friday, October 7, 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5VL_object_t *
+H5VL__new_vol_obj(H5I_type_t type, void *object, H5VL_t *vol_connector, hbool_t wrap_obj)
+{
+ H5VL_object_t *new_vol_obj = NULL; /* Pointer to new VOL object */
+ hbool_t conn_rc_incr = FALSE; /* Whether the VOL connector refcount has been incremented */
+ H5VL_object_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check arguments */
+ HDassert(object);
+ HDassert(vol_connector);
+
+ /* Make sure type number is valid */
+ if(type != H5I_ATTR && type != H5I_DATASET && type != H5I_DATATYPE
+ && type != H5I_FILE && type != H5I_GROUP && type != H5I_MAP)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, NULL, "invalid type number")
+
+ /* Create the new VOL object */
+ if(NULL == (new_vol_obj = H5FL_CALLOC(H5VL_object_t)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, NULL, "can't allocate memory for VOL object")
+ new_vol_obj->connector = vol_connector;
+ if(wrap_obj) {
+ if(NULL == (new_vol_obj->data = H5VL__wrap_obj(object, type)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, NULL, "can't wrap library object")
+ } /* end if */
+ else
+ new_vol_obj->data = object;
+
+ /* Bump the reference count on the VOL connector */
+ H5VL__conn_inc_rc(vol_connector);
+ conn_rc_incr = TRUE;
+
+ /* If this is a datatype, we have to hide the VOL object under the H5T_t pointer */
+ if(H5I_DATATYPE == type) {
+ if(NULL == (ret_value = (H5VL_object_t *)H5T_construct_datatype(new_vol_obj)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "can't construct datatype object")
+ } /* end if */
+ else
+ ret_value = (H5VL_object_t *)new_vol_obj;
+
+done:
+ /* Cleanup on error */
+ if(NULL == ret_value) {
+ if(conn_rc_incr && H5VL__conn_dec_rc(vol_connector) < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTDEC, NULL, "unable to decrement ref count on VOL connector")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__new_vol_obj() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_conn_copy
+ *
+ * Purpose: Copy VOL connector ID & info.
+ *
+ * Note: This is an "in-place" copy.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_conn_copy(H5VL_connector_prop_t *connector_prop)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ if(connector_prop) {
+ /* Copy the connector ID & info, if there is one */
+ if(connector_prop->connector_id > 0) {
+ /* Increment the reference count on connector ID and copy connector info */
+ if(H5I_inc_ref(connector_prop->connector_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINC, FAIL, "unable to increment ref count on VOL connector ID")
+
+ /* Copy connector info, if it exists */
+ if(connector_prop->connector_info) {
+ H5VL_class_t *connector; /* Pointer to connector */
+ void *new_connector_info = NULL; /* Copy of connector info */
+
+ /* Retrieve the connector for the ID */
+ if(NULL == (connector = (H5VL_class_t *)H5I_object(connector_prop->connector_id)))
+ HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a VOL connector ID")
+
+ /* Allocate and copy connector info */
+ if(H5VL_copy_connector_info(connector, &new_connector_info, connector_prop->connector_info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "connector info copy failed")
+
+ /* Set the connector info to the copy */
+ connector_prop->connector_info = new_connector_info;
+ } /* end if */
+ } /* end if */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_conn_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_conn_free
+ *
+ * Purpose: Free VOL connector ID & info.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_conn_free(const H5VL_connector_prop_t *connector_prop)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ if(connector_prop) {
+ /* Free the connector info (if it exists) and decrement the ID */
+ if(connector_prop->connector_id > 0) {
+ if(connector_prop->connector_info)
+ /* Free the connector info */
+ if(H5VL_free_connector_info(connector_prop->connector_id, connector_prop->connector_info) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to release VOL connector info object")
+
+ /* Decrement reference count for connector ID */
+ if(H5I_dec_ref(connector_prop->connector_id) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "can't decrement reference count for connector ID")
+ }
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_conn_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_register
+ *
+ * Purpose: VOL-aware version of H5I_register. Constructs an H5VL_object_t
+ * from the passed-in object and registers that. Does the right
+ * thing with datatypes, which are complicated under the VOL.
+ *
+ * Return: Success: A valid HDF5 ID
+ * Failure: H5I_INVALID_HID
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL_register(H5I_type_t type, void *object, H5VL_t *vol_connector, hbool_t app_ref)
+{
+ H5VL_object_t *vol_obj = NULL; /* VOL object wrapper for library object */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5I_INVALID_HID)
+
+ /* Check arguments */
+ HDassert(object);
+ HDassert(vol_connector);
+
+ /* Set up VOL object for the passed-in data */
+ /* (Does not wrap object, since it's from a VOL callback) */
+ if(NULL == (vol_obj = H5VL__new_vol_obj(type, object, vol_connector, FALSE)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, FAIL, "can't create VOL object")
+
+ /* Register VOL object as _object_ type, for future object API calls */
+ if((ret_value = H5I_register(type, vol_obj, app_ref)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize handle")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_register() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_register_using_existing_id
+ *
+ * Purpose: Registers an OBJECT in a TYPE with the supplied ID for it.
+ * This routine will check to ensure the supplied ID is not already
+ * in use, and ensure that it is a valid ID for the given type,
+ * but will NOT check to ensure the OBJECT is not already
+ * registered (thus, it is possible to register one object under
+ * multiple IDs).
+ *
+ * NOTE: Intended for use in refresh calls, where we have to close
+ * and re-open the underlying data, then hook the VOL object back
+ * up to the original ID.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_register_using_existing_id(H5I_type_t type, void *object, H5VL_t *vol_connector, hbool_t app_ref, hid_t existing_id)
+{
+ H5VL_object_t *new_vol_obj = NULL; /* Pointer to new VOL object */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check arguments */
+ HDassert(object);
+ HDassert(vol_connector);
+
+ /* Set up VOL object for the passed-in data */
+ /* (Wraps object, since it's a library object) */
+ if(NULL == (new_vol_obj = H5VL__new_vol_obj(type, object, vol_connector, TRUE)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, FAIL, "can't create VOL object")
+
+ /* Call the underlying H5I function to complete the registration */
+ if(H5I_register_using_existing_id(type, new_vol_obj, app_ref, existing_id) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, FAIL, "can't register object under existing ID")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_register_using_existing_id() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_register_using_vol_id
+ *
+ * Purpose: Utility function to create a user ID for an object created
+ * or opened through the VOL. Uses the VOL connector's ID to
+ * get the connector information instead of it being passed in.
+ *
+ * Return: Success: A valid HDF5 ID
+ * Failure: H5I_INVALID_HID
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL_register_using_vol_id(H5I_type_t type, void *obj, hid_t connector_id, hbool_t app_ref)
+{
+ H5VL_class_t *cls = NULL; /* VOL connector class */
+ H5VL_t *connector = NULL; /* VOL connector struct */
+ hbool_t conn_id_incr = FALSE; /* Whether the VOL connector ID has been incremented */
+ hid_t ret_value = H5I_INVALID_HID;/* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Get the VOL class object from the connector's ID */
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, H5I_INVALID_HID, "not a VOL connector ID")
+
+ /* Setup VOL info struct */
+ if(NULL == (connector = H5FL_CALLOC(H5VL_t)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, H5I_INVALID_HID, "can't allocate VOL info struct")
+ connector->cls = cls;
+ connector->id = connector_id;
+ if(H5I_inc_ref(connector->id, FALSE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector")
+ conn_id_incr = TRUE;
+
+ /* Get an ID for the VOL object */
+ if((ret_value = H5VL_register(type, obj, connector, app_ref)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object handle")
+
+done:
+ /* Clean up on error */
+ if(ret_value < 0) {
+ /* Decrement VOL connector ID ref count on error */
+ if(conn_id_incr && H5I_dec_ref(connector_id) < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTDEC, H5I_INVALID_HID, "unable to decrement ref count on VOL connector")
+
+ /* Free VOL connector struct */
+ if(NULL != connector)
+ connector = H5FL_FREE(H5VL_t, connector);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_register_using_vol_id() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_create_object_using_vol_id
+ *
+ * Purpose: Similar to H5VL_register_using_vol_id but does not create
+ * an id. Intended for use by internal library routines,
+ * therefore it wraps the object.
+ *
+ * Return: Success: VOL object pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+H5VL_object_t *
+H5VL_create_object_using_vol_id(H5I_type_t type, void *obj, hid_t connector_id)
+{
+ H5VL_class_t *cls = NULL; /* VOL connector class */
+ H5VL_t *connector = NULL; /* VOL connector struct */
+ hbool_t conn_id_incr = FALSE; /* Whether the VOL connector ID has been incremented */
+ H5VL_object_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Get the VOL class object from the connector's ID */
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, NULL, "not a VOL connector ID")
+
+ /* Setup VOL info struct */
+ if(NULL == (connector = H5FL_CALLOC(H5VL_t)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, NULL, "can't allocate VOL info struct")
+ connector->cls = cls;
+ connector->id = connector_id;
+ if(H5I_inc_ref(connector->id, FALSE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINC, NULL, "unable to increment ref count on VOL connector")
+ conn_id_incr = TRUE;
+
+ /* Set up VOL object for the passed-in data */
+ /* (Wraps object, since it's a library object) */
+ if(NULL == (ret_value = H5VL__new_vol_obj(type, obj, connector, TRUE)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, NULL, "can't create VOL object")
+
+done:
+ /* Clean up on error */
+ if(!ret_value) {
+ /* Decrement VOL connector ID ref count on error */
+ if(conn_id_incr && H5I_dec_ref(connector_id) < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTDEC, NULL, "unable to decrement ref count on VOL connector")
+
+ /* Free VOL connector struct */
+ if(NULL != connector)
+ connector = H5FL_FREE(H5VL_t, connector);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_create_object_using_vol_id() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__conn_inc_rc
+ *
+ * Purpose: Wrapper to increment the ref. count on a connector.
+ *
+ * Return: Current ref. count (can't fail)
+ *
+ * Programmer: Quincey Koziol
+ * February 23, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+static int64_t
+H5VL__conn_inc_rc(H5VL_t *connector)
+{
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(connector);
+
+ /* Increment refcount for connector */
+ connector->nrefs++;
+
+ FUNC_LEAVE_NOAPI(connector->nrefs)
+} /* end H5VL__conn_inc_rc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__conn_dec_rc
+ *
+ * Purpose: Wrapper to decrement the ref. count on a connector.
+ *
+ * Return: Current ref. count (>=0) on success, <0 on failure
+ *
+ * Programmer: Quincey Koziol
+ * February 23, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+static int64_t
+H5VL__conn_dec_rc(H5VL_t *connector)
+{
+ int64_t ret_value = -1; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check arguments */
+ HDassert(connector);
+
+ /* Decrement refcount for connector */
+ connector->nrefs--;
+
+ /* Check for last reference */
+ if(0 == connector->nrefs) {
+ if(H5I_dec_ref(connector->id) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to decrement ref count on VOL connector")
+ H5FL_FREE(H5VL_t, connector);
+
+ /* Set return value */
+ ret_value = 0;
+ } /* end if */
+ else
+ /* Set return value */
+ ret_value = connector->nrefs;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__conn_dec_rc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_free_object
+ *
+ * Purpose: Wrapper to unregister an object ID with a VOL aux struct
+ * and decrement ref count on VOL connector ID
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_free_object(H5VL_object_t *vol_obj)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check arguments */
+ HDassert(vol_obj);
+
+ /* Decrement refcount on connector */
+ if(H5VL__conn_dec_rc(vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to decrement ref count on VOL connector")
+
+ vol_obj = H5FL_FREE(H5VL_object_t, vol_obj);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_free_object() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_object_is_native
+ *
+ * Purpose: Query if an object is (if it's a file object) / is in (if its
+ * an object) a native connector's file.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * December 14, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_object_is_native(const H5VL_object_t *obj, hbool_t *is_native)
+{
+ const H5VL_class_t *cls; /* VOL connector class structs for object */
+ const H5VL_class_t *native_cls; /* Native VOL connector class structs */
+ int cmp_value; /* Comparison result */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check arguments */
+ HDassert(obj);
+ HDassert(is_native);
+
+ /* Retrieve the terminal connector class for the object */
+ cls = NULL;
+ if(H5VL_introspect_get_conn_cls(obj, H5VL_GET_CONN_LVL_TERM, &cls) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get VOL connector class")
+
+ /* Retrieve the native connector class */
+ if(NULL == (native_cls = (H5VL_class_t *)H5I_object_verify(H5VL_NATIVE, H5I_VOL)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't retrieve native VOL connector class")
+
+ /* Compare connector classes */
+ if(H5VL_cmp_connector_cls(&cmp_value, cls, native_cls) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCOMPARE, FAIL, "can't compare connector classes")
+
+ /* If classes compare equal, then the object is / is in a native connector's file */
+ *is_native = (cmp_value == 0);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_object_is_native() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_file_is_same
+ *
+ * Purpose: Query if two files are the same.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * December 14, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_file_is_same(const H5VL_object_t *vol_obj1, const H5VL_object_t *vol_obj2,
+ hbool_t *same_file)
+{
+ const H5VL_class_t *cls1; /* VOL connector class struct for first object */
+ const H5VL_class_t *cls2; /* VOL connector class struct for second object */
+ int cmp_value; /* Comparison result */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check arguments */
+ HDassert(vol_obj1);
+ HDassert(vol_obj2);
+ HDassert(same_file);
+
+ /* Retrieve the terminal connectors for each object */
+ cls1 = NULL;
+ if(H5VL_introspect_get_conn_cls(vol_obj1, H5VL_GET_CONN_LVL_TERM, &cls1) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get VOL connector class")
+ cls2 = NULL;
+ if(H5VL_introspect_get_conn_cls(vol_obj2, H5VL_GET_CONN_LVL_TERM, &cls2) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get VOL connector class")
+
+ /* Compare connector classes */
+ if(H5VL_cmp_connector_cls(&cmp_value, cls1, cls2) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCOMPARE, FAIL, "can't compare connector classes")
+
+ /* If the connector classes are different, the files are different */
+ if(cmp_value)
+ *same_file = FALSE;
+ else {
+ void *obj2; /* Terminal object for second file */
+
+ /* Get unwrapped (terminal) object for vol_obj2 */
+ if(NULL == (obj2 = H5VL_object_data(vol_obj2)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get unwrapped object")
+
+ /* Make callback */
+ if(H5VL_file_specific(vol_obj1, H5VL_FILE_IS_EQUAL, H5P_DATASET_XFER_DEFAULT, NULL, obj2, same_file) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "file specific failed")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_file_is_same() */
+
+
+/*-------------------------------------------------------------------------
+ * 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 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)
+
+ /* Check arguments */
+ HDassert(cls);
+
+ /* Copy the class structure so the caller can reuse or free it */
+ 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")
+ H5MM_memcpy(saved, cls, sizeof(H5VL_class_t));
+ if(NULL == (saved->name = H5MM_strdup(cls->name)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, H5I_INVALID_HID, "memory allocation failed for VOL connector name")
+
+ /* Initialize the VOL connector */
+ if(cls->initialize && cls->initialize(vipl_id) < 0)
+ 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)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector ID")
+
+done:
+ if(ret_value < 0 && saved) {
+ if(saved->name)
+ H5MM_xfree_const(saved->name);
+
+ H5FL_FREE(H5VL_class_t, saved);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_register_connector() */
+
+
+/*-------------------------------------------------------------------------
+ * 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, app_ref) < 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_by_name
+ *
+ * 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_by_name(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_by_name() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__is_connector_registered_by_value
+ *
+ * Purpose: Checks if a connector with a particular value (ID) is
+ * registered.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5VL__is_connector_registered_by_value(H5VL_class_value_t value)
+{
+ 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_VALUE;
+ op_data.u.value = value;
+ op_data.found_id = H5I_INVALID_HID;
+
+ /* Find connector with value */
+ 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_by_value() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__get_connector_id
+ *
+ * Purpose: Retrieves the VOL connector ID for a given object ID.
+ *
+ * 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(hid_t obj_id, hbool_t is_api)
+{
+ H5VL_object_t *vol_obj = NULL;
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Get the underlying VOL object for the object ID */
+ if(NULL == (vol_obj = H5VL_vol_object(obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Return the VOL object's VOL class ID */
+ ret_value = vol_obj->connector->id;
+ if(H5I_inc_ref(ret_value, is_api) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__get_connector_id() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__get_connector_id_by_name
+ *
+ * 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_by_name(const char *name, hbool_t is_api)
+{
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Find connector with name */
+ if((ret_value = H5VL__peek_connector_id_by_name(name)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_BADITER, H5I_INVALID_HID, "can't find VOL connector")
+
+ /* Found a connector with that name */
+ if(H5I_inc_ref(ret_value, is_api) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__get_connector_id_by_name() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__get_connector_id_by_value
+ *
+ * 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)
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL__get_connector_id_by_value(H5VL_class_value_t value, hbool_t is_api)
+{
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Find connector with value */
+ if((ret_value = H5VL__peek_connector_id_by_value(value)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_BADITER, H5I_INVALID_HID, "can't find VOL connector")
+
+ /* Found a connector with that value */
+ if(H5I_inc_ref(ret_value, is_api) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__get_connector_id_by_value() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__peek_connector_id_by_name
+ *
+ * Purpose: Retrieves the ID for a registered VOL connector. Does not
+ * increment the ref count
+ *
+ * Return: Positive if the VOL class has been registered
+ * Negative on error (if the class is not a valid class or
+ * not registered)
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL__peek_connector_id_by_name(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_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")
+
+ /* Set return value */
+ ret_value = op_data.found_id;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__peek_connector_id_by_name() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__peek_connector_id_by_value
+ *
+ * Purpose: Retrieves the ID for a registered VOL connector. Does not
+ * increment the ref count
+ *
+ * Return: Positive if the VOL class has been registered
+ * Negative on error (if the class is not a valid class or
+ * not registered)
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL__peek_connector_id_by_value(H5VL_class_value_t value)
+{
+ 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;
+
+ /* Find connector with value */
+ 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")
+
+ /* Set return value */
+ ret_value = op_data.found_id;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__peek_connector_id_by_value() */
+
+
+/*-------------------------------------------------------------------------
+ * 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
+ *
+ * Return: Success: The length of the connector name
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+ssize_t
+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_PACKAGE
+
+ /* get the object pointer */
+ if (NULL == (vol_obj = H5VL_vol_object(id)))
+ HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "invalid VOL identifier")
+
+ cls = vol_obj->connector->cls;
+
+ len = HDstrlen(cls->name);
+ if(name) {
+ HDstrncpy(name, cls->name, MIN(len + 1, size));
+ if(len >= size)
+ name[size - 1] = '\0';
+ } /* end if */
+
+ /* Set the return value for the API call */
+ ret_value = (ssize_t)len;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__get_connector_name() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_vol_object
+ *
+ * Purpose: Utility function to return the object pointer associated with
+ * a hid_t. This routine is the same as H5I_object for all types
+ * except for named datatypes, where the vol_obj is returned that
+ * is attached to the H5T_t struct.
+ *
+ * Return: Success: object pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+H5VL_object_t *
+H5VL_vol_object(hid_t id)
+{
+ void *obj = NULL;
+ H5I_type_t obj_type;
+ H5VL_object_t *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ obj_type = H5I_get_type(id);
+ if(H5I_FILE == obj_type || H5I_GROUP == obj_type || H5I_ATTR == obj_type ||
+ H5I_DATASET == obj_type || H5I_DATATYPE == obj_type) {
+ /* Get the object */
+ if(NULL == (obj = H5I_object(id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "invalid identifier")
+
+ /* If this is a datatype, get the VOL object attached to the H5T_t struct */
+ if(H5I_DATATYPE == obj_type)
+ if(NULL == (obj = H5T_get_named_type((H5T_t *)obj)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a named datatype")
+ } /* end if */
+ else
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "invalid identifier type to function")
+
+ ret_value = (H5VL_object_t *)obj;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_vol_object() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_object_data
+ *
+ * Purpose: Correctly retrieve the 'data' field for a VOL object (H5VL_object),
+ * even for nested / stacked VOL connectors.
+ *
+ * Return: Success: object pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_object_data(const H5VL_object_t *vol_obj)
+{
+ void *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Check for 'get_object' callback in connector */
+ if(vol_obj->connector->cls->wrap_cls.get_object)
+ ret_value = (vol_obj->connector->cls->wrap_cls.get_object)(vol_obj->data);
+ else
+ ret_value = vol_obj->data;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_object_data() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_object_unwrap
+ *
+ * Purpose: Correctly unwrap the 'data' field for a VOL object (H5VL_object),
+ * even for nested / stacked VOL connectors.
+ *
+ * Return: Success: Object pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_object_unwrap(const H5VL_object_t *vol_obj)
+{
+ void *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ if(NULL == (ret_value = H5VL_unwrap_object(vol_obj->connector->cls, vol_obj->data)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "can't unwrap object")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_object_unwrap() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__object
+ *
+ * Purpose: Internal function to return the VOL object pointer associated
+ * with an hid_t.
+ *
+ * Return: Success: object pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL__object(hid_t id, H5I_type_t obj_type)
+{
+ H5VL_object_t *vol_obj = NULL;
+ void *ret_value = NULL;
+
+ FUNC_ENTER_STATIC
+
+ /* Get the underlying object */
+ switch(obj_type) {
+ case H5I_GROUP:
+ case H5I_DATASET:
+ case H5I_FILE:
+ case H5I_ATTR:
+ case H5I_MAP:
+ /* get the object */
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "invalid identifier")
+ break;
+
+ case H5I_DATATYPE:
+ {
+ H5T_t *dt = NULL;
+
+ /* get the object */
+ if (NULL == (dt = (H5T_t *)H5I_object(id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "invalid identifier")
+
+ /* Get the actual datatype object that should be the vol_obj */
+ if (NULL == (vol_obj = H5T_get_named_type(dt)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a named datatype")
+ break;
+ }
+
+ case H5I_UNINIT:
+ case H5I_BADID:
+ case H5I_DATASPACE:
+ case H5I_VFL:
+ case H5I_VOL:
+ case H5I_GENPROP_CLS:
+ case H5I_GENPROP_LST:
+ case H5I_ERROR_CLASS:
+ case H5I_ERROR_MSG:
+ case H5I_ERROR_STACK:
+ case H5I_SPACE_SEL_ITER:
+ case H5I_NTYPES:
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "unknown data object type")
+ } /* end switch */
+
+ /* Set the return value */
+ ret_value = H5VL_object_data(vol_obj);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__object() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_object
+ *
+ * Purpose: Utility function to return the VOL object pointer associated with
+ * a hid_t.
+ *
+ * Return: Success: object pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_object(hid_t id)
+{
+ void *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Get the underlying object */
+ if(NULL == (ret_value = H5VL__object(id, H5I_get_type(id))))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "can't retrieve object for ID")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_object() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_object_verify
+ *
+ * Purpose: Utility function to return the VOL object pointer associated
+ * with an identifier.
+ *
+ * Return: Success: object pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_object_verify(hid_t id, H5I_type_t obj_type)
+{
+ void *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Check of ID of correct type */
+ if(obj_type != H5I_get_type(id))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "invalid identifier")
+
+ /* Get the underlying object */
+ if(NULL == (ret_value = H5VL__object(id, obj_type)))
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, NULL, "can't retrieve object for ID")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_object_verify() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_cmp_connector_cls
+ *
+ * Purpose: Compare VOL class for a connector
+ *
+ * Note: Sets *cmp_value positive if VALUE1 is greater than VALUE2,
+ * negative if VALUE2 is greater than VALUE1, and zero if VALUE1
+ * and VALUE2 are equal (like strcmp).
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_cmp_connector_cls(int *cmp_value, const H5VL_class_t *cls1, const H5VL_class_t *cls2)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cls1);
+ HDassert(cls2);
+
+ /* If the pointers are the same the classes are the same */
+ if(cls1 == cls2) {
+ *cmp_value = 0;
+ HGOTO_DONE(SUCCEED);
+ } /* end if */
+
+ /* Compare connector "values" */
+ if(cls1->value < cls2->value) {
+ *cmp_value = -1;
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ if(cls1->value > cls2->value) {
+ *cmp_value = 1;
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ HDassert(cls1->value == cls2->value);
+
+ /* Compare connector names */
+ if(cls1->name == NULL && cls2->name != NULL) {
+ *cmp_value = -1;
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ if(cls1->name != NULL && cls2->name == NULL) {
+ *cmp_value = 1;
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ if(0 != (*cmp_value = HDstrcmp(cls1->name, cls2->name)))
+ HGOTO_DONE(SUCCEED)
+
+ /* Compare connector VOL API versions */
+ if(cls1->version < cls2->version) {
+ *cmp_value = -1;
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ if(cls1->version > cls2->version) {
+ *cmp_value = 1;
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ HDassert(cls1->version == cls2->version);
+
+ /* Compare connector info */
+ if(cls1->info_cls.size < cls2->info_cls.size) {
+ *cmp_value = -1;
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ if(cls1->info_cls.size > cls2->info_cls.size) {
+ *cmp_value = 1;
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ HDassert(cls1->info_cls.size == cls2->info_cls.size);
+
+ /* Set comparison value to 'equal' */
+ *cmp_value = 0;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_cmp_connector_cls() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_retrieve_lib_state
+ *
+ * Purpose: Retrieve the state of the library.
+ *
+ * Note: Currently just retrieves the API context state, but could be
+ * expanded in the future.
+ *
+ * Return: Success: Non-negative, *state set
+ * Failure: Negative, *state unset
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_retrieve_lib_state(void **state)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(state);
+
+ /* Retrieve the API context state */
+ if(H5CX_retrieve_state((H5CX_state_t **)state) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get API context state")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_retrieve_lib_state() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_restore_lib_state
+ *
+ * Purpose: Restore the state of the library.
+ *
+ * Note: Currently just restores the API context state, but could be
+ * expanded in the future.
+ *
+ * Return: SUCCEED / FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, January 10, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_restore_lib_state(const void *state)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(state);
+
+ /* Push a new API context on the stack */
+ if(H5CX_push() < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't push API context")
+
+ /* Restore the API context state */
+ if(H5CX_restore_state((const H5CX_state_t *)state) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set API context state")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_restore_lib_state() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_reset_lib_state
+ *
+ * Purpose: Reset the state of the library, undoing affects of
+ * H5VL_restore_lib_state.
+ *
+ * Note: Currently just resets the API context state, but could be
+ * expanded in the future.
+ *
+ * Note: This routine must be called as a "pair" with
+ * H5VL_restore_lib_state. It can be called before / after /
+ * independently of H5VL_free_lib_state.
+ *
+ * Return: SUCCEED / FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, February 23, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_reset_lib_state(void)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Pop the API context off the stack */
+ if(H5CX_pop() < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRESET, FAIL, "can't pop API context")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_reset_lib_state() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_free_lib_state
+ *
+ * Purpose: Free a library state.
+ *
+ * Note: This routine must be called as a "pair" with
+ * H5VL_retrieve_lib_state.
+ *
+ * Return: SUCCEED / FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, January 10, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_free_lib_state(void *state)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(state);
+
+ /* Free the API context state */
+ if(H5CX_free_state((H5CX_state_t *)state) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "can't free API context state")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_free_lib_state() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__free_vol_wrapper
+ *
+ * Purpose: Free object wrapping context for VOL connector
+ *
+ * Return: SUCCEED / FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, January 9, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__free_vol_wrapper(H5VL_wrap_ctx_t *vol_wrap_ctx)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(vol_wrap_ctx);
+ HDassert(0 == vol_wrap_ctx->rc);
+ HDassert(vol_wrap_ctx->connector);
+ HDassert(vol_wrap_ctx->connector->cls);
+
+ /* If there is a VOL connector object wrapping context, release it */
+ if(vol_wrap_ctx->obj_wrap_ctx)
+ /* Release the VOL connector's object wrapping context */
+ if((*vol_wrap_ctx->connector->cls->wrap_cls.free_wrap_ctx)(vol_wrap_ctx->obj_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to release connector's object wrapping context")
+
+ /* Decrement refcount on connector */
+ if(H5VL__conn_dec_rc(vol_wrap_ctx->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to decrement ref count on VOL connector")
+
+ /* Release object wrapping context */
+ H5FL_FREE(H5VL_wrap_ctx_t, vol_wrap_ctx);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__free_vol_wrapper() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_set_vol_wrapper
+ *
+ * Purpose: Set up object wrapping context for current VOL connector
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_set_vol_wrapper(const H5VL_object_t *vol_obj)
+{
+ H5VL_wrap_ctx_t *vol_wrap_ctx = NULL; /* Object wrapping context */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(vol_obj);
+
+ /* Retrieve the VOL object wrap context */
+ if(H5CX_get_vol_wrap_ctx((void **)&vol_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get VOL object wrap context")
+
+ /* Check for existing wrapping context */
+ if(NULL == vol_wrap_ctx) {
+ void *obj_wrap_ctx = NULL; /* VOL connector's wrapping context */
+
+ /* Sanity checks */
+ HDassert(vol_obj->data);
+ HDassert(vol_obj->connector);
+
+ /* Check if the connector can create a wrap context */
+ if(vol_obj->connector->cls->wrap_cls.get_wrap_ctx) {
+ /* Sanity check */
+ HDassert(vol_obj->connector->cls->wrap_cls.free_wrap_ctx);
+
+ /* Get the wrap context from the connector */
+ if((vol_obj->connector->cls->wrap_cls.get_wrap_ctx)(vol_obj->data, &obj_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't retrieve VOL connector's object wrap context")
+ } /* end if */
+
+ /* Allocate VOL object wrapper context */
+ if(NULL == (vol_wrap_ctx = H5FL_MALLOC(H5VL_wrap_ctx_t)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, FAIL, "can't allocate VOL wrap context")
+
+ /* Increment the outstanding objects that are using the connector */
+ H5VL__conn_inc_rc(vol_obj->connector);
+
+ /* Set up VOL object wrapper context */
+ vol_wrap_ctx->rc = 1;
+ vol_wrap_ctx->connector = vol_obj->connector;
+ vol_wrap_ctx->obj_wrap_ctx = obj_wrap_ctx;
+ } /* end if */
+ else
+ /* Incremeent ref count on existing wrapper context */
+ vol_wrap_ctx->rc++;
+
+ /* Save the wrapper context */
+ if(H5CX_set_vol_wrap_ctx(vol_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL object wrap context")
+
+done:
+ if(ret_value < 0 && vol_wrap_ctx)
+ /* Release object wrapping context */
+ H5FL_FREE(H5VL_wrap_ctx_t, vol_wrap_ctx);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_set_vol_wrapper() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_inc_vol_wrapper
+ *
+ * Purpose: Increment refcount on object wrapping context
+ *
+ * Return: SUCCEED / FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, January 9, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_inc_vol_wrapper(void *_vol_wrap_ctx)
+{
+ H5VL_wrap_ctx_t *vol_wrap_ctx = (H5VL_wrap_ctx_t *)_vol_wrap_ctx; /* VOL object wrapping context */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check for valid, active VOL object wrap context */
+ if(NULL == vol_wrap_ctx)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "no VOL object wrap context?")
+ if(0 == vol_wrap_ctx->rc)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "bad VOL object wrap context refcount?")
+
+ /* Increment ref count on wrapping context */
+ vol_wrap_ctx->rc++;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_inc_vol_wrapper() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_dec_vol_wrapper
+ *
+ * Purpose: Decrement refcount on object wrapping context, releasing it
+ * if the refcount drops to zero.
+ *
+ * Return: SUCCEED / FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, January 9, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_dec_vol_wrapper(void *_vol_wrap_ctx)
+{
+ H5VL_wrap_ctx_t *vol_wrap_ctx = (H5VL_wrap_ctx_t *)_vol_wrap_ctx; /* VOL object wrapping context */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check for valid, active VOL object wrap context */
+ if(NULL == vol_wrap_ctx)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "no VOL object wrap context?")
+ if(0 == vol_wrap_ctx->rc)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "bad VOL object wrap context refcount?")
+
+ /* Decrement ref count on wrapping context */
+ vol_wrap_ctx->rc--;
+
+ /* Release context if the ref count drops to zero */
+ if(0 == vol_wrap_ctx->rc)
+ if(H5VL__free_vol_wrapper(vol_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to release VOL object wrapping context")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_dec_vol_wrapper() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_reset_vol_wrapper
+ *
+ * Purpose: Reset object wrapping context for current VOL connector
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_reset_vol_wrapper(void)
+{
+ H5VL_wrap_ctx_t *vol_wrap_ctx = NULL; /* Object wrapping context */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Retrieve the VOL object wrap context */
+ if(H5CX_get_vol_wrap_ctx((void **)&vol_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get VOL object wrap context")
+
+ /* Check for VOL object wrap context */
+ if(NULL == vol_wrap_ctx)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "no VOL object wrap context?")
+
+ /* Decrement ref count on wrapping context */
+ vol_wrap_ctx->rc--;
+
+ /* Release context if the ref count drops to zero */
+ if(0 == vol_wrap_ctx->rc) {
+ /* Release object wrapping context */
+ if(H5VL__free_vol_wrapper(vol_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to release VOL object wrapping context")
+
+ /* Reset the wrapper context */
+ if(H5CX_set_vol_wrap_ctx(NULL) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL object wrap context")
+ } /* end if */
+ else
+ /* Save the updated wrapper context */
+ if(H5CX_set_vol_wrap_ctx(vol_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL object wrap context")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_reset_vol_wrapper() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_wrap_register
+ *
+ * Purpose: Wrap an object and register an ID for it
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL_wrap_register(H5I_type_t type, void *obj, hbool_t app_ref)
+{
+ H5VL_wrap_ctx_t *vol_wrap_ctx = NULL; /* Object wrapping context */
+ void *new_obj; /* Newly wrapped object */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5I_INVALID_HID)
+
+ /* Sanity check */
+ HDassert(obj);
+
+ /* If the datatype is already VOL-managed, the datatype's vol_obj
+ * field will get clobbered later, so disallow this.
+ */
+ if(type == H5I_DATATYPE)
+ if(TRUE == H5T_already_vol_managed((const H5T_t *)obj))
+ HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, H5I_INVALID_HID, "can't wrap an uncommitted datatype")
+
+ /* Wrap the object with VOL connector info */
+ if(NULL == (new_obj = H5VL__wrap_obj(obj, type)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, H5I_INVALID_HID, "can't wrap library object")
+
+ /* Retrieve the VOL object wrapping context */
+ if(H5CX_get_vol_wrap_ctx((void **)&vol_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, H5I_INVALID_HID, "can't get VOL object wrap context")
+ if(NULL == vol_wrap_ctx || NULL == vol_wrap_ctx->connector)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, H5I_INVALID_HID, "VOL object wrap context or its connector is NULL???")
+
+ /* Get an ID for the object */
+ if((ret_value = H5VL_register_using_vol_id(type, new_obj, vol_wrap_ctx->connector->id, app_ref)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to get an ID for the object")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_wrap_register() */
+