summaryrefslogtreecommitdiffstats
path: root/src/H5VLint.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5VLint.c')
-rw-r--r--src/H5VLint.c1114
1 files changed, 1114 insertions, 0 deletions
diff --git a/src/H5VLint.c b/src/H5VLint.c
new file mode 100644
index 0000000..82886cd
--- /dev/null
+++ b/src/H5VLint.c
@@ -0,0 +1,1114 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 "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 */
+
+
+/****************/
+/* 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 */
+ const H5VL_t *connector; /* VOL connector for "outermost" class to start wrap */
+ void *obj_wrap_ctx; /* "wrap context" for outermost connector */
+} H5VL_wrap_ctx_t;
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+static herr_t H5VL__free_cls(H5VL_class_t *cls);
+static void *H5VL__wrap_obj(void *obj);
+static H5VL_object_t *H5VL__new_vol_obj(H5I_type_t type, void *object,
+ H5VL_t *vol_connector, hbool_t wrap_obj);
+static void *H5VL__object(hid_t id, H5I_type_t obj_type);
+
+
+/*********************/
+/* 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);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_init
+ *
+ * Purpose: Initialize the interface from some other package
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_init(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() */
+
+
+/*-------------------------------------------------------------------------
+ * 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 (H5I_nmembers(H5I_VOL) > 0) {
+ (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 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((void *)cls->name); /* Casting away const OK -QAK */
+ H5FL_FREE(H5VL_class_t, cls);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__free_cls() */
+
+
+/*-------------------------------------------------------------------------
+ * 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)
+{
+ 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)))
+ 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 */
+ 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)
+ 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)))
+ 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 */
+ vol_connector->nrefs++;
+
+ /* 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:
+ 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 *info)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ if(info) {
+ /* 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")
+
+ /* Free the connector info */
+ if(H5VL_free_connector_info(connector, (void *)info->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)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "can't decrement reference count for connector ID")
+ } /* end if */
+ } /* end if */
+
+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;
+ H5VL_t *connector = NULL; /* VOL connector struct */
+ hid_t ret_value = H5I_INVALID_HID;
+
+ 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")
+
+ /* 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:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_register_using_vol_id() */
+
+
+/*-------------------------------------------------------------------------
+ * 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;
+
+ FUNC_ENTER_NOAPI(SUCCEED)
+
+ /* Check arguments */
+ HDassert(vol_obj);
+
+ vol_obj->connector->nrefs --;
+
+ if(0 == vol_obj->connector->nrefs) {
+ if(H5I_dec_ref(vol_obj->connector->id) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to decrement ref count on VOL connector")
+ vol_obj->connector = H5FL_FREE(H5VL_t, vol_obj->connector);
+ } /* end if */
+
+ vol_obj = H5FL_FREE(H5VL_object_t, vol_obj);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_free_object() */
+
+
+/*-------------------------------------------------------------------------
+ * 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
+ *
+ *-------------------------------------------------------------------------
+ */
+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_CALLOC(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)))
+ 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)
+ if (saved)
+ H5FL_FREE(H5VL_class_t, saved);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_register_connector() */
+
+
+/*-------------------------------------------------------------------------
+ * 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_NOAPI(FAIL)
+
+ /* 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->get_object)
+ ret_value = (vol_obj->connector->cls->get_object)(vol_obj->data);
+ else
+ ret_value = vol_obj->data;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_object_data() */
+
+
+/*-------------------------------------------------------------------------
+ * 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:
+ /* 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_REFERENCE:
+ 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_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_ARGS, 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
+ *
+ * Return: Positive if VALUE1 is greater than VALUE2, negative if
+ * VALUE2 is greater than VALUE1 and zero if VALUE1 and
+ * VALUE2 are equal.
+ *
+ *-------------------------------------------------------------------------
+ */
+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);
+
+ /* 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_size < cls2->info_size) {
+ *cmp_value = -1;
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ if(cls1->info_size > cls2->info_size) {
+ *cmp_value = 1;
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ HDassert(cls1->info_size == cls2->info_size);
+
+ /* Set comparison value to 'equal' */
+ *cmp_value = 0;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_cmp_connector_cls() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_set_vol_wrapper
+ *
+ * Purpose: Set up object wrapping context for current VOL connector
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_set_vol_wrapper(void *obj, const H5VL_t *connector)
+{
+ H5VL_wrap_ctx_t *vol_wrap_ctx = NULL; /* Object wrapping context */
+ void *obj_wrap_ctx = NULL; /* VOL connector's wrapping context */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(obj);
+ HDassert(connector);
+
+ /* 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) {
+ /* Check if the connector can create a wrap context */
+ if(connector->cls->get_wrap_ctx) {
+ /* Sanity check */
+ HDassert(connector->cls->free_wrap_ctx);
+
+ /* Get the wrap context from the connector */
+ if((connector->cls->get_wrap_ctx)(obj, &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")
+
+ /* Set up VOL object wrapper context */
+ vol_wrap_ctx->rc = 1;;
+ vol_wrap_ctx->connector = 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_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) {
+ /* 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->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")
+ } /* end if */
+
+ /* Release object wrapping context */
+ H5FL_FREE(H5VL_wrap_ctx_t, vol_wrap_ctx);
+
+ /* 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")
+ } /* end else */
+
+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)))
+ 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() */
+