diff options
Diffstat (limited to 'src/H5VLint.c')
-rw-r--r-- | src/H5VLint.c | 1853 |
1 files changed, 1364 insertions, 489 deletions
diff --git a/src/H5VLint.c b/src/H5VLint.c index f9262f4..2bd5b36 100644 --- a/src/H5VLint.c +++ b/src/H5VLint.c @@ -5,7 +5,7 @@ * 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. * + * distribution tree, or in https://www.hdfgroup.org/licenses. * * If you do not have access to either file, you may request a copy from * * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -17,47 +17,49 @@ * 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 */ - +#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 "H5PLprivate.h" /* Plugins */ -#include "H5Tprivate.h" /* Datatypes */ -#include "H5VLpkg.h" /* Virtual Object Layer */ +#include "H5private.h" /* Generic Functions */ +#include "H5Aprivate.h" /* Attributes */ +#include "H5CXprivate.h" /* API Contexts */ +#include "H5Dprivate.h" /* Datasets */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5ESprivate.h" /* Event sets */ +#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 */ - +#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 */ + 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. @@ -68,60 +70,45 @@ typedef struct H5VL_wrap_ctx_t { */ 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; + H5PL_vol_key_t key; /* OUT */ - hid_t found_id; /* The connector ID, if we found a match */ + 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); - +static herr_t H5VL__free_cls(H5VL_class_t *cls, void **request); +static int H5VL__get_connector_cb(void *obj, hid_t id, void *_op_data); +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 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 */ + 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 */ @@ -139,8 +126,6 @@ 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 * @@ -158,17 +143,18 @@ static H5VL_connector_prop_t H5VL_def_conn_s = {-1, NULL}; herr_t H5VL_init_phase1(void) { - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) - /* FUNC_ENTER() does all the work */ + /* Initialize the ID 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_phase1() */ - /*------------------------------------------------------------------------- * Function: H5VL_init_phase2 * @@ -185,46 +171,51 @@ done: herr_t H5VL_init_phase2(void) { - herr_t ret_value = SUCCEED; /* Return value */ + size_t i; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) + /* clang-format off */ + struct { + herr_t (*func)(void); + const char *descr; + } initializer[] = { + {H5T_init, "datatype"} + , {H5O_init, "object header"} + , {H5D_init, "dataset"} + , {H5F_init, "file"} + , {H5G_init, "group"} + , {H5A_init, "attribute"} + , {H5M_init, "map"} + , {H5CX_init, "context"} + , {H5ES_init, "event set"} + , {H5Z_init, "transform"} + , {H5R_init, "reference"} + }; + + /* Initialize all packages for VOL-managed objects */ + for (i = 0; i < NELMTS(initializer); i++) { + if (initializer[i].func() < 0) { + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, + "unable to initialize %s interface", initializer[i].descr) + } + } + + /* clang-format on */ + + /* Sanity check default VOL connector */ + HDassert(H5VL_def_conn_s.connector_id == (-1)); + HDassert(H5VL_def_conn_s.connector_info == NULL); + /* Set up the default VOL connector in the default FAPL */ - if(H5VL__set_def_conn() < 0) + 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 * @@ -239,39 +230,39 @@ done: int H5VL_term_package(void) { - int n = 0; + 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; + 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 { - if(H5I_nmembers(H5I_VOL) > 0) { - /* Unregister all VOL connectors */ - (void)H5I_clear_type(H5I_VOL, FALSE, FALSE); + if (H5VL__num_opt_operation() > 0) { + /* Unregister all dynamically registered optional operations */ + (void)H5VL__term_opt_operation(); 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 */ + } /* end else */ + } /* end else */ FUNC_LEAVE_NOAPI(n) } /* end H5VL_term_package() */ - /*------------------------------------------------------------------------- * Function: H5VL__free_cls * @@ -285,28 +276,27 @@ H5VL_term_package(void) *------------------------------------------------------------------------- */ static herr_t -H5VL__free_cls(H5VL_class_t *cls) +H5VL__free_cls(H5VL_class_t *cls, void H5_ATTR_UNUSED **request) { herr_t ret_value = SUCCEED; - FUNC_ENTER_STATIC + FUNC_ENTER_PACKAGE /* Sanity check */ HDassert(cls); /* Shut down the VOL connector */ - if(cls->terminate && cls->terminate() < 0) + 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 */ + 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 * @@ -324,30 +314,29 @@ done: 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 */ + 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 + FUNC_ENTER_PACKAGE_NOERR - if(H5VL_GET_CONNECTOR_BY_NAME == op_data->kind) { - if(0 == HDstrcmp(cls->name, op_data->u.name)) { + if (H5VL_GET_CONNECTOR_BY_NAME == op_data->key.kind) { + if (0 == HDstrcmp(cls->name, op_data->key.u.name)) { op_data->found_id = id; - ret_value = H5_ITER_STOP; + ret_value = H5_ITER_STOP; } /* end if */ - } /* end if */ + } /* end if */ else { - HDassert(H5VL_GET_CONNECTOR_BY_VALUE == op_data->kind); - if(cls->value == op_data->u.value) { + HDassert(H5VL_GET_CONNECTOR_BY_VALUE == op_data->key.kind); + if (cls->value == op_data->key.u.value) { op_data->found_id = id; - ret_value = H5_ITER_STOP; + ret_value = H5_ITER_STOP; } /* end if */ - } /* end else */ + } /* end else */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL__get_connector_cb() */ - /*------------------------------------------------------------------------- * Function: H5VL__set_def_conn * @@ -365,114 +354,121 @@ H5VL__get_connector_cb(void *obj, hid_t id, void *_op_data) * *------------------------------------------------------------------------- */ -static herr_t +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 */ + 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 + FUNC_ENTER_PACKAGE - /* Sanity check */ - HDassert(H5VL_def_conn_s.connector_id == (-1)); - HDassert(H5VL_def_conn_s.connector_info == NULL); + /* Reset default VOL connector, if it's set already */ + /* (Can happen during testing -QAK) */ + 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; + } /* end if */ /* Check for environment variable set */ - env_var = HDgetenv("HDF5_VOL_CONNECTOR"); + 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 */ + 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))) + 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))) + if (NULL == (tok = HDstrtok_r(buf, " \t\n\r", &lasts))) HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "VOL connector environment variable set empty?") /* First, check to see if the connector is already registered */ - if((connector_is_registered = H5VL__is_connector_registered(tok)) < 0) + 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) { + else if (connector_is_registered) { /* Retrieve the ID of the already-registered VOL connector */ - if((connector_id = H5VL__get_connector_id(tok, FALSE)) < 0) + 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")) { + if (!HDstrcmp(tok, "native")) { connector_id = H5VL_NATIVE; - if(H5I_inc_ref(connector_id, FALSE) < 0) + 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")) { + else if (!HDstrcmp(tok, "pass_through")) { connector_id = H5VL_PASSTHRU; - if(H5I_inc_ref(connector_id, FALSE) < 0) + if (H5I_inc_ref(connector_id, FALSE) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTINC, FAIL, "can't increment VOL connector refcount") } /* end else-if */ else { /* Register the VOL connector */ /* (NOTE: No provisions for vipl_id currently) */ - if((connector_id = H5VL__register_connector_by_name(tok, FALSE, H5P_DEFAULT)) < 0) + 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 */ + } /* 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) + 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_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_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) + 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") + if (NULL == (def_fapclass = (H5P_genclass_t *)H5I_object(H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_VOL, H5E_BADID, 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") + 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") + if (NULL == (def_fapl = (H5P_genplist_t *)H5I_object(H5P_FILE_ACCESS_DEFAULT))) + HGOTO_ERROR(H5E_VOL, H5E_BADID, 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) + 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) + 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) + if (connector_id >= 0) /* The H5VL_class_t struct will be freed by this function */ - if(H5I_dec_ref(connector_id) < 0) + if (H5I_dec_ref(connector_id) < 0) HDONE_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to unregister VOL connector") } /* end if */ @@ -482,7 +478,6 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL__set_def_conn() */ - /*------------------------------------------------------------------------- * Function: H5VL__wrap_obj * @@ -500,22 +495,23 @@ done: 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 */ + H5VL_wrap_ctx_t *vol_wrap_ctx = NULL; /* Object wrapping context */ + void * ret_value = NULL; /* Return value */ - FUNC_ENTER_STATIC + FUNC_ENTER_PACKAGE /* Check arguments */ HDassert(obj); /* Retrieve the VOL object wrapping context */ - if(H5CX_get_vol_wrap_ctx((void **)&vol_wrap_ctx) < 0) + 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) { + 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))) + 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 @@ -525,7 +521,6 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL__wrap_obj() */ - /*------------------------------------------------------------------------- * Function: H5VL__new_vol_obj * @@ -542,47 +537,55 @@ done: 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 */ + 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 + FUNC_ENTER_PACKAGE /* 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) + 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))) + 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))) + 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; + new_vol_obj->rc = 1; /* Bump the reference count on the VOL connector */ - H5VL__conn_inc_rc(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))) + 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 * @@ -598,41 +601,41 @@ done: herr_t H5VL_conn_copy(H5VL_connector_prop_t *connector_prop) { - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) - if(connector_prop) { + if (connector_prop) { /* Copy the connector ID & info, if there is one */ - if(connector_prop->connector_id > 0) { + 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) + 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 */ + 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))) + 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) + 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 */ + } /* end if */ + } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_conn_copy() */ - /*------------------------------------------------------------------------- * Function: H5VL_conn_free * @@ -646,29 +649,29 @@ done: herr_t H5VL_conn_free(const H5VL_connector_prop_t *connector_prop) { - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) - if(connector_prop) { + 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) + if (connector_prop->connector_id > 0) { + if (connector_prop->connector_info) /* Free the connector info */ - if(H5VL_free_connector_info(connector_prop->connector_id, (void *)connector_prop->connector_info) < 0) /* Casting away const OK - QAK */ + 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) + if (H5I_dec_ref(connector_prop->connector_id) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "can't decrement reference count for connector ID") - } /* end if */ - } /* end if */ + } + } done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_conn_free() */ - /*------------------------------------------------------------------------- * Function: H5VL_register * @@ -684,8 +687,8 @@ done: 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 */ + 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) @@ -695,24 +698,23 @@ H5VL_register(H5I_type_t type, void *object, H5VL_t *vol_connector, hbool_t app_ /* 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))) + 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") + if ((ret_value = H5I_register(type, vol_obj, app_ref)) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register 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, + * 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). @@ -726,10 +728,11 @@ done: *------------------------------------------------------------------------- */ 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_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 */ + H5VL_object_t *new_vol_obj = NULL; /* Pointer to new VOL object */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -739,18 +742,68 @@ H5VL_register_using_existing_id(H5I_type_t type, void *object, H5VL_t *vol_conne /* 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))) + 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) + 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_new_connector + * + * Purpose: Utility function to create a connector for a connector ID. + * + * Return: Success: Pointer to a new connector object + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +H5VL_t * +H5VL_new_connector(hid_t connector_id) +{ + H5VL_class_t *cls = NULL; /* VOL connector class */ + H5VL_t * connector = NULL; /* New VOL connector struct */ + hbool_t conn_id_incr = FALSE; /* Whether the VOL connector ID has been incremented */ + H5VL_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 connector 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 return value */ + ret_value = connector; + +done: + /* Clean up on error */ + if (NULL == 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_new_connector() */ + /*------------------------------------------------------------------------- * Function: H5VL_register_using_vol_id * @@ -759,42 +812,134 @@ done: * get the connector information instead of it being passed in. * * Return: Success: A valid HDF5 ID - * Failure: H5I_INVALID_HID + * 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; + H5VL_t *connector = NULL; /* VOL connector struct */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ FUNC_ENTER_NOAPI(FAIL) + /* Create new VOL connector object, using the connector ID */ + if (NULL == (connector = H5VL_new_connector(connector_id))) + HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, H5I_INVALID_HID, "can't create VOL connector object") + + /* 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 (H5I_INVALID_HID == ret_value) + /* Release newly created connector */ + if (connector && H5VL_conn_dec_rc(connector) < 0) + HDONE_ERROR(H5E_VOL, H5E_CANTDEC, H5I_INVALID_HID, + "unable to decrement ref count on VOL connector") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_register_using_vol_id() */ + +/*------------------------------------------------------------------------- + * Function: H5VL_create_object + * + * Purpose: Similar to H5VL_register but does not create an ID. + * Creates a new VOL object for the provided generic object + * using the provided vol connector. Should only be used for + * internal objects returned from the connector such as + * requests. + * + * Return: Success: A valid VOL object + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +H5VL_object_t * +H5VL_create_object(void *object, H5VL_t *vol_connector) +{ + H5VL_object_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI(NULL) + + /* 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 == (ret_value = H5FL_CALLOC(H5VL_object_t))) + HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, NULL, "can't allocate memory for VOL object") + ret_value->connector = vol_connector; + ret_value->data = object; + ret_value->rc = 1; + + /* Bump the reference count on the VOL connector */ + H5VL_conn_inc_rc(vol_connector); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_create_object() */ + +/*------------------------------------------------------------------------- + * 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, H5I_INVALID_HID, "not a VOL connector 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, H5I_INVALID_HID, "can't allocate 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, H5I_INVALID_HID, "unable to increment ref count on VOL connector") + 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; - /* 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") + /* 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_register_using_vol_id() */ +} /* end H5VL_create_object_using_vol_id() */ - /*------------------------------------------------------------------------- - * Function: H5VL__conn_inc_rc + * Function: H5VL_conn_inc_rc * * Purpose: Wrapper to increment the ref. count on a connector. * @@ -805,10 +950,12 @@ done: * *------------------------------------------------------------------------- */ -static int64_t -H5VL__conn_inc_rc(H5VL_t *connector) +int64_t +H5VL_conn_inc_rc(H5VL_t *connector) { - FUNC_ENTER_STATIC_NOERR + int64_t ret_value = -1; + + FUNC_ENTER_NOAPI_NOERR /* Check arguments */ HDassert(connector); @@ -816,12 +963,13 @@ H5VL__conn_inc_rc(H5VL_t *connector) /* Increment refcount for connector */ connector->nrefs++; - FUNC_LEAVE_NOAPI(connector->nrefs) -} /* end H5VL__conn_inc_rc() */ + ret_value = connector->nrefs; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_conn_inc_rc() */ - /*------------------------------------------------------------------------- - * Function: H5VL__conn_dec_rc + * Function: H5VL_conn_dec_rc * * Purpose: Wrapper to decrement the ref. count on a connector. * @@ -832,12 +980,12 @@ H5VL__conn_inc_rc(H5VL_t *connector) * *------------------------------------------------------------------------- */ -static int64_t -H5VL__conn_dec_rc(H5VL_t *connector) +int64_t +H5VL_conn_dec_rc(H5VL_t *connector) { - int64_t ret_value = -1; /* Return value */ + int64_t ret_value = -1; /* Return value */ - FUNC_ENTER_STATIC + FUNC_ENTER_NOAPI(-1) /* Check arguments */ HDassert(connector); @@ -846,8 +994,8 @@ H5VL__conn_dec_rc(H5VL_t *connector) connector->nrefs--; /* Check for last reference */ - if(0 == connector->nrefs) { - if(H5I_dec_ref(connector->id) < 0) + 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); @@ -860,9 +1008,29 @@ H5VL__conn_dec_rc(H5VL_t *connector) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5VL__conn_dec_rc() */ +} /* end H5VL_conn_dec_rc() */ + +/*------------------------------------------------------------------------- + * Function: H5VL_object_inc_rc + * + * Purpose: Wrapper to increment the ref count on a VOL object. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +hsize_t +H5VL_object_inc_rc(H5VL_object_t *vol_obj) +{ + FUNC_ENTER_NOAPI_NOERR_NOFS + + /* Check arguments */ + HDassert(vol_obj); + + /* Increment refcount for object and return */ + FUNC_LEAVE_NOAPI(++vol_obj->rc) +} /* end H5VL_object_inc_rc() */ - /*------------------------------------------------------------------------- * Function: H5VL_free_object * @@ -876,26 +1044,138 @@ done: herr_t H5VL_free_object(H5VL_object_t *vol_obj) { - herr_t ret_value = SUCCEED; /* Return value */ + 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") + if (--vol_obj->rc == 0) { + /* 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); + vol_obj = H5FL_FREE(H5VL_object_t, vol_obj); + } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_free_object() */ - /*------------------------------------------------------------------------- - * Function: H5VL_register_connector + * 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 */ + H5VL_file_specific_args_t vol_cb_args; /* Arguments to VOL callback */ + + /* 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") + + /* Set up VOL callback arguments */ + vol_cb_args.op_type = H5VL_FILE_IS_EQUAL; + vol_cb_args.args.is_equal.obj2 = obj2; + vol_cb_args.args.is_equal.same_file = same_file; + + /* Make 'are files equal' callback */ + if (H5VL_file_specific(vol_obj1, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, NULL) < 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. @@ -903,7 +1183,7 @@ done: * Return: Success: A VOL connector ID which is good until the * library is closed or the connector is unregistered. * - * Failure: H5I_INVALID_HID + * Failure: H5I_INVALID_HID * * Programmer: Dana Robinson * June 22, 2017 @@ -911,46 +1191,47 @@ done: *------------------------------------------------------------------------- */ hid_t -H5VL_register_connector(const void *_cls, hbool_t app_ref, hid_t vipl_id) +H5VL__register_connector(const void *_cls, hbool_t app_ref, hid_t vipl_id) { - const H5VL_class_t *cls = (const H5VL_class_t *)_cls; - H5VL_class_t *saved = NULL; - hid_t ret_value = H5I_INVALID_HID; + const H5VL_class_t *cls = (const H5VL_class_t *)_cls; + H5VL_class_t * saved = NULL; + hid_t ret_value = H5I_INVALID_HID; - FUNC_ENTER_NOAPI(H5I_INVALID_HID) + FUNC_ENTER_PACKAGE /* Check arguments */ HDassert(cls); /* 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") + 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") + 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) + 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) + 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((void *)(saved->name)); /* Casting away const OK -QAK */ + 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() */ +} /* end H5VL__register_connector() */ - /*------------------------------------------------------------------------- - * Function: H5VL__register_connector + * Function: H5VL__register_connector_by_class * * Purpose: Registers a new VOL connector as a member of the virtual object * layer class. @@ -967,39 +1248,60 @@ done: *------------------------------------------------------------------------- */ hid_t -H5VL__register_connector(const H5VL_class_t *cls, hbool_t app_ref, hid_t vipl_id) +H5VL__register_connector_by_class(const H5VL_class_t *cls, hbool_t app_ref, hid_t vipl_id) { - H5VL_get_connector_ud_t op_data; /* Callback info for connector search */ - hid_t ret_value = H5I_INVALID_HID; /* Return value */ + H5VL_get_connector_ud_t op_data; /* Callback info for connector search */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ FUNC_ENTER_PACKAGE + /* Check arguments */ + if (!cls) + HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID, + "VOL connector class pointer cannot be NULL") + if (H5VL_VERSION != cls->version) + HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "VOL connector has incompatible version") + if (!cls->name) + HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, + "VOL connector class name cannot be the NULL pointer") + if (0 == HDstrlen(cls->name)) + HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, + "VOL connector class name cannot be the empty string") + if (cls->info_cls.copy && !cls->info_cls.free) + HGOTO_ERROR( + H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, + "VOL connector must provide free callback for VOL info objects when a copy callback is provided") + if (cls->wrap_cls.get_wrap_ctx && !cls->wrap_cls.free_wrap_ctx) + HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, + "VOL connector must provide free callback for object wrapping contexts when a get " + "callback is provided") + /* Set up op data for iteration */ - op_data.kind = H5VL_GET_CONNECTOR_BY_NAME; - op_data.u.name = cls->name; - op_data.found_id = H5I_INVALID_HID; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_NAME; + op_data.key.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) + 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") + 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) + if ((ret_value = H5VL__register_connector(cls, app_ref, vipl_id)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector") } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5VL__register_connector() */ +} /* end H5VL__register_connector_by_class() */ - /*------------------------------------------------------------------------- * Function: H5VL__register_connector_by_name * @@ -1020,38 +1322,39 @@ done: 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 */ + 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; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_NAME; + op_data.key.u.name = name; + op_data.found_id = H5I_INVALID_HID; /* Check if connector is already registered */ - if(H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0) + 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") + /* If connector already 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; + H5PL_key_t key; const H5VL_class_t *cls; /* Try loading the connector */ - key.vol.kind = H5VL_GET_CONNECTOR_BY_NAME; + 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))) + 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) + 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 */ @@ -1059,7 +1362,6 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL__register_connector_by_name() */ - /*------------------------------------------------------------------------- * Function: H5VL__register_connector_by_value * @@ -1080,38 +1382,39 @@ done: 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 */ + 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; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_VALUE; + op_data.key.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) + 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") + /* If connector already 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; + H5PL_key_t key; const H5VL_class_t *cls; /* Try loading the connector */ - key.vol.kind = H5VL_GET_CONNECTOR_BY_VALUE; + 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))) + 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) + 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 */ @@ -1119,14 +1422,14 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL__register_connector_by_value() */ - /*------------------------------------------------------------------------- - * Function: H5VL__is_connector_registered + * Function: H5VL__is_connector_registered_by_name * * Purpose: Checks if a connector with a particular name is registered. * - * Return: Success: 0 - * Failure: -1 + * Return: >0 if a VOL connector with that name has been registered + * 0 if a VOL connector with that name has NOT been registered + * <0 on errors * * Programmer: Dana Robinson * June 17, 2017 @@ -1134,34 +1437,104 @@ done: *------------------------------------------------------------------------- */ htri_t -H5VL__is_connector_registered(const char *name) +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 */ + 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; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_NAME; + op_data.key.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) + 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: >0 if a VOL connector with that value has been registered + * 0 if a VOL connector with that value hasn't been registered + * <0 on errors + * + *------------------------------------------------------------------------- + */ +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.key.kind = H5VL_GET_CONNECTOR_BY_VALUE; + op_data.key.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) + if (op_data.found_id != H5I_INVALID_HID) ret_value = TRUE; done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5VL__is_connector_registered() */ +} /* 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 @@ -1173,34 +1546,126 @@ done: *------------------------------------------------------------------------- */ hid_t -H5VL__get_connector_id(const char *name, hbool_t is_api) +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 */ + 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; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_NAME; + op_data.key.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) + if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0) HGOTO_ERROR(H5E_VOL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VOL connectors") - /* Found a connector with that name */ - if(op_data.found_id != H5I_INVALID_HID) { - if(H5I_inc_ref(op_data.found_id, is_api) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector") - ret_value = op_data.found_id; - } /* end if */ + /* Set return value */ + ret_value = op_data.found_id; done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5VL__get_connector_id() */ +} /* 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.key.kind = H5VL_GET_CONNECTOR_BY_VALUE; + op_data.key.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 * @@ -1217,21 +1682,21 @@ done: herr_t H5VL__connector_str_to_info(const char *str, hid_t connector_id, void **info) { - herr_t ret_value = SUCCEED; /* Return value */ + 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 */ + 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))) + 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) + 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 @@ -1244,7 +1709,6 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL__connector_str_to_info() */ - /*------------------------------------------------------------------------- * Function: H5VL__get_connector_name * @@ -1258,8 +1722,8 @@ done: 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; + H5VL_object_t * vol_obj; + const H5VL_class_t *cls; size_t len; ssize_t ret_value = -1; @@ -1272,9 +1736,9 @@ H5VL__get_connector_name(hid_t id, char *name /*out*/, size_t size) cls = vol_obj->connector->cls; len = HDstrlen(cls->name); - if(name) { - HDstrncpy(name, cls->name, MIN(len + 1, size)); - if(len >= size) + if (name) { + HDstrncpy(name, cls->name, size); + if (len >= size) name[size - 1] = '\0'; } /* end if */ @@ -1285,13 +1749,12 @@ 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 + * except for named datatypes, where the vol_obj is returned that * is attached to the H5T_t struct. * * Return: Success: object pointer @@ -1302,20 +1765,20 @@ done: H5VL_object_t * H5VL_vol_object(hid_t id) { - void *obj = NULL; - H5I_type_t obj_type; - H5VL_object_t *ret_value = NULL; + 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) { + if (H5I_FILE == obj_type || H5I_GROUP == obj_type || H5I_ATTR == obj_type || H5I_DATASET == obj_type || + H5I_DATATYPE == obj_type || H5I_MAP == 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 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") @@ -1329,7 +1792,6 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_vol_object() */ - /*------------------------------------------------------------------------- * Function: H5VL_object_data * @@ -1349,7 +1811,7 @@ H5VL_object_data(const H5VL_object_t *vol_obj) FUNC_ENTER_NOAPI_NOINIT_NOERR /* Check for 'get_object' callback in connector */ - if(vol_obj->connector->cls->wrap_cls.get_object) + 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; @@ -1357,7 +1819,6 @@ H5VL_object_data(const H5VL_object_t *vol_obj) FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_object_data() */ - /*------------------------------------------------------------------------- * Function: H5VL_object_unwrap * @@ -1376,14 +1837,13 @@ H5VL_object_unwrap(const H5VL_object_t *vol_obj) FUNC_ENTER_NOAPI(NULL) - if(NULL == (ret_value = H5VL_unwrap_object(vol_obj->connector->cls, vol_obj->data))) + 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 * @@ -1398,16 +1858,16 @@ done: static void * H5VL__object(hid_t id, H5I_type_t obj_type) { - H5VL_object_t *vol_obj = NULL; - void *ret_value = NULL; + H5VL_object_t *vol_obj = NULL; + void * ret_value = NULL; - FUNC_ENTER_STATIC + FUNC_ENTER_PACKAGE /* Get the underlying object */ - switch(obj_type) { + switch (obj_type) { case H5I_GROUP: case H5I_DATASET: - case H5I_FILE: + case H5I_FILE: case H5I_ATTR: case H5I_MAP: /* get the object */ @@ -1415,19 +1875,18 @@ H5VL__object(hid_t id, H5I_type_t obj_type) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "invalid identifier") break; - case H5I_DATATYPE: - { - H5T_t *dt = NULL; + 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 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; - } + /* 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: @@ -1440,6 +1899,7 @@ H5VL__object(hid_t id, H5I_type_t obj_type) case H5I_ERROR_MSG: case H5I_ERROR_STACK: case H5I_SPACE_SEL_ITER: + case H5I_EVENTSET: case H5I_NTYPES: default: HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "unknown data object type") @@ -1452,7 +1912,6 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL__object() */ - /*------------------------------------------------------------------------- * Function: H5VL_object * @@ -1467,19 +1926,18 @@ done: void * H5VL_object(hid_t id) { - void *ret_value = NULL; + void *ret_value = NULL; FUNC_ENTER_NOAPI(NULL) /* Get the underlying object */ - if(NULL == (ret_value = H5VL__object(id, H5I_get_type(id)))) + 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 * @@ -1494,23 +1952,22 @@ done: void * H5VL_object_verify(hid_t id, H5I_type_t obj_type) { - void *ret_value = NULL; + void *ret_value = NULL; FUNC_ENTER_NOAPI(NULL) /* Check of ID of correct type */ - if(obj_type != H5I_get_type(id)) + 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))) + 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 * @@ -1527,54 +1984,60 @@ done: 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 */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* 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) { + if (cls1->value < cls2->value) { *cmp_value = -1; HGOTO_DONE(SUCCEED) } /* end if */ - if(cls1->value > cls2->value) { + 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) { + if (cls1->name == NULL && cls2->name != NULL) { *cmp_value = -1; HGOTO_DONE(SUCCEED) } /* end if */ - if(cls1->name != NULL && cls2->name == NULL) { + if (cls1->name != NULL && cls2->name == NULL) { *cmp_value = 1; HGOTO_DONE(SUCCEED) } /* end if */ - if(0 != (*cmp_value = HDstrcmp(cls1->name, cls2->name))) + if (0 != (*cmp_value = HDstrcmp(cls1->name, cls2->name))) HGOTO_DONE(SUCCEED) /* Compare connector VOL API versions */ - if(cls1->version < cls2->version) { + if (cls1->version < cls2->version) { *cmp_value = -1; HGOTO_DONE(SUCCEED) } /* end if */ - if(cls1->version > cls2->version) { + 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) { + 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) { + if (cls1->info_cls.size > cls2->info_cls.size) { *cmp_value = 1; HGOTO_DONE(SUCCEED) } /* end if */ @@ -1587,7 +2050,6 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_cmp_connector_cls() */ - /*------------------------------------------------------------------------- * Function: H5VL_retrieve_lib_state * @@ -1604,7 +2066,7 @@ done: herr_t H5VL_retrieve_lib_state(void **state) { - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -1612,14 +2074,43 @@ H5VL_retrieve_lib_state(void **state) HDassert(state); /* Retrieve the API context state */ - if(H5CX_retrieve_state((H5CX_state_t **)state) < 0) + 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_start_lib_state + * + * Purpose: Opens a new internal state for the HDF5 library. + * + * Note: Currently just pushes a new API context state, but could be + * expanded in the future. + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Friday, February 5, 2021 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_start_lib_state(void) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Push a new API context on the stack */ + if (H5CX_push() < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't push API context") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_start_lib_state() */ + /*------------------------------------------------------------------------- * Function: H5VL_restore_lib_state * @@ -1638,37 +2129,32 @@ done: herr_t H5VL_restore_lib_state(const void *state) { - herr_t ret_value = SUCCEED; /* Return value */ + 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) + 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 + * Function: H5VL_finish_lib_state * - * Purpose: Reset the state of the library, undoing affects of - * H5VL_restore_lib_state. + * Purpose: Closes the state of the library, undoing affects of + * H5VL_start_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 / + * H5VL_start_lib_state. It can be called before / after / * independently of H5VL_free_lib_state. * * Return: SUCCEED / FAIL @@ -1679,21 +2165,20 @@ done: *------------------------------------------------------------------------- */ herr_t -H5VL_reset_lib_state(void) +H5VL_finish_lib_state(void) { - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Pop the API context off the stack */ - if(H5CX_pop() < 0) + if (H5CX_pop(FALSE) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTRESET, FAIL, "can't pop API context") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5VL_reset_lib_state() */ +} /* end H5VL_finish_lib_state() */ - /*------------------------------------------------------------------------- * Function: H5VL_free_lib_state * @@ -1712,7 +2197,7 @@ done: herr_t H5VL_free_lib_state(void *state) { - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -1720,14 +2205,13 @@ H5VL_free_lib_state(void *state) HDassert(state); /* Free the API context state */ - if(H5CX_free_state((H5CX_state_t *)state) < 0) + 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 * @@ -1743,9 +2227,9 @@ done: static herr_t H5VL__free_vol_wrapper(H5VL_wrap_ctx_t *vol_wrap_ctx) { - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_STATIC + FUNC_ENTER_PACKAGE /* Sanity check */ HDassert(vol_wrap_ctx); @@ -1754,13 +2238,14 @@ H5VL__free_vol_wrapper(H5VL_wrap_ctx_t *vol_wrap_ctx) HDassert(vol_wrap_ctx->connector->cls); /* If there is a VOL connector object wrapping context, release it */ - if(vol_wrap_ctx->obj_wrap_ctx) + 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") + 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) + 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 */ @@ -1770,7 +2255,6 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL__free_vol_wrapper() */ - /*------------------------------------------------------------------------- * Function: H5VL_set_vol_wrapper * @@ -1781,44 +2265,48 @@ done: *------------------------------------------------------------------------- */ herr_t -H5VL_set_vol_wrapper(void *obj, H5VL_t *connector) +H5VL_set_vol_wrapper(const H5VL_object_t *vol_obj) { - 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 */ + H5VL_wrap_ctx_t *vol_wrap_ctx = NULL; /* Object wrapping context */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) - /* Sanity checks */ - HDassert(obj); - HDassert(connector); + /* Sanity check */ + HDassert(vol_obj); /* Retrieve the VOL object wrap context */ - if(H5CX_get_vol_wrap_ctx((void **)&vol_wrap_ctx) < 0) + 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) { + 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(connector->cls->wrap_cls.get_wrap_ctx) { + if (vol_obj->connector->cls->wrap_cls.get_wrap_ctx) { /* Sanity check */ - HDassert(connector->cls->wrap_cls.free_wrap_ctx); + HDassert(vol_obj->connector->cls->wrap_cls.free_wrap_ctx); /* Get the wrap context from the connector */ - if((connector->cls->wrap_cls.get_wrap_ctx)(obj, &obj_wrap_ctx) < 0) + 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))) + 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(connector); + H5VL_conn_inc_rc(vol_obj->connector); /* Set up VOL object wrapper context */ - vol_wrap_ctx->rc = 1; - vol_wrap_ctx->connector = connector; + vol_wrap_ctx->rc = 1; + vol_wrap_ctx->connector = vol_obj->connector; vol_wrap_ctx->obj_wrap_ctx = obj_wrap_ctx; } /* end if */ else @@ -1826,18 +2314,17 @@ H5VL_set_vol_wrapper(void *obj, H5VL_t *connector) vol_wrap_ctx->rc++; /* Save the wrapper context */ - if(H5CX_set_vol_wrap_ctx(vol_wrap_ctx) < 0) + 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) + 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 * @@ -1854,14 +2341,14 @@ 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 */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Check for valid, active VOL object wrap context */ - if(NULL == vol_wrap_ctx) + if (NULL == vol_wrap_ctx) HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "no VOL object wrap context?") - if(0 == vol_wrap_ctx->rc) + 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 */ @@ -1871,7 +2358,6 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_inc_vol_wrapper() */ - /*------------------------------------------------------------------------- * Function: H5VL_dec_vol_wrapper * @@ -1889,29 +2375,28 @@ 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 */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Check for valid, active VOL object wrap context */ - if(NULL == vol_wrap_ctx) + if (NULL == vol_wrap_ctx) HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "no VOL object wrap context?") - if(0 == vol_wrap_ctx->rc) + 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) + 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 * @@ -1924,42 +2409,41 @@ done: 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 */ + 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) + 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) + 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 (0 == vol_wrap_ctx->rc) { /* Release object wrapping context */ - if(H5VL__free_vol_wrapper(vol_wrap_ctx) < 0) + 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) + 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") + 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 * @@ -1972,37 +2456,428 @@ done: 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 */ + 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); + /* 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???") + /* 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") + if (type == H5I_DATATYPE) + if (vol_wrap_ctx->connector->id == H5VL_NATIVE) + 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))) + 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) + 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() */ +/*------------------------------------------------------------------------- + * Function: H5VL_check_plugin_load + * + * Purpose: Check if a VOL connector matches the search criteria, and + * can be loaded. + * + * Note: Matching the connector's name / value, but the connector + * having an incompatible version is not an error, but means + * that the connector isn't a "match". Setting the SUCCEED + * value to FALSE and not failing for that case allows the + * plugin framework to keep looking for other DLLs that match + * and have a compatible version. + * + * Return: SUCCEED / FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_check_plugin_load(const H5VL_class_t *cls, const H5PL_key_t *key, hbool_t *success) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOERR + + /* Sanity checks */ + HDassert(cls); + HDassert(key); + HDassert(success); + + /* Which kind of key are we looking for? */ + if (key->vol.kind == H5VL_GET_CONNECTOR_BY_NAME) { + /* Check if plugin name matches VOL connector class name */ + if (cls->name && !HDstrcmp(cls->name, key->vol.u.name)) + *success = TRUE; + } /* end if */ + else { + /* Sanity check */ + HDassert(key->vol.kind == H5VL_GET_CONNECTOR_BY_VALUE); + + /* Check if plugin value matches VOL connector class value */ + if (cls->value == key->vol.u.value) + *success = TRUE; + } /* end else */ + + /* Connector is a match, but might not be a compatible version */ + if (*success && cls->version != H5VL_VERSION) + *success = FALSE; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_check_plugin_load() */ + +/*------------------------------------------------------------------------- + * Function: H5VL__is_default_conn + * + * Purpose: Check if the default connector will be used for a container. + * + * Return: SUCCEED / FAIL + * + *------------------------------------------------------------------------- + */ +void +H5VL__is_default_conn(hid_t fapl_id, hid_t connector_id, hbool_t *is_default) +{ + FUNC_ENTER_PACKAGE_NOERR + + /* Sanity checks */ + HDassert(is_default); + + /* Determine if the default VOL connector will be used, based on non-default + * values in the FAPL, connector ID, or the HDF5_VOL_CONNECTOR environment + * variable being set. + */ + *is_default = (H5VL_def_conn_s.connector_id == H5_DEFAULT_VOL) && + ((H5P_FILE_ACCESS_DEFAULT == fapl_id) || connector_id == H5_DEFAULT_VOL); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL__is_default_conn() */ + +/*------------------------------------------------------------------------- + * Function: H5VL_setup_args + * + * Purpose: Set up arguments to access an object + * + * Return: SUCCEED / FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_setup_args(hid_t loc_id, H5I_type_t id_type, H5VL_object_t **vol_obj) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(vol_obj); + + /* Get attribute pointer */ + if (NULL == (*vol_obj = (H5VL_object_t *)H5I_object_verify(loc_id, id_type))) + HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "not the correct type of ID") + + /* Set up collective metadata (if appropriate) */ + if (H5CX_set_loc(loc_id) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set collective metadata read") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_setup_args() */ + +/*------------------------------------------------------------------------- + * Function: H5VL_setup_loc_args + * + * Purpose: Set up arguments to access an object + * + * Return: SUCCEED / FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_setup_loc_args(hid_t loc_id, H5VL_object_t **vol_obj, H5VL_loc_params_t *loc_params) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(vol_obj); + HDassert(loc_params); + + /* Get the location object */ + if (NULL == (*vol_obj = (H5VL_object_t *)H5VL_vol_object(loc_id))) + HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "not the correct type of ID") + + /* Set up collective metadata (if appropriate */ + if (H5CX_set_loc(loc_id) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set collective metadata read") + + /* Set location parameters */ + loc_params->type = H5VL_OBJECT_BY_SELF; + loc_params->obj_type = H5I_get_type(loc_id); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_setup_loc_args() */ + +/*------------------------------------------------------------------------- + * Function: H5VL_setup_acc_args + * + * Purpose: Set up arguments to access an object + * + * Return: SUCCEED / FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_setup_acc_args(hid_t loc_id, const H5P_libclass_t *libclass, hbool_t is_collective, hid_t *acspl_id, + H5VL_object_t **vol_obj, H5VL_loc_params_t *loc_params) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(libclass); + HDassert(acspl_id); + HDassert(vol_obj); + HDassert(loc_params); + + /* Verify access property list and set up collective metadata if appropriate */ + if (H5CX_set_apl(acspl_id, libclass, loc_id, is_collective) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set access property list info") + + /* Get the location object */ + if (NULL == (*vol_obj = (H5VL_object_t *)H5VL_vol_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") + + /* Set location parameters */ + loc_params->type = H5VL_OBJECT_BY_SELF; + loc_params->obj_type = H5I_get_type(loc_id); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_setup_acc_args() */ + +/*------------------------------------------------------------------------- + * Function: H5VL_setup_self_args + * + * Purpose: Set up arguments to access an object "by self" + * + * Return: SUCCEED / FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_setup_self_args(hid_t loc_id, H5VL_object_t **vol_obj, H5VL_loc_params_t *loc_params) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(vol_obj); + HDassert(loc_params); + + /* Get the location object */ + if (NULL == (*vol_obj = (H5VL_object_t *)H5VL_vol_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") + + /* Set location parameters */ + loc_params->type = H5VL_OBJECT_BY_SELF; + loc_params->obj_type = H5I_get_type(loc_id); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_setup_self_args() */ + +/*------------------------------------------------------------------------- + * Function: H5VL_setup_name_args + * + * Purpose: Set up arguments to access an object "by name" + * + * Return: SUCCEED / FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_setup_name_args(hid_t loc_id, const char *name, hbool_t is_collective, hid_t lapl_id, + H5VL_object_t **vol_obj, H5VL_loc_params_t *loc_params) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(vol_obj); + HDassert(loc_params); + + /* Check args */ + if (!name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "name parameter cannot be NULL") + if (!*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "name parameter cannot be an empty string") + + /* Verify access property list and set up collective metadata if appropriate */ + if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, is_collective) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set access property list info") + + /* Get the location object */ + if (NULL == (*vol_obj = (H5VL_object_t *)H5VL_vol_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") + + /* Set up location parameters */ + loc_params->type = H5VL_OBJECT_BY_NAME; + loc_params->loc_data.loc_by_name.name = name; + loc_params->loc_data.loc_by_name.lapl_id = lapl_id; + loc_params->obj_type = H5I_get_type(loc_id); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_setup_name_args() */ + +/*------------------------------------------------------------------------- + * Function: H5VL_setup_idx_args + * + * Purpose: Set up arguments to access an object "by idx" + * + * Return: SUCCEED / FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_setup_idx_args(hid_t loc_id, const char *name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, + hbool_t is_collective, hid_t lapl_id, H5VL_object_t **vol_obj, + H5VL_loc_params_t *loc_params) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(vol_obj); + HDassert(loc_params); + + /* Check args */ + if (!name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "name parameter cannot be NULL") + if (!*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "name parameter cannot be an empty string") + if (idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified") + if (order <= H5_ITER_UNKNOWN || order >= H5_ITER_N) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified") + + /* Verify access property list and set up collective metadata if appropriate */ + if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, is_collective) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set access property list info") + + /* Get the location object */ + if (NULL == (*vol_obj = (H5VL_object_t *)H5VL_vol_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") + + /* Set location parameters */ + loc_params->type = H5VL_OBJECT_BY_IDX; + loc_params->loc_data.loc_by_idx.name = name; + loc_params->loc_data.loc_by_idx.idx_type = idx_type; + loc_params->loc_data.loc_by_idx.order = order; + loc_params->loc_data.loc_by_idx.n = n; + loc_params->loc_data.loc_by_idx.lapl_id = lapl_id; + loc_params->obj_type = H5I_get_type(loc_id); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_setup_idx_args() */ + +/*------------------------------------------------------------------------- + * Function: H5VL_setup_token_args + * + * Purpose: Set up arguments to access an object by token + * + * Return: SUCCEED / FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_setup_token_args(hid_t loc_id, H5O_token_t *obj_token, H5VL_object_t **vol_obj, + H5VL_loc_params_t *loc_params) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(vol_obj); + HDassert(loc_params); + + /* Get the location object */ + if (NULL == (*vol_obj = (H5VL_object_t *)H5VL_vol_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") + + /* Set location parameters */ + loc_params->type = H5VL_OBJECT_BY_TOKEN; + loc_params->loc_data.loc_by_token.token = obj_token; + loc_params->obj_type = H5I_get_type(loc_id); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_setup_token_args() */ + +/*------------------------------------------------------------------------- + * Function: H5VL_get_cap_flags + * + * Purpose: Query capability flags for connector property. + * + * Note: VOL connector set with HDF5_VOL_CONNECTOR overrides the + * property passed in. + * + * Return: Success: Non-negative + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_get_cap_flags(const H5VL_connector_prop_t *connector_prop, unsigned *cap_flags) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(connector_prop); + + /* Copy the connector ID & info, if there is one */ + if (connector_prop->connector_id > 0) { + H5VL_class_t *connector; /* Pointer to connector */ + + /* 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") + + /* Query the connector's capability flags */ + if (H5VL_introspect_get_cap_flags(connector_prop->connector_info, connector, cap_flags) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't query connector's capability flags") + } /* end if */ + else + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "connector ID not set?") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_get_cap_flags() */ |