diff options
Diffstat (limited to 'src/H5I.c')
-rw-r--r-- | src/H5I.c | 291 |
1 files changed, 261 insertions, 30 deletions
@@ -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 /*------------------------------------------------------------------------- |