summaryrefslogtreecommitdiffstats
path: root/src/H5I.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5I.c')
-rw-r--r--src/H5I.c291
1 files changed, 261 insertions, 30 deletions
diff --git a/src/H5I.c b/src/H5I.c
index 15db6d6..1486603 100644
--- a/src/H5I.c
+++ b/src/H5I.c
@@ -46,6 +46,8 @@
#include "H5MMprivate.h" /* Memory management */
#include "H5Oprivate.h" /* Object headers */
#include "H5SLprivate.h" /* Skip Lists */
+#include "H5Tprivate.h" /* Datatypes */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/* Define this to compile in support for dumping ID information */
/* #define H5I_DEBUG_OUTPUT */
@@ -76,7 +78,7 @@ typedef struct H5I_id_info_t {
/* ID type structure used */
typedef struct {
- const H5I_class_t *cls; /* Pointer to ID class */
+ H5I_class_t *cls; /* Pointer to ID class */
unsigned init_count; /* # of times this type has been initialized*/
uint64_t id_count; /* Current number of IDs held */
uint64_t nextid; /* ID to use for the next atom */
@@ -89,11 +91,24 @@ typedef struct {
void *ret_obj; /* Object to return */
} H5I_search_ud_t;
+typedef struct {
+ H5I_iterate_func_t op; /* Application's callback routine */
+ void *op_data; /* Application's user data */
+} H5I_iterate_pub_ud_t;
+
+/* User data for iterator callback for retrieveing an ID correponding to an object pointer */
+typedef struct {
+ const void *object; /* object pointer to search for */
+ H5I_type_t obj_type; /* type of object we are searching for */
+ hid_t ret_id; /* ID returned */
+} H5I_get_id_ud_t;
+
/* User data for iterator callback for ID iteration */
typedef struct {
H5I_search_func_t user_func; /* 'User' function to invoke */
void *user_udata; /* User data to pass to 'user' function */
hbool_t app_ref; /* Whether this is an appl. ref. call */
+ H5I_type_t obj_type; /* type of object we are iterating over */
} H5I_iterate_ud_t;
/* User data for H5I__clear_type_cb */
@@ -128,6 +143,8 @@ H5FL_DEFINE_STATIC(H5I_id_type_t);
/* Declare a free list to manage the H5I_class_t struct */
H5FL_DEFINE_STATIC(H5I_class_t);
+H5FL_EXTERN(H5VL_object_t);
+
/*--------------------- Local function prototypes ---------------------------*/
static htri_t H5I__clear_type_cb(void *_id, void *key, void *udata);
static int H5I__destroy_type(H5I_type_t type);
@@ -136,6 +153,7 @@ static void *H5I__remove_common(H5I_id_type_t *type_ptr, hid_t id);
static int H5I__inc_type_ref(H5I_type_t type);
static int H5I__get_type_ref(H5I_type_t type);
static H5I_id_info_t *H5I__find_id(hid_t id);
+static int H5I__iterate_pub_cb(void *obj, hid_t id, void *udata);
#ifdef H5I_DEBUG_OUTPUT
static herr_t H5I__debug(H5I_type_t type);
#endif /* H5I_DEBUG_OUTPUT */
@@ -1869,14 +1887,89 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5I__iterate_pub_cb
+ *
+ * Purpose: Callback routine for H5Iiterate, when it calls
+ * H5I_iterate. Calls "user" callback search function, and
+ * then sets return value, based on the result of that
+ * callback.
+ *
+ * Return: The value returned by the user callback
+ *
+ * Programmer: Neil Fortner
+ * Friday, October 11, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5I__iterate_pub_cb(void H5_ATTR_UNUSED *obj, hid_t id, void *_udata)
+{
+ H5I_iterate_pub_ud_t *udata = (H5I_iterate_pub_ud_t *)_udata; /* User data for callback */
+ herr_t ret_value; /* Callback return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ ret_value = (*udata->op)(id, udata->op_data);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I__iterate_pub_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Iiterate
+ *
+ * Purpose: Call the callback funciton op for each member of the id
+ * type type. op takes as parameters the id and a
+ * passthrough of op_data, and returns an herr_t. A positive
+ * return from op will cause the iteration to stop and
+ * H5Iiterate will return the value returned by op. A
+ * negative return from op will cause the iteration to stop
+ * and H5Iiterate will return failure. A zero return from op
+ * will allow iteration to continue, as long as there are
+ * other ids remaining in type.
+ *
+ * Limitation: Currently there is no way to start searching from where a
+ * previous search left off.
+ *
+ * Return: The last value returned by op
+ *
+ * Programmer: Neil Fortner
+ * Friday, October 11, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Iiterate(H5I_type_t type, H5I_iterate_func_t op, void *op_data)
+{
+ H5I_iterate_pub_ud_t int_udata; /* Internal user data */
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "Itx*x", type, op, op_data);
+
+ /* Set up udata struct */
+ int_udata.op = op;
+ int_udata.op_data = op_data;
+
+ /* Note that H5I_iterate returns an error code. We ignore it
+ * here, as we can't do anything with it without revising the API.
+ */
+ if((ret_value = H5I_iterate(type, H5I__iterate_pub_cb, &int_udata, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADITER, FAIL, "can't iterate over ids")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Iiterate() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5I__iterate_cb
*
* Purpose: Callback routine for H5I_iterate, invokes "user" callback
* function, and then sets return value, based on the result of
* that callback.
*
- * Return: Success: Non-negative on success
- * Failure: Negative
+ * Return: Value returned by callback
*
* Programmer: Quincey Koziol
* Thursday, October 3, 2013
@@ -1894,16 +1987,24 @@ H5I__iterate_cb(void *_item, void H5_ATTR_UNUSED *_key, void *_udata)
/* Don't make callback if app_ref is set and the appl. ref count is 0 */
if((!udata->app_ref) || (item->app_count > 0)) {
- herr_t cb_ret_val;
+ H5I_type_t type = udata->obj_type;
+ const void *obj_ptr = NULL;
+
+ if(H5I_FILE == type || H5I_GROUP == type || H5I_DATASET == type || H5I_ATTR == type) {
+ const H5VL_object_t *obj = (const H5VL_object_t *)item->obj_ptr;
+ obj_ptr = obj->vol_obj;
+ }
+ else if(H5I_DATATYPE == type) {
+ const H5T_t *dt = (const H5T_t *)item->obj_ptr;
+ obj_ptr = (void *)H5T_get_actual_type(dt);
+ }
+ else
+ obj_ptr = item->obj_ptr;
/* (Casting away const OK) */
- cb_ret_val = (*udata->user_func)((void *)item->obj_ptr, item->id, udata->user_udata);
- if(cb_ret_val > 0)
- ret_value = H5_ITER_STOP; /* terminate iteration early */
- else if(cb_ret_val < 0)
- ret_value = H5_ITER_ERROR; /* indicate failure (which terminates iteration) */
- } /* end if */
+ ret_value = (*udata->user_func)((void *)obj_ptr, item->id, udata->user_udata);
+ }
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I__iterate_cb() */
@@ -1916,21 +2017,18 @@ H5I__iterate_cb(void *_item, void H5_ATTR_UNUSED *_key, void *_udata)
* Stop if FUNC returns a non zero value (i.e. anything
* other than H5_ITER_CONT).
*
- * If FUNC returns a positive value (i.e. H5_ITER_STOP),
- * return SUCCEED.
- *
- * If FUNC returns a negative value (i.e. H5_ITER_ERROR),
- * return FAIL.
+ * Returns the last value returned by the callback, or FAIL
+ * if an internal error occurred.
*
* The FUNC should take a pointer to the object and the
* udata as arguments and return non-zero to terminate
- * siteration, and zero to continue.
+ * iteration, and zero to continue.
*
* Limitation: Currently there is no way to start the iteration from
* where a previous iteration left off.
*
- * Return: Success: SUCCEED
- * Failure: FAIL
+ * Return: Success: Last value returned by callback
+ * Failure: FAIL or last value returned by callback
*
* Programmer: John Mainzer
* Monday, December 6, 2011
@@ -1953,15 +2051,15 @@ H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_re
/* Only iterate through ID list if it is initialized and there are IDs in type */
if(type_ptr && type_ptr->init_count > 0 && type_ptr->id_count > 0) {
H5I_iterate_ud_t iter_udata; /* User data for iteration callback */
- herr_t iter_status; /* Iteration status */
/* Set up iterator user data */
iter_udata.user_func = func;
iter_udata.user_udata = udata;
iter_udata.app_ref = app_ref;
+ iter_udata.obj_type = type;
/* Iterate over IDs */
- if((iter_status = H5SL_iterate(type_ptr->ids, H5I__iterate_cb, &iter_udata)) < 0)
+ if((ret_value = H5SL_iterate(type_ptr->ids, H5I__iterate_cb, &iter_udata)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_BADITER, FAIL, "iteration failed")
} /* end if */
@@ -2060,8 +2158,10 @@ done:
/*-------------------------------------------------------------------------
* Function: H5Iget_file_id
*
- * Purpose: The public version of H5I_get_file_id(), obtains the file
- * ID given an object ID. User has to close this ID.
+ * Purpose: Obtains the file ID given an object ID. User has to close
+ * this ID. This routine goes through the VOL to get the file
+ * struct and checks if an ID for that struct exists (increments
+ * ref count & returns this ID) or creates a new ID for it.
*
* Return: Success: file ID
*
@@ -2070,19 +2170,53 @@ done:
* Programmer: Raymond Lu
* Oct 27, 2003
*
+ * Modified: Mohamad Chaarawi
+ * September, 2012
+ * Update for Virtual Object Layer
*-------------------------------------------------------------------------
*/
hid_t
H5Iget_file_id(hid_t obj_id)
{
- hid_t ret_value; /* Return value */
+ H5VL_object_t *obj;
+ void *file = NULL;
+ H5I_type_t type; /* ID type */
+ hid_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("i", "i", obj_id);
- if((ret_value = H5I_get_file_id(obj_id, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't retrieve file ID")
+ /* Get object type */
+ type = H5I_TYPE(obj_id);
+ if(H5I_FILE == type || H5I_DATATYPE == type || H5I_GROUP == type ||
+ H5I_DATASET == type || H5I_ATTR == type) {
+ /* get the object pointer*/
+ if(NULL == (obj = H5VL_get_object(obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid identifier")
+
+ /* Get the file through the VOL */
+ if(H5VL_file_get(obj->vol_obj, obj->vol_info->vol_cls, H5VL_OBJECT_GET_FILE,
+ H5AC_dxpl_id, H5_REQUEST_NULL, type, &file) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "unable to get file")
+
+ if (NULL == file)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to reopen file")
+
+ /* Check if the ID already exists and procceed accordingly */
+ if (FAIL == (ret_value = H5I_get_id(file, H5I_FILE))) {
+ /* Get an atom for the file */
+ if((ret_value = H5VL_register_id(H5I_FILE, file, obj->vol_info, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file handle")
+ }
+ else {
+ /* Increment ref count on existing ID */
+ if(H5I_inc_ref(ret_value, TRUE) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed")
+ }
+ }
+ else
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid object ID")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Iget_file_id() */
@@ -2091,7 +2225,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5I_get_file_id
*
- * Purpose: The private version of H5Iget_file_id(), obtains the file
+ * Purpose: The native version of H5Iget_file_id(), obtains the file
* ID given an object ID.
*
* Return: Success: file ID
@@ -2100,6 +2234,10 @@ done:
* Programmer: Raymond Lu
* Oct 27, 2003
*
+ * Modified: Mohamad Chaarawi
+ * September, 2012
+ * Update for Virtual Object Layer
+ *
*-------------------------------------------------------------------------
*/
hid_t
@@ -2112,12 +2250,11 @@ H5I_get_file_id(hid_t obj_id, hbool_t app_ref)
/* Get object type */
type = H5I_TYPE(obj_id);
+
+ /* object is a file, just increment reference count on ID */
if(type == H5I_FILE) {
- /* Increment reference count on file ID */
if(H5I_inc_ref(obj_id, app_ref) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed")
-
- /* Set return value */
ret_value = obj_id;
} /* end if */
else if(type == H5I_DATATYPE || type == H5I_GROUP || type == H5I_DATASET || type == H5I_ATTR) {
@@ -2133,11 +2270,105 @@ H5I_get_file_id(hid_t obj_id, hbool_t app_ref)
} /* end if */
else
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid object ID")
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_get_file_id() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5I__get_id_cb
+ *
+ * Purpose: Callback for searching for an ID with a specific pointer
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Mohamad Chaarawi
+ * October 16, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5I__get_id_cb(void *_item, void H5_ATTR_UNUSED *_key, void *_udata)
+{
+ H5I_id_info_t *item = (H5I_id_info_t *)_item; /* Pointer to the ID node */
+ H5I_get_id_ud_t *udata = (H5I_get_id_ud_t *)_udata; /* Pointer to user data */
+ H5I_type_t type = udata->obj_type;
+ const void *obj_ptr = NULL;
+ int ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity check */
+ HDassert(item);
+ HDassert(udata);
+
+ if(H5I_FILE == type || H5I_GROUP == type || H5I_DATASET == type || H5I_ATTR == type) {
+ const H5VL_object_t *obj = (const H5VL_object_t *)item->obj_ptr;
+ obj_ptr = obj->vol_obj;
+ }
+ else if(H5I_DATATYPE == type) {
+ const H5T_t *dt = (const H5T_t *)item->obj_ptr;
+ obj_ptr = (void *)H5T_get_actual_type(dt);
+ }
+ else
+ obj_ptr = item->obj_ptr;
+
+ if (obj_ptr == udata->object) {
+ udata->ret_id = item->id;
+ ret_value = H5_ITER_STOP;
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I__get_id_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5I_get_id
+ *
+ * Purpose: return ID of object
+ *
+ * Return: Success: id of object
+ * Failure: FAIL
+ *
+ * Programmer: Mohamad Chaarawi
+ * June 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5I_get_id(const void *object, H5I_type_t type)
+{
+ hid_t ret_value = FAIL; /* Return value */
+ H5I_id_type_t *type_ptr; /*ptr to the type */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ type_ptr = H5I_id_type_list_g[type];
+ if (!type_ptr || type_ptr->init_count <= 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
+
+ /* Only iterate through ID list if it is initialized and there are IDs in type */
+ if(type_ptr && type_ptr->init_count > 0 && type_ptr->id_count > 0) {
+ H5I_get_id_ud_t udata; /* User data */
+ herr_t iter_status; /* Iteration status */
+
+ /* Set up iterator user data */
+ udata.object = object;
+ udata.obj_type = type;
+ udata.ret_id = FAIL;
+
+ /* Iterate over IDs */
+ if((iter_status = H5SL_iterate(type_ptr->ids, H5I__get_id_cb, &udata)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADITER, FAIL, "iteration failed")
+
+ ret_value = udata.ret_id;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I_get_id() */
+
#ifdef H5I_DEBUG_OUTPUT
/*-------------------------------------------------------------------------