diff options
Diffstat (limited to 'src')
119 files changed, 9283 insertions, 2108 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a7e3f57..1bc878f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -174,6 +174,10 @@ IDE_GENERATED_PROPERTIES ("H5EA" "${H5EA_HDRS}" "${H5EA_SOURCES}" ) set (H5ES_SOURCES + ${HDF5_SRC_DIR}/H5ES.c + ${HDF5_SRC_DIR}/H5ESevent.c + ${HDF5_SRC_DIR}/H5ESint.c + ${HDF5_SRC_DIR}/H5ESlist.c ) set (H5ES_HDRS ${HDF5_SRC_DIR}/H5ESpublic.h @@ -181,6 +185,7 @@ set (H5ES_HDRS IDE_GENERATED_PROPERTIES ("H5ES" "${H5ES_HDRS}" "${H5ES_SOURCES}" ) + set (H5F_SOURCES ${HDF5_SRC_DIR}/H5F.c ${HDF5_SRC_DIR}/H5Faccum.c @@ -440,6 +445,7 @@ set (H5MP_HDRS ) IDE_GENERATED_PROPERTIES ("H5MP" "${H5MP_HDRS}" "${H5MP_SOURCES}" ) + set (H5O_SOURCES ${HDF5_SRC_DIR}/H5O.c ${HDF5_SRC_DIR}/H5Oainfo.c @@ -640,6 +646,7 @@ set (H5TS_SOURCES ${HDF5_SRC_DIR}/H5TS.c ) set (H5TS_HDRS + ${HDF5_SRC_DIR}/H5TSpublic.h ) IDE_GENERATED_PROPERTIES ("H5TS" "${H5TS_HDRS}" "${H5TS_SOURCES}" ) @@ -726,6 +733,7 @@ set (H5_MODULE_HEADERS ${HDF5_SRC_DIR}/H5Dmodule.h ${HDF5_SRC_DIR}/H5Emodule.h ${HDF5_SRC_DIR}/H5EAmodule.h + ${HDF5_SRC_DIR}/H5ESmodule.h ${HDF5_SRC_DIR}/H5Fmodule.h ${HDF5_SRC_DIR}/H5FAmodule.h ${HDF5_SRC_DIR}/H5FDdrvr_module.h @@ -767,6 +775,7 @@ set (common_SRCS ${H5D_SOURCES} ${H5E_SOURCES} ${H5EA_SOURCES} + ${H5ES_SOURCES} ${H5F_SOURCES} ${H5FA_SOURCES} ${H5FD_SOURCES} @@ -836,6 +845,7 @@ set (H5_PUBLIC_HEADERS ${H5S_HDRS} ${H5SM_HDRS} ${H5T_HDRS} + ${H5TS_HDRS} ${H5VL_HDRS} ${H5Z_HDRS} ) @@ -875,6 +885,9 @@ set (H5_PRIVATE_HEADERS ${HDF5_SRC_DIR}/H5EApkg.h ${HDF5_SRC_DIR}/H5EAprivate.h + ${HDF5_SRC_DIR}/H5ESpkg.h + ${HDF5_SRC_DIR}/H5ESprivate.h + ${HDF5_SRC_DIR}/H5Fpkg.h ${HDF5_SRC_DIR}/H5Fprivate.h @@ -254,6 +254,8 @@ H5_init_library(void) * It might not be initialized during normal file open. * When the application does not close the file, routines in the module might * be called via H5_term_library() when shutting down the file. + * The dataspace interface needs to be initialized so that future IDs for + * dataspaces work. */ if (H5E_init() < 0) HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize error interface") @@ -267,6 +269,8 @@ H5_init_library(void) HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize link interface") if (H5FS_init() < 0) HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize FS interface") + if (H5S_init() < 0) + HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize dataspace interface") /* Finish initializing interfaces that depend on the interfaces above */ if (H5VL_init_phase2() < 0) @@ -357,21 +361,31 @@ H5_term_library(void) /* Try to organize these so the "higher" level components get shut * down before "lower" level components that they might rely on. -QAK */ - pending += DOWN(L); - /* Close the "top" of various interfaces (IDs, etc) but don't shut - * down the whole interface yet, so that the object header messages - * get serialized correctly for entries in the metadata cache and the - * symbol table entry in the superblock gets serialized correctly, etc. - * all of which is performed in the 'F' shutdown. + /* Close the event sets first, so that all asynchronous operations + * complete before anything else attempts to shut down. */ - pending += DOWN(A_top); - pending += DOWN(D_top); - pending += DOWN(G_top); - pending += DOWN(M_top); - pending += DOWN(R_top); - pending += DOWN(S_top); - pending += DOWN(T_top); + pending += DOWN(ES); + + /* Close down the user-facing interfaces, after the event sets */ + if (pending == 0) { + /* Close the interfaces dependent on others */ + pending += DOWN(L); + + /* Close the "top" of various interfaces (IDs, etc) but don't shut + * down the whole interface yet, so that the object header messages + * get serialized correctly for entries in the metadata cache and the + * symbol table entry in the superblock gets serialized correctly, etc. + * all of which is performed in the 'F' shutdown. + */ + pending += DOWN(A_top); + pending += DOWN(D_top); + pending += DOWN(G_top); + pending += DOWN(M_top); + pending += DOWN(R_top); + pending += DOWN(S_top); + pending += DOWN(T_top); + } /* end if */ /* Don't shut down the file code until objects in files are shut down */ if (pending == 0) @@ -1183,12 +1197,12 @@ H5free_memory(void *mem) herr_t H5is_library_threadsafe(hbool_t *is_ts /*out*/) { - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API_NOINIT H5TRACE1("e", "x", is_ts); - if(is_ts) { + if (is_ts) { #ifdef H5_HAVE_THREADSAFE *is_ts = TRUE; #else /* H5_HAVE_THREADSAFE */ @@ -1218,14 +1232,14 @@ H5is_library_threadsafe(hbool_t *is_ts /*out*/) herr_t H5is_library_terminating(hbool_t *is_terminating /*out*/) { - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API_NOINIT H5TRACE1("e", "x", is_terminating); HDassert(is_terminating); - if(is_terminating) + if (is_terminating) *is_terminating = H5_TERM_GLOBAL; else ret_value = FAIL; @@ -25,6 +25,7 @@ #include "H5Apkg.h" /* Attributes */ #include "H5CXprivate.h" /* API Contexts */ #include "H5Eprivate.h" /* Error handling */ +#include "H5ESprivate.h" /* Event Sets */ #include "H5FLprivate.h" /* Free Lists */ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ @@ -48,6 +49,45 @@ /* Local Prototypes */ /********************/ +/* Helper routines for sync/async API calls */ +static hid_t H5A__create_common(H5VL_object_t *vol_obj, H5VL_loc_params_t *loc_params, const char *attr_name, + hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id, + void **token_ptr); +static hid_t H5A__create_api_common(hid_t loc_id, const char *attr_name, hid_t type_id, hid_t space_id, + hid_t acpl_id, hid_t aapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static hid_t H5A__create_by_name_api_common(hid_t loc_id, const char *obj_name, const char *attr_name, + hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id, + hid_t lapl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr); +static hid_t H5A__open_common(H5VL_object_t *vol_obj, H5VL_loc_params_t *loc_params, const char *attr_name, + hid_t aapl_id, void **token_ptr); +static hid_t H5A__open_api_common(hid_t loc_id, const char *attr_name, hid_t aapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static hid_t H5A__open_by_name_api_common(hid_t loc_id, const char *obj_name, const char *attr_name, + hid_t aapl_id, hid_t lapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static hid_t H5A__open_by_idx_api_common(hid_t loc_id, const char *obj_name, H5_index_t idx_type, + H5_iter_order_t order, hsize_t n, hid_t aapl_id, hid_t lapl_id, + void **token_ptr, H5VL_object_t **_vol_obj_ptr); +static herr_t H5A__write_api_common(hid_t attr_id, hid_t type_id, const void *buf, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static herr_t H5A__read_api_common(hid_t attr_id, hid_t dtype_id, void *buf, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static herr_t H5A__rename_common(H5VL_object_t *vol_obj, H5VL_loc_params_t *loc_params, const char *old_name, + const char *new_name, void **token_ptr); +static herr_t H5A__rename_api_common(hid_t loc_id, const char *old_name, const char *new_name, + void **token_ptr, H5VL_object_t **_vol_obj_ptr); +static herr_t H5A__rename_by_name_api_common(hid_t loc_id, const char *obj_name, const char *old_attr_name, + const char *new_attr_name, hid_t lapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static herr_t H5A__exists_common(H5VL_object_t *vol_obj, H5VL_loc_params_t *loc_params, const char *attr_name, + hbool_t *attr_exists, void **token_ptr); +static herr_t H5A__exists_api_common(hid_t obj_id, const char *attr_name, hbool_t *attr_exists, + void **token_ptr, H5VL_object_t **_vol_obj_ptr); +static herr_t H5A__exists_by_name_api_common(hid_t obj_id, const char *obj_name, const char *attr_name, + hbool_t *attr_exists, hid_t lapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); + /*********************/ /* Package Variables */ /*********************/ @@ -61,6 +101,95 @@ /*******************/ /*-------------------------------------------------------------------------- + * Function: H5A__create_common + * + * Purpose: This is the common function for creating HDF5 datasets. + * + * Return: Success: A attribute ID + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +static hid_t +H5A__create_common(H5VL_object_t *vol_obj, H5VL_loc_params_t *loc_params, const char *attr_name, + hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id, void **token_ptr) +{ + void *attr = NULL; /* Attribute created */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity checks */ + HDassert(vol_obj); + HDassert(loc_params); + HDassert(attr_name); + + /* Create the attribute */ + if (NULL == (attr = H5VL_attr_create(vol_obj, loc_params, attr_name, type_id, space_id, acpl_id, aapl_id, + H5P_DATASET_XFER_DEFAULT, token_ptr))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5I_INVALID_HID, "unable to create attribute") + + /* Register the new attribute and get an ID for it */ + if ((ret_value = H5VL_register(H5I_ATTR, attr, vol_obj->connector, TRUE)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register attribute for ID") + +done: + /* Cleanup on failure */ + if (H5I_INVALID_HID == ret_value) + if (attr && H5VL_attr_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close attribute") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A__create_common() */ + +/*-------------------------------------------------------------------------- + * Function: H5A__create_api_common + * + * Purpose: This is the common function for creating HDF5 attributes + * + * Return: Success: A attribute ID + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +static hid_t +H5A__create_api_common(hid_t loc_id, const char *attr_name, hid_t type_id, hid_t space_id, hid_t acpl_id, + hid_t aapl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check arguments */ + if (H5I_ATTR == H5I_get_type(loc_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "location is not valid for an attribute") + if (!attr_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "attr_name parameter cannot be NULL") + if (!*attr_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "attr_name parameter cannot be an empty string") + + /* Set up object access arguments */ + if (H5VL_setup_acc_args(loc_id, H5P_CLS_AACC, TRUE, &aapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set object access arguments") + + /* Get correct property list */ + if (H5P_DEFAULT == acpl_id) + acpl_id = H5P_ATTRIBUTE_CREATE_DEFAULT; + + /* Create the attribute */ + if ((ret_value = H5A__create_common(*vol_obj_ptr, &loc_params, attr_name, type_id, space_id, acpl_id, + aapl_id, token_ptr)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCREATE, H5I_INVALID_HID, "unable to create attribute") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A__create_api_common() */ + +/*-------------------------------------------------------------------------- * Function: H5Acreate2 * * Purpose: Creates an attribute on an object @@ -96,14 +225,90 @@ hid_t H5Acreate2(hid_t loc_id, const char *attr_name, hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id) { - void * attr = NULL; /* Attribute created */ - H5VL_object_t * vol_obj = NULL; /* Object of loc_id */ - H5VL_loc_params_t loc_params; - hid_t ret_value = H5I_INVALID_HID; /* Return value */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ FUNC_ENTER_API(H5I_INVALID_HID) H5TRACE6("i", "i*siiii", loc_id, attr_name, type_id, space_id, acpl_id, aapl_id); + /* Create the attribute synchronously */ + if ((ret_value = + H5A__create_api_common(loc_id, attr_name, type_id, space_id, acpl_id, aapl_id, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCREATE, H5I_INVALID_HID, "unable to synchronously create attribute") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Acreate2() */ + +/*-------------------------------------------------------------------------- + * Function: H5Acreate_sync + * + * Purpose: Asynchronous version of H5Acreate + * + * Return: Success: A attribute ID + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Acreate_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *attr_name, hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id, + hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE10("i", "*s*sIui*siiiii", app_file, app_func, app_line, loc_id, attr_name, type_id, space_id, + acpl_id, aapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Create the attribute asynchronously */ + if ((ret_value = H5A__create_api_common(loc_id, attr_name, type_id, space_id, acpl_id, aapl_id, token_ptr, + &vol_obj)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCREATE, H5I_INVALID_HID, "unable to asynchronously create attribute") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE10(FUNC, "*s*sIui*siiiii", app_file, app_func, app_line, loc_id, attr_name, + type_id, space_id, acpl_id, aapl_id, es_id)) < 0) { + if (H5I_dec_app_ref(ret_value) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, H5I_INVALID_HID, "can't decrement count on attribute ID") + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Acreate_async() */ + +/*-------------------------------------------------------------------------- + * Function: H5A__create_by_name_api_common + * + * Purpose: This is the common function for creating HDF5 attributes by name + * + * Return: Success: A attribute ID + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +static hid_t +H5A__create_by_name_api_common(hid_t loc_id, const char *obj_name, const char *attr_name, hid_t type_id, + hid_t space_id, hid_t acpl_id, hid_t aapl_id, hid_t lapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_STATIC + /* Check arguments */ if (H5I_ATTR == H5I_get_type(loc_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "location is not valid for an attribute") @@ -112,39 +317,27 @@ H5Acreate2(hid_t loc_id, const char *attr_name, hid_t type_id, hid_t space_id, h if (!*attr_name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "attr_name parameter cannot be an empty string") - /* Get correct property list */ - if (H5P_DEFAULT == acpl_id) - acpl_id = H5P_ATTRIBUTE_CREATE_DEFAULT; + /* obj_name is verified in H5VL_setup_name_args() */ + /* Set up object access arguments */ + if (H5VL_setup_name_args(loc_id, obj_name, H5P_CLS_LACC, TRUE, lapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set object access arguments") /* Verify access property list and set up collective metadata if appropriate */ if (H5CX_set_apl(&aapl_id, H5P_CLS_AACC, loc_id, TRUE) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info") - - /* Get the location object */ - if (NULL == (vol_obj = H5VL_vol_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier") + HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set attribute access property list info") - /* Set location parameters */ - loc_params.type = H5VL_OBJECT_BY_SELF; - loc_params.obj_type = H5I_get_type(loc_id); + /* Get correct property list */ + if (H5P_DEFAULT == acpl_id) + acpl_id = H5P_ATTRIBUTE_CREATE_DEFAULT; /* Create the attribute */ - if (NULL == (attr = H5VL_attr_create(vol_obj, &loc_params, attr_name, type_id, space_id, acpl_id, aapl_id, - H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5I_INVALID_HID, "unable to create attribute") - - /* Register the new attribute and get an ID for it */ - if ((ret_value = H5VL_register(H5I_ATTR, attr, vol_obj->connector, TRUE)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register attribute for ID") + if ((ret_value = H5A__create_common(*vol_obj_ptr, &loc_params, attr_name, type_id, space_id, acpl_id, + aapl_id, token_ptr)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCREATE, H5I_INVALID_HID, "unable to create attribute") done: - /* Cleanup on failure */ - if (H5I_INVALID_HID == ret_value) - if (attr && H5VL_attr_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) - HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close attribute") - - FUNC_LEAVE_API(ret_value) -} /* H5Acreate2() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A__create_by_name_api_common() */ /*-------------------------------------------------------------------------- NAME @@ -180,48 +373,97 @@ hid_t H5Acreate_by_name(hid_t loc_id, const char *obj_name, const char *attr_name, hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id, hid_t lapl_id) { - void * attr = NULL; /* attr object from VOL connector */ - H5VL_object_t * vol_obj = NULL; /* object of loc_id */ - H5VL_loc_params_t loc_params; - hid_t ret_value = H5I_INVALID_HID; /* Return value */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ FUNC_ENTER_API(H5I_INVALID_HID) H5TRACE8("i", "i*s*siiiii", loc_id, obj_name, attr_name, type_id, space_id, acpl_id, aapl_id, lapl_id); - /* Check arguments */ - if (H5I_ATTR == H5I_get_type(loc_id)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "location is not valid for an attribute") - if (!obj_name || !*obj_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "no object name") - if (!attr_name || !*attr_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "no attribute name") + /* Create the attribute synchronously */ + if ((ret_value = H5A__create_by_name_api_common(loc_id, obj_name, attr_name, type_id, space_id, acpl_id, + aapl_id, lapl_id, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCREATE, H5I_INVALID_HID, "unable to synchronously create attribute") - /* Get correct property list */ - if (H5P_DEFAULT == acpl_id) - acpl_id = H5P_ATTRIBUTE_CREATE_DEFAULT; +done: + FUNC_LEAVE_API(ret_value) +} /* H5Acreate_by_name() */ - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&aapl_id, H5P_CLS_AACC, loc_id, TRUE) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set attribute access property list info") - if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, TRUE) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set link access property list info") +/*-------------------------------------------------------------------------- + * Function: H5Acreate_by_name_async + * + * Purpose: Asynchronous version of H5Acreate_by_name + * + * Return: Success: A attribute ID + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Acreate_by_name_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *obj_name, const char *attr_name, hid_t type_id, hid_t space_id, + hid_t acpl_id, hid_t aapl_id, hid_t lapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ - /* Set up location struct */ - loc_params.type = H5VL_OBJECT_BY_NAME; - loc_params.obj_type = H5I_get_type(loc_id); - loc_params.loc_data.loc_by_name.name = obj_name; - loc_params.loc_data.loc_by_name.lapl_id = lapl_id; + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE12("i", "*s*sIui*s*siiiiii", app_file, app_func, app_line, loc_id, obj_name, attr_name, type_id, + space_id, acpl_id, aapl_id, lapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Create the attribute asynchronously */ + if ((ret_value = H5A__create_by_name_api_common(loc_id, obj_name, attr_name, type_id, space_id, acpl_id, + aapl_id, lapl_id, token_ptr, &vol_obj)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCREATE, H5I_INVALID_HID, "unable to asynchronously create attribute") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE12(FUNC, "*s*sIui*s*siiiiii", app_file, app_func, app_line, loc_id, + obj_name, attr_name, type_id, space_id, acpl_id, aapl_id, lapl_id, + es_id)) < 0) { + if (H5I_dec_app_ref(ret_value) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, H5I_INVALID_HID, "can't decrement count on attribute ID") + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ - /* Get the location object */ - if (NULL == (vol_obj = H5VL_vol_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier") +done: + FUNC_LEAVE_API(ret_value) +} /* H5Acreate_by_name_async() */ - /* Create the attribute */ - if (NULL == (attr = H5VL_attr_create(vol_obj, &loc_params, attr_name, type_id, space_id, acpl_id, aapl_id, - H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5I_INVALID_HID, "unable to create attribute") +/*------------------------------------------------------------------------- + * Function: H5A__open_common + * + * Purpose: This is the common function for opening an attribute + * + * Return: Success: A group ID + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +static hid_t +H5A__open_common(H5VL_object_t *vol_obj, H5VL_loc_params_t *loc_params, const char *attr_name, hid_t aapl_id, + void **token_ptr) +{ + void *attr = NULL; /* attr object from VOL connector */ + hid_t ret_value = H5I_INVALID_HID; - /* Register the new attribute and get an ID for it */ + FUNC_ENTER_STATIC + + /* Sanity checks */ + HDassert(vol_obj); + HDassert(loc_params); + + /* Open the attribute */ + if (NULL == + (attr = H5VL_attr_open(vol_obj, loc_params, attr_name, aapl_id, H5P_DATASET_XFER_DEFAULT, token_ptr))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open attribute: '%s'", attr_name) + + /* Register the attribute and get an ID for it */ if ((ret_value = H5VL_register(H5I_ATTR, attr, vol_obj->connector, TRUE)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register attribute for ID") @@ -231,8 +473,50 @@ done: if (attr && H5VL_attr_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close attribute") - FUNC_LEAVE_API(ret_value) -} /* H5Acreate_by_name() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A__open_common() */ + +/*------------------------------------------------------------------------- + * Function: H5A__open_api_common + * + * Purpose: This is the common function for opening an attribute + * + * Return: Success: A group ID + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +static hid_t +H5A__open_api_common(hid_t loc_id, const char *attr_name, hid_t aapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check arguments */ + if (H5I_ATTR == H5I_get_type(loc_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "location is not valid for an attribute") + if (!attr_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be NULL") + if (!*attr_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be an empty string") + + /* Set up object access arguments */ + if (H5VL_setup_acc_args(loc_id, H5P_CLS_AACC, FALSE, &aapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set object access arguments") + + /* Open the attribute */ + if ((ret_value = H5A__open_common(*vol_obj_ptr, &loc_params, attr_name, aapl_id, token_ptr)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open attribute: '%s'", attr_name) + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A__open_api_common() */ /*-------------------------------------------------------------------------- NAME @@ -256,51 +540,108 @@ done: hid_t H5Aopen(hid_t loc_id, const char *attr_name, hid_t aapl_id) { - void * attr = NULL; /* attr object from VOL connector */ - H5VL_object_t * vol_obj = NULL; /* object of loc_id */ - H5VL_loc_params_t loc_params; - hid_t ret_value = H5I_INVALID_HID; + hid_t ret_value = H5I_INVALID_HID; FUNC_ENTER_API(H5I_INVALID_HID) H5TRACE3("i", "i*si", loc_id, attr_name, aapl_id); + /* Open the attribute synchronously */ + if ((ret_value = H5A__open_api_common(loc_id, attr_name, aapl_id, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCREATE, H5I_INVALID_HID, "unable to synchronously open attribute") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Aopen() */ + +/*-------------------------------------------------------------------------- + * NAME + * H5Aopen_async + * PURPOSE + * Asynchronous version of H5Aopen + * + * RETURNS + * ID of attribute on success, H5I_INVALID_HID on failure + * + *--------------------------------------------------------------------------*/ +hid_t +H5Aopen_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *attr_name, hid_t aapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE7("i", "*s*sIui*sii", app_file, app_func, app_line, loc_id, attr_name, aapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Open the attribute asynchronously */ + if ((ret_value = H5A__open_api_common(loc_id, attr_name, aapl_id, token_ptr, &vol_obj)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCREATE, H5I_INVALID_HID, "unable to asynchronously open attribute") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE7(FUNC, "*s*sIui*sii", app_file, app_func, app_line, loc_id, attr_name, + aapl_id, es_id)) < 0) { + if (H5I_dec_app_ref(ret_value) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, H5I_INVALID_HID, "can't decrement count on attribute ID") + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Aopen_async() */ + +/*------------------------------------------------------------------------- + * Function: H5A__open_by_name_api_common + * + * Purpose: This is the common function for opening an attribute + * + * Return: Success: A group ID + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +static hid_t +H5A__open_by_name_api_common(hid_t loc_id, const char *obj_name, const char *attr_name, hid_t aapl_id, + hid_t lapl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + hid_t ret_value = H5I_INVALID_HID; + + FUNC_ENTER_STATIC + /* Check arguments */ if (H5I_ATTR == H5I_get_type(loc_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "location is not valid for an attribute") - if (!attr_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be NULL") - if (!*attr_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be an empty string") - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&aapl_id, H5P_CLS_AACC, loc_id, FALSE) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info") + if (!attr_name || !*attr_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "no attribute name") - /* Set location struct fields */ - loc_params.type = H5VL_OBJECT_BY_SELF; - loc_params.obj_type = H5I_get_type(loc_id); + /* obj_name is verified in H5VL_setup_name_args() */ + /* Set up object access arguments */ + if (H5VL_setup_name_args(loc_id, obj_name, H5P_CLS_LACC, FALSE, lapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set object access arguments") - /* Get the location object */ - if (NULL == (vol_obj = H5VL_vol_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier") + /* Verify access property list and set up collective metadata if appropriate */ + if (H5CX_set_apl(&aapl_id, H5P_CLS_AACC, loc_id, FALSE) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set attribute access property list info") /* Open the attribute */ - if (NULL == (attr = H5VL_attr_open(vol_obj, &loc_params, attr_name, aapl_id, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL))) + if ((ret_value = H5A__open_common(*vol_obj_ptr, &loc_params, attr_name, aapl_id, token_ptr)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open attribute: '%s'", attr_name) - /* Register the attribute and get an ID for it */ - if ((ret_value = H5VL_register(H5I_ATTR, attr, vol_obj->connector, TRUE)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register attribute for ID") - done: - /* Cleanup on failure */ - if (H5I_INVALID_HID == ret_value) - if (attr && H5VL_attr_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) - HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close attribute") - - FUNC_LEAVE_API(ret_value) -} /* H5Aopen() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A__open_by_name_api_common() */ /*-------------------------------------------------------------------------- NAME @@ -326,55 +667,115 @@ done: hid_t H5Aopen_by_name(hid_t loc_id, const char *obj_name, const char *attr_name, hid_t aapl_id, hid_t lapl_id) { - void * attr = NULL; /* attr object from VOL connector */ - H5VL_object_t * vol_obj = NULL; /* object of loc_id */ - H5VL_loc_params_t loc_params; - hid_t ret_value = H5I_INVALID_HID; + hid_t ret_value = H5I_INVALID_HID; FUNC_ENTER_API(H5I_INVALID_HID) H5TRACE5("i", "i*s*sii", loc_id, obj_name, attr_name, aapl_id, lapl_id); + /* Open the attribute by name asynchronously */ + if ((ret_value = + H5A__open_by_name_api_common(loc_id, obj_name, attr_name, aapl_id, lapl_id, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to synchronously open attribute") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Aopen_by_name() */ + +/*-------------------------------------------------------------------------- + * NAME + * H5Aopen_by_name_async + * PURPOSE + * Asynchronous version of H5Aopen_by_name + * + * RETURNS + * ID of attribute on success, H5I_INVALID_HID on failure + * + *--------------------------------------------------------------------------*/ +hid_t +H5Aopen_by_name_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *obj_name, const char *attr_name, hid_t aapl_id, hid_t lapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE9("i", "*s*sIui*s*siii", app_file, app_func, app_line, loc_id, obj_name, attr_name, aapl_id, + lapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Open the attribute by name asynchronously */ + if ((ret_value = H5A__open_by_name_api_common(loc_id, obj_name, attr_name, aapl_id, lapl_id, token_ptr, + &vol_obj)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to asynchronously open attribute") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE9(FUNC, "*s*sIui*s*siii", app_file, app_func, app_line, loc_id, obj_name, + attr_name, aapl_id, lapl_id, es_id)) < 0) { + if (H5I_dec_app_ref(ret_value) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, H5I_INVALID_HID, "can't decrement count on attribute ID") + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Aopen_by_name_async() */ + +/*------------------------------------------------------------------------- + * Function: H5A__open_by_idx_api_common + * + * Purpose: This is the common function for opening an attribute + * + * Return: Success: A group ID + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +static hid_t +H5A__open_by_idx_api_common(hid_t loc_id, const char *obj_name, H5_index_t idx_type, H5_iter_order_t order, + hsize_t n, hid_t aapl_id, hid_t lapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + hid_t ret_value = H5I_INVALID_HID; + + FUNC_ENTER_STATIC + /* Check arguments */ if (H5I_ATTR == H5I_get_type(loc_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "location is not valid for an attribute") if (!obj_name || !*obj_name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "no object name") - if (!attr_name || !*attr_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "no attribute name") + if (idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid index type specified") + if (order <= H5_ITER_UNKNOWN || order >= H5_ITER_N) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid iteration order specified") + + /* Set up object access arguments */ + if (H5VL_setup_idx_args(loc_id, obj_name, idx_type, order, n, H5P_CLS_LACC, FALSE, lapl_id, vol_obj_ptr, + &loc_params) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set object access arguments") /* Verify access property list and set up collective metadata if appropriate */ if (H5CX_set_apl(&aapl_id, H5P_CLS_AACC, loc_id, FALSE) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set attribute access property list info") - if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set link access property list info") - - /* Fill in location struct fields */ - loc_params.type = H5VL_OBJECT_BY_NAME; - loc_params.loc_data.loc_by_name.name = obj_name; - loc_params.loc_data.loc_by_name.lapl_id = lapl_id; - loc_params.obj_type = H5I_get_type(loc_id); - - /* Get the location object */ - if (NULL == (vol_obj = H5VL_vol_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier") /* Open the attribute */ - if (NULL == (attr = H5VL_attr_open(vol_obj, &loc_params, attr_name, aapl_id, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "can't open attribute") - - /* Register the attribute and get an ID for it */ - if ((ret_value = H5VL_register(H5I_ATTR, attr, vol_obj->connector, TRUE)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register attribute handle") + if ((ret_value = H5A__open_common(*vol_obj_ptr, &loc_params, NULL, aapl_id, token_ptr)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open attribute") done: - /* Cleanup on failure */ - if (H5I_INVALID_HID == ret_value) - if (attr && H5VL_attr_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) - HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close attribute") - - FUNC_LEAVE_API(ret_value) -} /* end H5Aopen_by_name() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A__open_by_idx_api_common() */ /*-------------------------------------------------------------------------- NAME @@ -404,60 +805,103 @@ hid_t H5Aopen_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t aapl_id, hid_t lapl_id) { - void * attr = NULL; /* Attribute opened */ - H5VL_object_t * vol_obj = NULL; /* object of loc_id */ - H5VL_loc_params_t loc_params; - hid_t ret_value = H5I_INVALID_HID; /* Return value */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ FUNC_ENTER_API(H5I_INVALID_HID) H5TRACE7("i", "i*sIiIohii", loc_id, obj_name, idx_type, order, n, aapl_id, lapl_id); - /* Check arguments */ - if (H5I_ATTR == H5I_get_type(loc_id)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "location is not valid for an attribute") - if (!obj_name || !*obj_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "no object name") - if (idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid index type specified") - if (order <= H5_ITER_UNKNOWN || order >= H5_ITER_N) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid iteration order specified") + /* Open the attribute by idx synchronously */ + if ((ret_value = H5A__open_by_idx_api_common(loc_id, obj_name, idx_type, order, n, aapl_id, lapl_id, NULL, + NULL)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCREATE, H5I_INVALID_HID, "unable to synchronously open attribute") - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&aapl_id, H5P_CLS_AACC, loc_id, FALSE) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set attribute access property list info") - if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set link access property list info") +done: + FUNC_LEAVE_API(ret_value) +} /* H5Aopen_by_idx() */ - /* Fill in location struct parameters */ - loc_params.type = H5VL_OBJECT_BY_IDX; - loc_params.loc_data.loc_by_idx.name = obj_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); +/*-------------------------------------------------------------------------- + * NAME + * H5Aopen_by_idx_async + * PURPOSE + * Asynchronous version of H5Aopen_by_idx + * + * RETURNS + * ID of attribute on success, H5I_INVALID_HID on failure + * + *--------------------------------------------------------------------------*/ +hid_t +H5Aopen_by_idx_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *obj_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, + hid_t aapl_id, hid_t lapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; - /* Get the location object */ - if (NULL == (vol_obj = H5VL_vol_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier") + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE11("i", "*s*sIui*sIiIohiii", app_file, app_func, app_line, loc_id, obj_name, idx_type, order, n, + aapl_id, lapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Open the attribute by idx asynchronously */ + if ((ret_value = H5A__open_by_idx_api_common(loc_id, obj_name, idx_type, order, n, aapl_id, lapl_id, + token_ptr, &vol_obj)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCREATE, H5I_INVALID_HID, "unable to asynchronously open attribute") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE11(FUNC, "*s*sIui*sIiIohiii", app_file, app_func, app_line, loc_id, + obj_name, idx_type, order, n, aapl_id, lapl_id, es_id)) < 0) { + if (H5I_dec_app_ref(ret_value) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, H5I_INVALID_HID, "can't decrement count on attribute ID") + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ - /* Open the attribute */ - if (NULL == (attr = H5VL_attr_open(vol_obj, &loc_params, NULL, aapl_id, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open attribute") +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Aopen_by_idx_async() */ - /* Register the attribute and get an ID for it */ - if ((ret_value = H5VL_register(H5I_ATTR, attr, vol_obj->connector, TRUE)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register attribute handle") +/*-------------------------------------------------------------------------- + NAME + H5A__write_api_common + PURPOSE + Common helper routine for sync/async dataset write operations. + RETURNS + Non-negative on success/Negative on failure +--------------------------------------------------------------------------*/ +static herr_t +H5A__write_api_common(hid_t attr_id, hid_t type_id, const void *buf, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + herr_t ret_value = SUCCEED; /* Return value */ -done: - /* Cleanup on failure */ - if (H5I_INVALID_HID == ret_value) - if (attr && H5VL_attr_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) - HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close attribute") + FUNC_ENTER_STATIC - FUNC_LEAVE_API(ret_value) -} /* H5Aopen_by_idx() */ + /* Check arguments */ + if (H5I_DATATYPE != H5I_get_type(type_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") + if (NULL == buf) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "buf parameter can't be NULL") + + /* Get attribute pointer */ + if (H5VL_setup_args(attr_id, H5I_ATTR, vol_obj_ptr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get VOL object for attribute") + + /* Write the attribute data */ + if (H5VL_attr_write(*vol_obj_ptr, type_id, buf, H5P_DATASET_XFER_DEFAULT, token_ptr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "unable to write attribute") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A__write_api_common() */ /*-------------------------------------------------------------------------- NAME @@ -478,31 +922,93 @@ done: herr_t H5Awrite(hid_t attr_id, hid_t dtype_id, const void *buf) { - H5VL_object_t *vol_obj; /* Attribute object for ID */ - herr_t ret_value; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE3("e", "ii*x", attr_id, dtype_id, buf); + /* Synchronously write the data */ + if (H5A__write_api_common(attr_id, dtype_id, buf, NULL, NULL) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "can't synchronously write data") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Awrite() */ + +/*-------------------------------------------------------------------------- + NAME + H5Awrite_async + PURPOSE + Asynchronous version of H5Awrite + RETURNS + Non-negative on success/Negative on failure +--------------------------------------------------------------------------*/ +herr_t +H5Awrite_async(const char *app_file, const char *app_func, unsigned app_line, hid_t attr_id, hid_t dtype_id, + const void *buf, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for attr_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE7("e", "*s*sIuii*xi", app_file, app_func, app_line, attr_id, dtype_id, buf, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Asynchronously write the data */ + if (H5A__write_api_common(attr_id, dtype_id, buf, token_ptr, &vol_obj) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "can't asynchronously write data") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE7(FUNC, "*s*sIuii*xi", app_file, app_func, app_line, attr_id, dtype_id, + buf, es_id)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Awrite_async() */ + +/*-------------------------------------------------------------------------- + * NAME + * H5A__read_api_common + * PURPOSE + * Common helper routine for sync/async attribute read operations. + * RETURNS + * Non-negative on success/Negative on failure + *--------------------------------------------------------------------------*/ +static herr_t +H5A__read_api_common(hid_t attr_id, hid_t dtype_id, void *buf, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + /* Check arguments */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(attr_id, H5I_ATTR))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute") if (H5I_DATATYPE != H5I_get_type(dtype_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") if (NULL == buf) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "buf parameter can't be NULL") - /* Set up collective metadata if appropriate */ - if (H5CX_set_loc(attr_id) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set collective metadata read") + /* Get attribute object pointer */ + if (NULL == (*vol_obj_ptr = (H5VL_object_t *)H5I_object_verify(attr_id, H5I_ATTR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute") - /* Write the attribute data */ - if ((ret_value = H5VL_attr_write(vol_obj, dtype_id, buf, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "unable to write attribute") + /* Read the attribute data */ + if (H5VL_attr_read(*vol_obj_ptr, dtype_id, buf, H5P_DATASET_XFER_DEFAULT, token_ptr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_READERROR, FAIL, "unable to read attribute") done: - FUNC_LEAVE_API(ret_value) -} /* H5Awrite() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A__read_api_common() */ /*-------------------------------------------------------------------------- NAME @@ -523,29 +1029,59 @@ done: herr_t H5Aread(hid_t attr_id, hid_t dtype_id, void *buf /*out*/) { - H5VL_object_t *vol_obj; /* Attribute object for ID */ - herr_t ret_value; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE3("e", "iix", attr_id, dtype_id, buf); - /* Check arguments */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(attr_id, H5I_ATTR))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute") - if (H5I_DATATYPE != H5I_get_type(dtype_id)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") - if (NULL == buf) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "buf parameter can't be NULL") - - /* Read the attribute data */ - if ((ret_value = H5VL_attr_read(vol_obj, dtype_id, buf, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_READERROR, FAIL, "unable to read attribute") + /* Synchronously read the data */ + if (H5A__read_api_common(attr_id, dtype_id, buf, NULL, NULL) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_READERROR, FAIL, "can't synchronously read data") done: FUNC_LEAVE_API(ret_value) } /* H5Aread() */ /*-------------------------------------------------------------------------- + * NAME + * H5Aread_async + * PURPOSE + * Asynchronous version of H5Aread + * RETURNS + * Non-negative on success/Negative on failure + *--------------------------------------------------------------------------*/ +herr_t +H5Aread_async(const char *app_file, const char *app_func, unsigned app_line, hid_t attr_id, hid_t dtype_id, + void *buf, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for attr_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE7("e", "*s*sIuii*xi", app_file, app_func, app_line, attr_id, dtype_id, buf, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Asynchronously read the data */ + if (H5A__read_api_common(attr_id, dtype_id, buf, token_ptr, &vol_obj) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_READERROR, FAIL, "can't asynchronously read data") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE7(FUNC, "*s*sIuii*xi", app_file, app_func, app_line, attr_id, dtype_id, + buf, es_id)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Aread_async() */ + +/*-------------------------------------------------------------------------- NAME H5Aget_space PURPOSE @@ -976,6 +1512,84 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Aget_info_by_idx() */ +/*-------------------------------------------------------------------------- + NAME + H5A__rename_common + PURPOSE + Common helper routine for sync/async attribute rename operations + RETURNS + Non-negative on success/Negative on failure +--------------------------------------------------------------------------*/ +static herr_t +H5A__rename_common(H5VL_object_t *vol_obj, H5VL_loc_params_t *loc_params, const char *old_name, + const char *new_name, void **token_ptr) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity checks */ + HDassert(vol_obj); + HDassert(loc_params); + HDassert(old_name); + HDassert(new_name); + + /* Avoid thrashing things if the names are the same */ + if (HDstrcmp(old_name, new_name)) + /* Rename the attribute */ + if (H5VL_attr_specific(vol_obj, loc_params, H5VL_ATTR_RENAME, H5P_DATASET_XFER_DEFAULT, token_ptr, + old_name, new_name) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute from '%s' to '%s'", old_name, + new_name) + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A__rename_common() */ + +/*-------------------------------------------------------------------------- + NAME + H5A__rename_api_common + PURPOSE + Common helper routine for sync/async attribute rename operations + RETURNS + Non-negative on success/Negative on failure +--------------------------------------------------------------------------*/ +static herr_t +H5A__rename_api_common(hid_t loc_id, const char *old_name, const char *new_name, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check arguments */ + if (H5I_ATTR == H5I_get_type(loc_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") + if (!old_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "old attribute name cannot be NULL") + if (!*old_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "old attribute name cannot be an empty string") + if (!new_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "new attribute name cannot be NULL") + if (!*new_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "new attribute name cannot be an empty string") + + /* Set up object access arguments */ + if (H5VL_setup_loc_args(loc_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set object access arguments") + + /* Rename the attribute */ + if (H5A__rename_common(*vol_obj_ptr, &loc_params, old_name, new_name, token_ptr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A__rename_api_common() */ + /*------------------------------------------------------------------------- * Function: H5Arename * @@ -997,9 +1611,77 @@ H5Arename(hid_t loc_id, const char *old_name, const char *new_name) FUNC_ENTER_API(FAIL) H5TRACE3("e", "i*s*s", loc_id, old_name, new_name); + /* Synchronously rename the attribute */ + if (H5A__rename_api_common(loc_id, old_name, new_name, NULL, NULL) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't synchronously rename attribute") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Arename() */ + +/*-------------------------------------------------------------------------- + * NAME + * H5Arename_async + * PURPOSE + * Asynchronous version of H5Arename + * RETURNS + * Non-negative on success/Negative on failure + *--------------------------------------------------------------------------*/ +herr_t +H5Arename_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *old_name, const char *new_name, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE7("e", "*s*sIui*s*si", app_file, app_func, app_line, loc_id, old_name, new_name, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Asynchronously rename the attribute */ + if (H5A__rename_api_common(loc_id, old_name, new_name, token_ptr, &vol_obj) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't asynchronously rename attribute") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE7(FUNC, "*s*sIui*s*si", app_file, app_func, app_line, loc_id, old_name, + new_name, es_id)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Arename_async() */ + +/*-------------------------------------------------------------------------- + NAME + H5A__rename_by_name_api_common + PURPOSE + Common helper routine for sync/async attribute rename operations + RETURNS + Non-negative on success/Negative on failure +--------------------------------------------------------------------------*/ +static herr_t +H5A__rename_by_name_api_common(hid_t loc_id, const char *obj_name, const char *old_name, const char *new_name, + hid_t lapl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + /* Check arguments */ if (H5I_ATTR == H5I_get_type(loc_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") + if (!old_name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "old attribute name cannot be NULL") if (!*old_name) @@ -1009,30 +1691,18 @@ H5Arename(hid_t loc_id, const char *old_name, const char *new_name) if (!*new_name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "new attribute name cannot be an empty string") - /* Avoid thrashing things if the names are the same */ - if (HDstrcmp(old_name, new_name)) { - H5VL_object_t * vol_obj; - H5VL_loc_params_t loc_params; - - loc_params.type = H5VL_OBJECT_BY_SELF; - loc_params.obj_type = H5I_get_type(loc_id); - - if (NULL == (vol_obj = H5VL_vol_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") + /* obj_name is verified in H5VL_setup_name_args() */ + /* Set up object access arguments */ + if (H5VL_setup_name_args(loc_id, obj_name, H5P_CLS_LACC, TRUE, lapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set object access arguments") - /* Set up collective metadata if appropriate */ - if (H5CX_set_loc(loc_id) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set collective metadata read") - - /* Rename the attribute */ - if (H5VL_attr_specific(vol_obj, &loc_params, H5VL_ATTR_RENAME, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL, old_name, new_name) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute") - } /* end if */ + /* Rename the attribute */ + if (H5A__rename_common(*vol_obj_ptr, &loc_params, old_name, new_name, token_ptr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute") done: - FUNC_LEAVE_API(ret_value) -} /* H5Arename() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A__rename_by_name_api_common() */ /*------------------------------------------------------------------------- * Function: H5Arename_by_name @@ -1056,43 +1726,56 @@ H5Arename_by_name(hid_t loc_id, const char *obj_name, const char *old_attr_name, FUNC_ENTER_API(FAIL) H5TRACE5("e", "i*s*s*si", loc_id, obj_name, old_attr_name, new_attr_name, lapl_id); - /* check arguments */ - if (H5I_ATTR == H5I_get_type(loc_id)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") - if (!obj_name || !*obj_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no object name") - if (!old_attr_name || !*old_attr_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no old attribute name") - if (!new_attr_name || !*new_attr_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no new attribute name") + /* Synchronously rename the attribute */ + if (H5A__rename_by_name_api_common(loc_id, obj_name, old_attr_name, new_attr_name, lapl_id, NULL, NULL) < + 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't synchronously rename attribute") - /* Avoid thrashing things if the names are the same */ - if (HDstrcmp(old_attr_name, new_attr_name)) { - H5VL_object_t * vol_obj; - H5VL_loc_params_t loc_params; +done: + FUNC_LEAVE_API(ret_value) +} /* H5Arename_by_name() */ + +/*-------------------------------------------------------------------------- + * NAME + * H5Arename_by_name_async + * PURPOSE + * Asynchronous version of H5Arename_by_name + * RETURNS + * Non-negative on success/Negative on failure + *--------------------------------------------------------------------------*/ +herr_t +H5Arename_by_name_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *obj_name, const char *old_attr_name, const char *new_attr_name, + hid_t lapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, TRUE) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set access property list info") + FUNC_ENTER_API(FAIL) + H5TRACE9("e", "*s*sIui*s*s*sii", app_file, app_func, app_line, loc_id, obj_name, old_attr_name, + new_attr_name, lapl_id, es_id); - loc_params.type = H5VL_OBJECT_BY_NAME; - loc_params.loc_data.loc_by_name.name = obj_name; - loc_params.loc_data.loc_by_name.lapl_id = lapl_id; - loc_params.obj_type = H5I_get_type(loc_id); + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ - /* Get the location object */ - if (NULL == (vol_obj = H5VL_vol_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") + /* Asynchronously rename the attribute */ + if (H5A__rename_by_name_api_common(loc_id, obj_name, old_attr_name, new_attr_name, lapl_id, token_ptr, + &vol_obj) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't synchronously rename attribute") - /* Rename the attribute */ - if (H5VL_attr_specific(vol_obj, &loc_params, H5VL_ATTR_RENAME, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL, old_attr_name, new_attr_name) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute") - } /* end if */ + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE9(FUNC, "*s*sIui*s*s*sii", app_file, app_func, app_line, loc_id, obj_name, + old_attr_name, new_attr_name, lapl_id, es_id)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "can't insert token into event set") done: FUNC_LEAVE_API(ret_value) -} /* H5Arename_by_name() */ +} /* H5Arename_by_name_async() */ /*-------------------------------------------------------------------------- NAME @@ -1136,8 +1819,8 @@ done: attribute. --------------------------------------------------------------------------*/ herr_t -H5Aiterate2(hid_t loc_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx /*in,out */, H5A_operator2_t op, - void *op_data) +H5Aiterate2(hid_t loc_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx /*in,out */, + H5A_operator2_t op, void *op_data) { H5VL_object_t * vol_obj = NULL; /* object of loc_id */ H5VL_loc_params_t loc_params; @@ -1470,6 +2153,138 @@ done: } /* H5Aclose() */ /*------------------------------------------------------------------------- + * Function: H5Aclose_async + * + * Purpose: Asynchronous version of H5Aclose + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5Aclose_async(const char *app_file, const char *app_func, unsigned app_line, hid_t attr_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + H5VL_t * connector = NULL; /* VOL connector */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "*s*sIuii", app_file, app_func, app_line, attr_id, es_id); + + /* Check arguments */ + if (H5I_ATTR != H5I_get_type(attr_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a attribute ID") + + /* Prepare for possible asynchronous operation */ + if (H5ES_NONE != es_id) { + /* Get attribute object's connector */ + if (NULL == (vol_obj = H5VL_vol_object(attr_id))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get VOL object for attribute") + + /* Increase connector's refcount, so it doesn't get closed if closing + * the attribute closes the file */ + connector = vol_obj->connector; + H5VL_conn_inc_rc(connector); + + /* Point at token for operation to set up */ + token_ptr = &token; + } /* end if */ + + /* Decrement the counter on the attribute ID. It will be freed if the count + * reaches zero. + */ + if (H5I_dec_app_ref_async(attr_id, token_ptr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "decrementing attribute ID failed") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE5(FUNC, "*s*sIuii", app_file, app_func, app_line, attr_id, es_id)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + if (connector && H5VL_conn_dec_rc(connector) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "can't decrement ref count on connector") + + FUNC_LEAVE_API(ret_value) +} /* H5Aclose_async() */ + +/*-------------------------------------------------------------------------- + * NAME + * H5A__exists_common + * PURPOSE + * Common helper routine for sync/async check if an attribute exists + * RETURNS + * Non-negative on success/Negative on failure + *--------------------------------------------------------------------------*/ +static herr_t +H5A__exists_common(H5VL_object_t *vol_obj, H5VL_loc_params_t *loc_params, const char *attr_name, + hbool_t *attr_exists, void **token_ptr) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity checks */ + HDassert(vol_obj); + HDassert(loc_params); + + /* Check arguments */ + if (!attr_name || !*attr_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no attribute name") + + /* Check if the attribute exists */ + if (H5VL_attr_specific(vol_obj, loc_params, H5VL_ATTR_EXISTS, H5P_DATASET_XFER_DEFAULT, token_ptr, + attr_name, attr_exists) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to determine if attribute exists") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A__exists_common() */ + +/*-------------------------------------------------------------------------- + * NAME + * H5A__exists_api_common + * PURPOSE + * Common helper routine for sync/async check if an attribute exists + * RETURNS + * Non-negative on success/Negative on failure + *--------------------------------------------------------------------------*/ +static herr_t +H5A__exists_api_common(hid_t obj_id, const char *attr_name, hbool_t *attr_exists, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check arguments */ + if (H5I_ATTR == H5I_get_type(obj_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") + if (!attr_name || !*attr_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no attribute name") + if (NULL == attr_exists) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid pointer for attribute existence") + + /* Set up object access arguments */ + if (H5VL_setup_self_args(obj_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set object access arguments") + + /* Check if the attribute exists */ + if (H5A__exists_common(*vol_obj_ptr, &loc_params, attr_name, attr_exists, token_ptr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to determine if attribute exists") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A__exists_api_common() */ + +/*------------------------------------------------------------------------- * Function: H5Aexists * * Purpose: Checks if an attribute with a given name exists on an opened @@ -1486,34 +2301,104 @@ done: htri_t H5Aexists(hid_t obj_id, const char *attr_name) { - H5VL_object_t * vol_obj; - H5VL_loc_params_t loc_params; - htri_t ret_value; /* Return value */ + hbool_t exists; /* Flag for attribute existance */ + htri_t ret_value = FAIL; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE2("t", "i*s", obj_id, attr_name); + /* Synchronously check if an attribute exists */ + exists = FALSE; + if (H5A__exists_api_common(obj_id, attr_name, &exists, NULL, NULL) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't synchronously rename attribute") + + /* Set return value */ + ret_value = (htri_t)exists; + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Aexists() */ + +/*-------------------------------------------------------------------------- + * NAME + * H5Aexists_async + * PURPOSE + * Asynchronous version of H5Aexists + * RETURNS + * Non-negative on success/Negative on failure + *--------------------------------------------------------------------------*/ +herr_t +H5Aexists_async(const char *app_file, const char *app_func, unsigned app_line, hid_t obj_id, + const char *attr_name, hbool_t *attr_exists, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE7("e", "*s*sIui*s*bi", app_file, app_func, app_line, obj_id, attr_name, attr_exists, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Asynchronously check if an attribute exists */ + if (H5A__exists_api_common(obj_id, attr_name, attr_exists, token_ptr, &vol_obj) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't asynchronously check if attribute exists") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE7(FUNC, "*s*sIui*s*bi", app_file, app_func, app_line, obj_id, attr_name, + attr_exists, es_id)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Aexists_async() */ + +/*-------------------------------------------------------------------------- + * NAME + * H5A__exists_by_name_api_common + * PURPOSE + * Common helper routine for sync/async check if an attribute exists + * RETURNS + * Non-negative on success/Negative on failure + *--------------------------------------------------------------------------*/ +static herr_t +H5A__exists_by_name_api_common(hid_t loc_id, const char *obj_name, const char *attr_name, + hbool_t *attr_exists, hid_t lapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + /* Check arguments */ - if (H5I_ATTR == H5I_get_type(obj_id)) + if (H5I_ATTR == H5I_get_type(loc_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") if (!attr_name || !*attr_name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no attribute name") + if (NULL == attr_exists) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid pointer for attribute existence") - /* get the object */ - if (NULL == (vol_obj = H5VL_vol_object(obj_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier") - - loc_params.type = H5VL_OBJECT_BY_SELF; - loc_params.obj_type = H5I_get_type(obj_id); + /* obj_name is verified in H5VL_setup_name_args() */ + /* Set up object access arguments */ + if (H5VL_setup_name_args(loc_id, obj_name, H5P_CLS_LACC, FALSE, lapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set object access arguments") /* Check if the attribute exists */ - if (H5VL_attr_specific(vol_obj, &loc_params, H5VL_ATTR_EXISTS, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, - attr_name, &ret_value) < 0) + if (H5A__exists_common(*vol_obj_ptr, &loc_params, attr_name, attr_exists, token_ptr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to determine if attribute exists") done: - FUNC_LEAVE_API(ret_value) -} /* H5Aexists() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A__exists_by_name_api_common() */ /*------------------------------------------------------------------------- * Function: H5Aexists_by_name @@ -1521,7 +2406,7 @@ done: * Purpose: Checks if an attribute with a given name exists on an object. * * Return: Success: TRUE/FALSE - * Failure: Negative + * Failure: Negative * * Programmer: Quincey Koziol * Thursday, November 1, 2007 @@ -1531,39 +2416,62 @@ done: htri_t H5Aexists_by_name(hid_t loc_id, const char *obj_name, const char *attr_name, hid_t lapl_id) { - H5VL_object_t * vol_obj; - H5VL_loc_params_t loc_params; - htri_t ret_value; /* Return value */ + hbool_t exists; /* Flag for attribute existance */ + htri_t ret_value = FAIL; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE4("t", "i*s*si", loc_id, obj_name, attr_name, lapl_id); - /* check arguments */ - if (H5I_ATTR == H5I_get_type(loc_id)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") - if (!obj_name || !*obj_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no object name") - if (!attr_name || !*attr_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no attribute name") + /* Synchronously check if an attribute exists */ + exists = FALSE; + if (H5A__exists_by_name_api_common(loc_id, obj_name, attr_name, &exists, lapl_id, NULL, NULL) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't synchronously rename attribute") - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set access property list info") + /* Set return value */ + ret_value = (htri_t)exists; - /* get the object */ - if (NULL == (vol_obj = H5VL_vol_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier") +done: + FUNC_LEAVE_API(ret_value) +} /* H5Aexists_by_name() */ - loc_params.type = H5VL_OBJECT_BY_NAME; - loc_params.loc_data.loc_by_name.name = obj_name; - loc_params.loc_data.loc_by_name.lapl_id = lapl_id; - loc_params.obj_type = H5I_get_type(loc_id); +/*-------------------------------------------------------------------------- + * NAME + * H5Aexists_by_name_async + * PURPOSE + * Asynchronous version of H5Aexists_by_name + * RETURNS + * Non-negative on success/Negative on failure + *--------------------------------------------------------------------------*/ +herr_t +H5Aexists_by_name_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *obj_name, const char *attr_name, hbool_t *attr_exists, hid_t lapl_id, + hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ - /* Check existence of attribute */ - if (H5VL_attr_specific(vol_obj, &loc_params, H5VL_ATTR_EXISTS, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, - attr_name, &ret_value) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to determine if attribute exists") + FUNC_ENTER_API(FAIL) + H5TRACE9("e", "*s*sIui*s*s*bii", app_file, app_func, app_line, loc_id, obj_name, attr_name, attr_exists, + lapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Asynchronously check if an attribute exists */ + if (H5A__exists_by_name_api_common(loc_id, obj_name, attr_name, attr_exists, lapl_id, token_ptr, + &vol_obj) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't asynchronously rename attribute") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE9(FUNC, "*s*sIui*s*s*bii", app_file, app_func, app_line, loc_id, obj_name, + attr_name, attr_exists, lapl_id, es_id)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "can't insert token into event set") done: FUNC_LEAVE_API(ret_value) -} /* H5Aexists_by_name() */ +} /* H5Aexists_by_name_async() */ diff --git a/src/H5Adense.c b/src/H5Adense.c index 1efe45d..69f2a15 100644 --- a/src/H5Adense.c +++ b/src/H5Adense.c @@ -338,7 +338,7 @@ H5A__dense_open(H5F_t *f, const H5O_ainfo_t *ainfo, const char *name) H5HF_t * shared_fheap = NULL; /* Fractal heap handle for shared header messages */ H5B2_t * bt2_name = NULL; /* v2 B-tree handle for name index */ htri_t attr_sharable; /* Flag indicating attributes are sharable */ - htri_t attr_exists; /* Attribute exists in v2 B-tree */ + hbool_t attr_exists; /* Attribute exists in v2 B-tree */ H5A_t * ret_value = NULL; /* Return value */ FUNC_ENTER_PACKAGE @@ -388,9 +388,10 @@ H5A__dense_open(H5F_t *f, const H5O_ainfo_t *ainfo, const char *name) udata.found_op_data = &ret_value; /* Find & copy the attribute in the 'name' index */ - if ((attr_exists = H5B2_find(bt2_name, &udata, NULL, NULL)) < 0) + attr_exists = FALSE; + if (H5B2_find(bt2_name, &udata, &attr_exists, NULL, NULL) < 0) HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "can't search for attribute in name index") - else if (attr_exists == FALSE) + if (attr_exists == FALSE) HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "can't locate attribute in name index") done: @@ -866,7 +867,7 @@ H5A__dense_rename(H5F_t *f, const H5O_ainfo_t *ainfo, const char *old_name, cons H5A_t * attr_copy = NULL; /* Copy of attribute to rename */ htri_t attr_sharable; /* Flag indicating attributes are sharable */ htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */ - htri_t attr_exists; /* Attribute exists in v2 B-tree */ + hbool_t attr_exists; /* Attribute exists in v2 B-tree */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -917,9 +918,10 @@ H5A__dense_rename(H5F_t *f, const H5O_ainfo_t *ainfo, const char *old_name, cons udata.found_op_data = &attr_copy; /* Get copy of attribute through 'name' tracking v2 B-tree */ - if ((attr_exists = H5B2_find(bt2_name, &udata, NULL, NULL)) < 0) + attr_exists = FALSE; + if (H5B2_find(bt2_name, &udata, &attr_exists, NULL, NULL) < 0) HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't search for attribute in name index") - else if (attr_exists == FALSE) + if (attr_exists == FALSE) HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't locate attribute in name index") HDassert(attr_copy); @@ -942,7 +944,7 @@ H5A__dense_rename(H5F_t *f, const H5O_ainfo_t *ainfo, const char *old_name, cons /* Need to remove the attribute from the creation order index v2 B-tree */ if (ainfo->index_corder) { - htri_t corder_attr_exists; /* Attribute exists in v2 B-tree */ + hbool_t corder_attr_exists; /* Attribute exists in v2 B-tree */ /* Open the creation order index v2 B-tree */ HDassert(H5F_addr_defined(ainfo->corder_bt2_addr)); @@ -952,7 +954,8 @@ H5A__dense_rename(H5F_t *f, const H5O_ainfo_t *ainfo, const char *old_name, cons /* Set up the creation order to search for */ udata.corder = attr_copy->shared->crt_idx; - if ((corder_attr_exists = H5B2_find(bt2_corder, &udata, NULL, NULL)) < 0) + corder_attr_exists = FALSE; + if (H5B2_find(bt2_corder, &udata, &corder_attr_exists, NULL, NULL) < 0) HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't search for attribute in name index") if (corder_attr_exists) { @@ -1665,15 +1668,15 @@ done: * *------------------------------------------------------------------------- */ -htri_t -H5A__dense_exists(H5F_t *f, const H5O_ainfo_t *ainfo, const char *name) +herr_t +H5A__dense_exists(H5F_t *f, const H5O_ainfo_t *ainfo, const char *name, hbool_t *attr_exists) { H5A_bt2_ud_common_t udata; /* User data for v2 B-tree modify */ H5HF_t * fheap = NULL; /* Fractal heap handle */ H5HF_t * shared_fheap = NULL; /* Fractal heap handle for shared header messages */ H5B2_t * bt2_name = NULL; /* v2 B-tree handle for name index */ htri_t attr_sharable; /* Flag indicating attributes are sharable */ - htri_t ret_value = TRUE; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -1681,6 +1684,7 @@ H5A__dense_exists(H5F_t *f, const H5O_ainfo_t *ainfo, const char *name) HDassert(f); HDassert(ainfo); HDassert(name); + HDassert(attr_exists); /* Open the fractal heap */ if (NULL == (fheap = H5HF_open(f, ainfo->fheap_addr))) @@ -1722,7 +1726,7 @@ H5A__dense_exists(H5F_t *f, const H5O_ainfo_t *ainfo, const char *name) udata.found_op_data = NULL; /* Find the attribute in the 'name' index */ - if ((ret_value = H5B2_find(bt2_name, &udata, NULL, NULL)) < 0) + if (H5B2_find(bt2_name, &udata, attr_exists, NULL, NULL) < 0) HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't search for attribute in name index") done: diff --git a/src/H5Aint.c b/src/H5Aint.c index 9b24950..de9d36a 100644 --- a/src/H5Aint.c +++ b/src/H5Aint.c @@ -294,7 +294,7 @@ H5A__create(const H5G_loc_t *loc, const char *attr_name, const H5T_t *type, cons H5A_t * attr = NULL; /* Attribute created */ hssize_t snelmts; /* elements in attribute */ size_t nelmts; /* elements in attribute */ - htri_t exists; /* Whether attribute exists */ + hbool_t exists; /* Whether attribute exists */ H5A_t * ret_value = NULL; /* Return value */ FUNC_ENTER_PACKAGE_TAG(loc->oloc->addr) @@ -310,9 +310,10 @@ H5A__create(const H5G_loc_t *loc, const char *attr_name, const H5T_t *type, cons * name, but it's going to be hard to unwind all the special cases on * failure, so just check first, for now - QAK) */ - if ((exists = H5O__attr_exists(loc->oloc, attr_name)) < 0) + exists = FALSE; + if (H5O__attr_exists(loc->oloc, attr_name, &exists) < 0) HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "error checking attributes") - else if (exists > 0) + if (exists) HGOTO_ERROR(H5E_ATTR, H5E_ALREADYEXISTS, NULL, "attribute already exists") /* Check if the dataspace has an extent set (or is NULL) */ @@ -1467,20 +1468,21 @@ done: * *------------------------------------------------------------------------- */ -htri_t -H5A__exists_by_name(H5G_loc_t loc, const char *obj_name, const char *attr_name) +herr_t +H5A__exists_by_name(H5G_loc_t loc, const char *obj_name, const char *attr_name, hbool_t *attr_exists) { - H5G_loc_t obj_loc; /* Location used to open group */ - H5G_name_t obj_path; /* Opened object group hier. path */ - H5O_loc_t obj_oloc; /* Opened object object location */ - hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */ - htri_t ret_value = FAIL; /* Return value */ + H5G_loc_t obj_loc; /* Location used to open group */ + H5G_name_t obj_path; /* Opened object group hier. path */ + H5O_loc_t obj_oloc; /* Opened object object location */ + hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ HDassert(obj_name); HDassert(attr_name); + HDassert(attr_exists); /* Set up opened group location to fill in */ obj_loc.oloc = &obj_oloc; @@ -1493,7 +1495,7 @@ H5A__exists_by_name(H5G_loc_t loc, const char *obj_name, const char *attr_name) loc_found = TRUE; /* Check if the attribute exists */ - if ((ret_value = H5O__attr_exists(obj_loc.oloc, attr_name)) < 0) + if (H5O__attr_exists(obj_loc.oloc, attr_name, attr_exists) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to determine if attribute exists") done: diff --git a/src/H5Apkg.h b/src/H5Apkg.h index 5a64a1b..e4c8551 100644 --- a/src/H5Apkg.h +++ b/src/H5Apkg.h @@ -203,7 +203,8 @@ H5_DLL herr_t H5A__iterate_old(hid_t loc_id, unsigned *attr_num, H5A_operator1_t H5_DLL herr_t H5A__delete_by_name(const H5G_loc_t *loc, const char *obj_name, const char *attr_name); H5_DLL herr_t H5A__delete_by_idx(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n); -H5_DLL htri_t H5A__exists_by_name(H5G_loc_t loc, const char *obj_name, const char *attr_name); +H5_DLL herr_t H5A__exists_by_name(H5G_loc_t loc, const char *obj_name, const char *attr_name, + hbool_t *attr_exists); H5_DLL herr_t H5A__write(H5A_t *attr, const H5T_t *mem_type, const void *buf); H5_DLL herr_t H5A__read(const H5A_t *attr, const H5T_t *mem_type, void *buf); H5_DLL ssize_t H5A__get_name(H5A_t *attr, size_t buf_size, char *buf); @@ -221,7 +222,7 @@ H5_DLL herr_t H5A__dense_iterate(H5F_t *f, hid_t loc_id, const H5O_ainfo_t *ainf H5_DLL herr_t H5A__dense_remove(H5F_t *f, const H5O_ainfo_t *ainfo, const char *name); H5_DLL herr_t H5A__dense_remove_by_idx(H5F_t *f, const H5O_ainfo_t *ainfo, H5_index_t idx_type, H5_iter_order_t order, hsize_t n); -H5_DLL htri_t H5A__dense_exists(H5F_t *f, const H5O_ainfo_t *ainfo, const char *name); +H5_DLL herr_t H5A__dense_exists(H5F_t *f, const H5O_ainfo_t *ainfo, const char *name, hbool_t *attr_exists); H5_DLL herr_t H5A__dense_delete(H5F_t *f, H5O_ainfo_t *ainfo); /* Attribute table operations */ @@ -246,7 +247,7 @@ H5_DLL herr_t H5O__attr_iterate(hid_t loc_id, H5_index_t idx_type, H5_iter_order H5_DLL herr_t H5O__attr_remove(const H5O_loc_t *loc, const char *name); H5_DLL herr_t H5O__attr_remove_by_idx(const H5O_loc_t *loc, H5_index_t idx_type, H5_iter_order_t order, hsize_t n); -H5_DLL htri_t H5O__attr_exists(const H5O_loc_t *loc, const char *name); +H5_DLL herr_t H5O__attr_exists(const H5O_loc_t *loc, const char *name, hbool_t *attr_exists); H5_DLL H5A_t *H5A__attr_copy_file(const H5A_t *attr_src, H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info); H5_DLL herr_t H5A__attr_post_copy_file(const H5O_loc_t *src_oloc, const H5A_t *mesg_src, H5O_loc_t *dst_oloc, diff --git a/src/H5Aprivate.h b/src/H5Aprivate.h index 4164154..69fba40 100644 --- a/src/H5Aprivate.h +++ b/src/H5Aprivate.h @@ -43,8 +43,8 @@ typedef herr_t (*H5A_lib_iterate_t)(const H5A_t *attr, void *op_data); /* Describe kind of callback to make for each attribute */ typedef enum H5A_attr_iter_op_type_t { #ifndef H5_NO_DEPRECATED_SYMBOLS - H5A_ATTR_OP_APP, /* Application callback */ -#endif /* H5_NO_DEPRECATED_SYMBOLS */ + H5A_ATTR_OP_APP, /* Application callback */ +#endif /* H5_NO_DEPRECATED_SYMBOLS */ H5A_ATTR_OP_APP2, /* Revised application callback */ H5A_ATTR_OP_LIB /* Library internal callback */ } H5A_attr_iter_op_type_t; @@ -53,8 +53,8 @@ typedef struct H5A_attr_iter_op_t { H5A_attr_iter_op_type_t op_type; union { #ifndef H5_NO_DEPRECATED_SYMBOLS - H5A_operator1_t app_op; /* Application callback for each attribute */ -#endif /* H5_NO_DEPRECATED_SYMBOLS */ + H5A_operator1_t app_op; /* Application callback for each attribute */ +#endif /* H5_NO_DEPRECATED_SYMBOLS */ H5A_operator2_t app_op2; /* Revised application callback for each attribute */ H5A_lib_iterate_t lib_op; /* Library internal callback for each attribute */ } u; diff --git a/src/H5Apublic.h b/src/H5Apublic.h index c3442b8..847f053 100644 --- a/src/H5Apublic.h +++ b/src/H5Apublic.h @@ -92,8 +92,11 @@ extern "C" { * \see H5Aclose() * */ -H5_DLL hid_t H5Acreate2(hid_t loc_id, const char *attr_name, hid_t type_id, hid_t space_id, hid_t acpl_id, - hid_t aapl_id); +H5_DLL hid_t H5Acreate2(hid_t loc_id, const char *attr_name, hid_t type_id, hid_t space_id, hid_t acpl_id, + hid_t aapl_id); +H5_DLL hid_t H5Acreate_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *attr_name, hid_t type_id, hid_t space_id, hid_t acpl_id, + hid_t aapl_id, hid_t es_id); /*--------------------------------------------------------------------------*/ /** * \ingroup H5A @@ -141,8 +144,12 @@ H5_DLL hid_t H5Acreate2(hid_t loc_id, const char *attr_name, hid_t type_id, hi * \since 1.8.0 * */ -H5_DLL hid_t H5Acreate_by_name(hid_t loc_id, const char *obj_name, const char *attr_name, hid_t type_id, - hid_t space_id, hid_t acpl_id, hid_t aapl_id, hid_t lapl_id); +H5_DLL hid_t H5Acreate_by_name(hid_t loc_id, const char *obj_name, const char *attr_name, hid_t type_id, + hid_t space_id, hid_t acpl_id, hid_t aapl_id, hid_t lapl_id); +H5_DLL hid_t H5Acreate_by_name_async(const char *app_file, const char *app_func, unsigned app_line, + hid_t loc_id, const char *obj_name, const char *attr_name, hid_t type_id, + hid_t space_id, hid_t acpl_id, hid_t aapl_id, hid_t lapl_id, + hid_t es_id); /*--------------------------------------------------------------------------*/ /** * \ingroup H5A @@ -173,7 +180,9 @@ H5_DLL hid_t H5Acreate_by_name(hid_t loc_id, const char *obj_name, const char * * \see H5Aclose(), H5Acreate() */ -H5_DLL hid_t H5Aopen(hid_t obj_id, const char *attr_name, hid_t aapl_id); +H5_DLL hid_t H5Aopen(hid_t obj_id, const char *attr_name, hid_t aapl_id); +H5_DLL hid_t H5Aopen_async(const char *app_file, const char *app_func, unsigned app_line, hid_t obj_id, + const char *attr_name, hid_t aapl_id, hid_t es_id); /*--------------------------------------------------------------------------*/ /** * \ingroup H5A @@ -219,8 +228,11 @@ H5_DLL hid_t H5Aopen(hid_t obj_id, const char *attr_name, hid_t aapl_id); * \since 1.8.0 * */ -H5_DLL hid_t H5Aopen_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type, H5_iter_order_t order, - hsize_t n, hid_t aapl_id, hid_t lapl_id); +H5_DLL hid_t H5Aopen_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type, H5_iter_order_t order, + hsize_t n, hid_t aapl_id, hid_t lapl_id); +H5_DLL hid_t H5Aopen_by_idx_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *obj_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, + hid_t aapl_id, hid_t lapl_id, hid_t es_id); /*--------------------------------------------------------------------------*/ /** * \ingroup H5A @@ -262,8 +274,11 @@ H5_DLL hid_t H5Aopen_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx * \since 1.8.0 * */ -H5_DLL hid_t H5Aopen_by_name(hid_t loc_id, const char *obj_name, const char *attr_name, hid_t aapl_id, - hid_t lapl_id); +H5_DLL hid_t H5Aopen_by_name(hid_t loc_id, const char *obj_name, const char *attr_name, hid_t aapl_id, + hid_t lapl_id); +H5_DLL hid_t H5Aopen_by_name_async(const char *app_file, const char *app_func, unsigned app_line, + hid_t loc_id, const char *obj_name, const char *attr_name, hid_t aapl_id, + hid_t lapl_id, hid_t es_id); /*-------------------------------------------------------------------------- */ /** * \ingroup H5A @@ -290,8 +305,10 @@ H5_DLL hid_t H5Aopen_by_name(hid_t loc_id, const char *obj_name, const char *a * * \see H5Awrite() * -*/ -H5_DLL herr_t H5Aread(hid_t attr_id, hid_t type_id, void *buf); + */ +H5_DLL herr_t H5Aread(hid_t attr_id, hid_t type_id, void *buf); +H5_DLL herr_t H5Aread_async(const char *app_file, const char *app_func, unsigned app_line, hid_t attr_id, + hid_t dtype_id, void *buf, hid_t es_id); /*--------------------------------------------------------------------------*/ /** * \ingroup H5A @@ -324,6 +341,8 @@ H5_DLL herr_t H5Aread(hid_t attr_id, hid_t type_id, void *buf); * */ H5_DLL herr_t H5Awrite(hid_t attr_id, hid_t type_id, const void *buf); +H5_DLL herr_t H5Awrite_async(const char *app_file, const char *app_func, unsigned app_line, hid_t attr_id, + hid_t type_id, const void *buf, hid_t es_id); H5_DLL hid_t H5Aget_space(hid_t attr_id); H5_DLL hid_t H5Aget_type(hid_t attr_id); H5_DLL hid_t H5Aget_create_plist(hid_t attr_id); @@ -338,8 +357,13 @@ H5_DLL herr_t H5Aget_info_by_name(hid_t loc_id, const char *obj_name, const cha H5_DLL herr_t H5Aget_info_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, H5A_info_t *ainfo /*out*/, hid_t lapl_id); H5_DLL herr_t H5Arename(hid_t loc_id, const char *old_name, const char *new_name); +H5_DLL herr_t H5Arename_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *old_name, const char *new_name, hid_t es_id); H5_DLL herr_t H5Arename_by_name(hid_t loc_id, const char *obj_name, const char *old_attr_name, const char *new_attr_name, hid_t lapl_id); +H5_DLL herr_t H5Arename_by_name_async(const char *app_file, const char *app_func, unsigned app_line, + hid_t loc_id, const char *obj_name, const char *old_attr_name, + const char *new_attr_name, hid_t lapl_id, hid_t es_id); H5_DLL herr_t H5Aiterate2(hid_t loc_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx, H5A_operator2_t op, void *op_data); H5_DLL herr_t H5Aiterate_by_name(hid_t loc_id, const char *obj_name, H5_index_t idx_type, @@ -350,7 +374,12 @@ H5_DLL herr_t H5Adelete_by_name(hid_t loc_id, const char *obj_name, const char H5_DLL herr_t H5Adelete_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t lapl_id); H5_DLL htri_t H5Aexists(hid_t obj_id, const char *attr_name); +H5_DLL herr_t H5Aexists_async(const char *app_file, const char *app_func, unsigned app_line, hid_t obj_id, + const char *attr_name, hbool_t *exists, hid_t es_id); H5_DLL htri_t H5Aexists_by_name(hid_t obj_id, const char *obj_name, const char *attr_name, hid_t lapl_id); +H5_DLL herr_t H5Aexists_by_name_async(const char *app_file, const char *app_func, unsigned app_line, + hid_t loc_id, const char *obj_name, const char *attr_name, + hbool_t *exists, hid_t lapl_id, hid_t es_id); /*-------------------------------------------------------------------------*/ /** * \ingroup H5A @@ -372,6 +401,42 @@ H5_DLL htri_t H5Aexists_by_name(hid_t obj_id, const char *obj_name, const char * * \see H5Acreate(), H5Aopen() */ H5_DLL herr_t H5Aclose(hid_t attr_id); +H5_DLL herr_t H5Aclose_async(const char *app_file, const char *app_func, unsigned app_line, hid_t attr_id, + hid_t es_id); + +/* API Wrappers for async routines */ +/* (Must be defined _after_ the function prototype) */ +/* (And must only defined when included in application code, not the library) */ +#ifndef H5A_MODULE +#define H5Acreate_async(...) H5Acreate_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Acreate_by_name_async(...) H5Acreate_by_name_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Aopen_async(...) H5Aopen_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Aopen_by_name_async(...) H5Aopen_by_name_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Aopen_by_idx_async(...) H5Aopen_by_idx_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Awrite_async(...) H5Awrite_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Aread_async(...) H5Aread_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Arename_async(...) H5Arename_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Arename_by_name_async(...) H5Arename_by_name_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Aexists_async(...) H5Aexists_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Aexists_by_name_async(...) H5Aexists_by_name_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Aclose_async(...) H5Aclose_async(__FILE__, __func__, __LINE__, __VA_ARGS__) + +/* Define "wrapper" versions of function calls, to allow compile-time values to + * be passed in by language wrapper or library layer on top of HDF5. + */ +#define H5Acreate_async_wrap H5_NO_EXPAND(H5Acreate_async) +#define H5Acreate_by_name_async_wrap H5_NO_EXPAND(H5Acreate_by_name_async) +#define H5Aopen_async_wrap H5_NO_EXPAND(H5Aopen_async) +#define H5Aopen_by_name_async_wrap H5_NO_EXPAND(H5Aopen_by_name_async) +#define H5Aopen_by_idx_async_wrap H5_NO_EXPAND(H5Aopen_by_idx_async) +#define H5Awrite_async_wrap H5_NO_EXPAND(H5Awrite_async) +#define H5Aread_async_wrap H5_NO_EXPAND(H5Aread_async) +#define H5Arename_async_wrap H5_NO_EXPAND(H5Arename_async) +#define H5Arename_by_name_async_wrap H5_NO_EXPAND(H5Arename_by_name_async) +#define H5Aexists_async_wrap H5_NO_EXPAND(H5Aexists_async) +#define H5Aexists_by_name_async_wrap H5_NO_EXPAND(H5Aexists_by_name_async) +#define H5Aclose_async_wrap H5_NO_EXPAND(H5Aclose_async) +#endif /* H5A_MODULE */ /* Symbols defined for compatibility with previous versions of the HDF5 API. * @@ -286,8 +286,8 @@ done: * *------------------------------------------------------------------------- */ -htri_t -H5B_find(H5F_t *f, const H5B_class_t *type, haddr_t addr, void *udata) +herr_t +H5B_find(H5F_t *f, const H5B_class_t *type, haddr_t addr, hbool_t *found, void *udata) { H5B_t * bt = NULL; H5UC_t * rc_shared; /* Ref-counted shared info */ @@ -295,7 +295,7 @@ H5B_find(H5F_t *f, const H5B_class_t *type, haddr_t addr, void *udata) H5B_cache_ud_t cache_udata; /* User-data for metadata cache callback */ unsigned idx = 0, lt = 0, rt; /* Final, left & right key indices */ int cmp = 1; /* Key comparison value */ - htri_t ret_value = FAIL; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -334,23 +334,25 @@ H5B_find(H5F_t *f, const H5B_class_t *type, haddr_t addr, void *udata) else lt = idx + 1; } /* end while */ + /* Check if not found */ if (cmp) - HGOTO_DONE(FALSE) - - /* - * Follow the link to the subtree or to the data node. - */ - HDassert(idx < bt->nchildren); - - if (bt->level > 0) { - if ((ret_value = H5B_find(f, type, bt->child[idx], udata)) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "can't lookup key in subtree") - } /* end if */ + *found = FALSE; else { - if ((ret_value = (type->found)(f, bt->child[idx], H5B_NKEY(bt, shared, idx), udata)) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "can't lookup key in leaf node") - } /* end else */ + /* + * Follow the link to the subtree or to the data node. + */ + HDassert(idx < bt->nchildren); + + if (bt->level > 0) { + if ((ret_value = H5B_find(f, type, bt->child[idx], found, udata)) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "can't lookup key in subtree") + } /* end if */ + else { + if ((ret_value = (type->found)(f, bt->child[idx], H5B_NKEY(bt, shared, idx), found, udata)) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "can't lookup key in leaf node") + } /* end else */ + } /* end else */ done: if (bt && H5AC_unprotect(f, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0) @@ -445,29 +445,30 @@ H5B2_iterate(H5B2_t *bt2, H5B2_operator_t op, void *op_data) * If 'OP' is NULL, then this routine just returns "TRUE" when * a record is present in the B-tree. * - * Return: Non-negative (TRUE/FALSE) on success, negative on failure. + * Return: SUCCEED/FAIL * * Programmer: Quincey Koziol * Feb 23 2005 * *------------------------------------------------------------------------- */ -htri_t -H5B2_find(H5B2_t *bt2, void *udata, H5B2_found_t op, void *op_data) +herr_t +H5B2_find(H5B2_t *bt2, void *udata, hbool_t *found, H5B2_found_t op, void *op_data) { - H5B2_hdr_t * hdr; /* Pointer to the B-tree header */ - H5B2_node_ptr_t curr_node_ptr; /* Node pointer info for current node */ - void * parent = NULL; /* Parent of current node */ - uint16_t depth; /* Current depth of the tree */ - int cmp; /* Comparison value of records */ - unsigned idx; /* Location of record which matches key */ - H5B2_nodepos_t curr_pos; /* Position of the current node */ - htri_t ret_value = TRUE; /* Return value */ + H5B2_hdr_t * hdr; /* Pointer to the B-tree header */ + H5B2_node_ptr_t curr_node_ptr; /* Node pointer info for current node */ + void * parent = NULL; /* Parent of current node */ + uint16_t depth; /* Current depth of the tree */ + int cmp; /* Comparison value of records */ + unsigned idx; /* Location of record which matches key */ + H5B2_nodepos_t curr_pos; /* Position of the current node */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Check arguments. */ HDassert(bt2); + HDassert(found); /* Set the shared v2 B-tree header's file context for this operation */ bt2->hdr->f = bt2->f; @@ -479,8 +480,10 @@ H5B2_find(H5B2_t *bt2, void *udata, H5B2_found_t op, void *op_data) curr_node_ptr = hdr->root; /* Check for empty tree */ - if (curr_node_ptr.node_nrec == 0) - HGOTO_DONE(FALSE) + if (curr_node_ptr.node_nrec == 0) { + *found = FALSE; + HGOTO_DONE(SUCCEED) + } /* Check record against min & max records in tree, to attempt to quickly * find candidates or avoid further searching. @@ -488,25 +491,31 @@ H5B2_find(H5B2_t *bt2, void *udata, H5B2_found_t op, void *op_data) if (hdr->min_native_rec != NULL) { if ((hdr->cls->compare)(udata, hdr->min_native_rec, &cmp) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records") - if (cmp < 0) - HGOTO_DONE(FALSE) /* Less than the least record--not found */ - else if (cmp == 0) { /* Record is found */ + if (cmp < 0) { + *found = FALSE; /* Less than the least record--not found */ + HGOTO_DONE(SUCCEED) + } + else if (cmp == 0) { /* Record is found */ if (op && (op)(hdr->min_native_rec, op_data) < 0) HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "'found' callback failed for B-tree find operation") - HGOTO_DONE(TRUE) + *found = TRUE; + HGOTO_DONE(SUCCEED) } /* end if */ } /* end if */ if (hdr->max_native_rec != NULL) { if ((hdr->cls->compare)(udata, hdr->max_native_rec, &cmp) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records") - if (cmp > 0) - HGOTO_DONE(FALSE) /* Less than the least record--not found */ - else if (cmp == 0) { /* Record is found */ + if (cmp > 0) { + *found = FALSE; /* Greater than the largest record--not found */ + HGOTO_DONE(SUCCEED) + } + else if (cmp == 0) { /* Record is found */ if (op && (op)(hdr->max_native_rec, op_data) < 0) HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "'found' callback failed for B-tree find operation") - HGOTO_DONE(TRUE) + *found = TRUE; + HGOTO_DONE(SUCCEED) } /* end if */ } /* end if */ @@ -597,7 +606,8 @@ H5B2_find(H5B2_t *bt2, void *udata, H5B2_found_t op, void *op_data) HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node") /* Indicate record found */ - HGOTO_DONE(TRUE) + *found = TRUE; + HGOTO_DONE(SUCCEED) } /* end else */ /* Decrement depth we're at in B-tree */ @@ -632,7 +642,8 @@ H5B2_find(H5B2_t *bt2, void *udata, H5B2_found_t op, void *op_data) HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node") /* Record not found */ - HGOTO_DONE(FALSE) + *found = FALSE; + HGOTO_DONE(SUCCEED) } /* end if */ else { /* Make callback for current record */ @@ -672,6 +683,9 @@ H5B2_find(H5B2_t *bt2, void *udata, H5B2_found_t op, void *op_data) /* Unlock current node */ if (H5AC_unprotect(hdr->f, H5AC_BT2_LEAF, curr_node_ptr.addr, leaf, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node") + + /* Indicate record found */ + *found = TRUE; } /* end block */ done: diff --git a/src/H5B2private.h b/src/H5B2private.h index e511897..0030bf4 100644 --- a/src/H5B2private.h +++ b/src/H5B2private.h @@ -131,7 +131,7 @@ H5_DLL H5B2_t *H5B2_open(H5F_t *f, haddr_t addr, void *ctx_udata); H5_DLL herr_t H5B2_get_addr(const H5B2_t *bt2, haddr_t *addr /*out*/); H5_DLL herr_t H5B2_insert(H5B2_t *bt2, void *udata); H5_DLL herr_t H5B2_iterate(H5B2_t *bt2, H5B2_operator_t op, void *op_data); -H5_DLL htri_t H5B2_find(H5B2_t *bt2, void *udata, H5B2_found_t op, void *op_data); +H5_DLL herr_t H5B2_find(H5B2_t *bt2, void *udata, hbool_t *found, H5B2_found_t op, void *op_data); H5_DLL herr_t H5B2_index(H5B2_t *bt2, H5_iter_order_t order, hsize_t idx, H5B2_found_t op, void *op_data); H5_DLL herr_t H5B2_neighbor(H5B2_t *bt2, H5B2_compare_t range, void *udata, H5B2_found_t op, void *op_data); H5_DLL herr_t H5B2_modify(H5B2_t *bt2, void *udata, H5B2_modify_t op, void *op_data); diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h index ae47162..6f2925f 100644 --- a/src/H5Bprivate.h +++ b/src/H5Bprivate.h @@ -110,7 +110,7 @@ typedef struct H5B_class_t { herr_t (*new_node)(H5F_t *, H5B_ins_t, void *, void *, void *, haddr_t *); int (*cmp2)(void *, void *, void *); /*compare 2 keys */ int (*cmp3)(void *, void *, void *); /*compare 3 keys */ - htri_t (*found)(H5F_t *, haddr_t, const void *, void *); + htri_t (*found)(H5F_t *, haddr_t, const void *, hbool_t *, void *); /* insert new data */ H5B_ins_t (*insert)(H5F_t *, haddr_t, void *, hbool_t *, void *, void *, void *, hbool_t *, haddr_t *); @@ -145,7 +145,7 @@ typedef struct H5B_info_t { /* Library-private Function Prototypes */ /***************************************/ H5_DLL herr_t H5B_create(H5F_t *f, const H5B_class_t *type, void *udata, haddr_t *addr_p /*out*/); -H5_DLL herr_t H5B_find(H5F_t *f, const H5B_class_t *type, haddr_t addr, void *udata); +H5_DLL herr_t H5B_find(H5F_t *f, const H5B_class_t *type, haddr_t addr, hbool_t *found, void *udata); H5_DLL herr_t H5B_insert(H5F_t *f, const H5B_class_t *type, haddr_t addr, void *udata); H5_DLL herr_t H5B_iterate(H5F_t *f, const H5B_class_t *type, haddr_t addr, H5B_operator_t op, void *udata); H5_DLL herr_t H5B_get_info(H5F_t *f, const H5B_class_t *type, haddr_t addr, H5B_info_t *bt_info, @@ -7131,7 +7131,7 @@ H5C__load_entry(H5F_t *f, MPI_Comm comm = MPI_COMM_NULL; /* File MPI Communicator */ int mpi_code; /* MPI error code */ #endif /* H5_HAVE_PARALLEL */ - void *ret_value = NULL; /* Return value */ + void *ret_value = NULL; /* Return value */ FUNC_ENTER_STATIC @@ -370,9 +370,9 @@ typedef struct H5CX_dxpl_cache_t { uint32_t mpio_global_no_coll_cause; /* Global reason for breaking collective I/O (H5D_MPIO_GLOBAL_NO_COLLECTIVE_CAUSE_NAME) */ H5FD_mpio_chunk_opt_t - mpio_chunk_opt_mode; /* Collective chunk option (H5D_XFER_MPIO_CHUNK_OPT_HARD_NAME) */ - unsigned mpio_chunk_opt_num; /* Collective chunk thrreshold (H5D_XFER_MPIO_CHUNK_OPT_NUM_NAME) */ - unsigned mpio_chunk_opt_ratio; /* Collective chunk ratio (H5D_XFER_MPIO_CHUNK_OPT_RATIO_NAME) */ + mpio_chunk_opt_mode; /* Collective chunk option (H5D_XFER_MPIO_CHUNK_OPT_HARD_NAME) */ + unsigned mpio_chunk_opt_num; /* Collective chunk thrreshold (H5D_XFER_MPIO_CHUNK_OPT_NUM_NAME) */ + unsigned mpio_chunk_opt_ratio; /* Collective chunk ratio (H5D_XFER_MPIO_CHUNK_OPT_RATIO_NAME) */ #endif /* H5_HAVE_PARALLEL */ H5Z_EDC_t err_detect; /* Error detection info (H5D_XFER_EDC_NAME) */ H5Z_cb_t filter_cb; /* Filter callback function (H5D_XFER_FILTER_CB_NAME) */ @@ -24,6 +24,7 @@ #include "H5CXprivate.h" /* API Contexts */ #include "H5Dpkg.h" /* Datasets */ #include "H5Eprivate.h" /* Error handling */ +#include "H5ESprivate.h" /* Event Sets */ #include "H5FLprivate.h" /* Free lists */ #include "H5Iprivate.h" /* IDs */ #include "H5VLprivate.h" /* Virtual Object Layer */ @@ -42,6 +43,21 @@ /* Local Prototypes */ /********************/ +/* Helper routines for sync/async API calls */ +static hid_t H5D__create_api_common(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, + hid_t lcpl_id, hid_t dcpl_id, hid_t dapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static hid_t H5D__open_api_common(hid_t loc_id, const char *name, hid_t dapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static hid_t H5D__get_space_api_common(hid_t dset_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr); +static herr_t H5D__read_api_common(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, + hid_t dxpl_id, void *buf, void **token_ptr, H5VL_object_t **_vol_obj_ptr); +static herr_t H5D__write_api_common(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, + hid_t dxpl_id, const void *buf, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static herr_t H5D__set_extent_api_common(hid_t dset_id, const hsize_t size[], void **token_ptr, + H5VL_object_t **_vol_obj_ptr); + /*********************/ /* Package Variables */ /*********************/ @@ -64,42 +80,27 @@ H5FL_BLK_EXTERN(type_conv); /*******************/ /*------------------------------------------------------------------------- - * Function: H5Dcreate2 - * - * Purpose: Creates a new dataset named NAME at LOC_ID, opens the - * dataset for access, and associates with that dataset constant - * and initial persistent properties including the type of each - * datapoint as stored in the file (TYPE_ID), the size of the - * dataset (SPACE_ID), and other initial miscellaneous - * properties (DCPL_ID). - * - * All arguments are copied into the dataset, so the caller is - * allowed to derive new types, dataspaces, and creation - * parameters from the old ones and reuse them in calls to - * create other datasets. + * Function: H5D__create_api_common * - * Return: Success: The object ID of the new dataset. At this - * point, the dataset is ready to receive its - * raw data. Attempting to read raw data from - * the dataset will probably return the fill - * value. The dataset should be closed when the - * caller is no longer interested in it. + * Purpose: This is the common function for creating HDF5 datasets. * + * Return: Success: A dataset ID * Failure: H5I_INVALID_HID * *------------------------------------------------------------------------- */ -hid_t -H5Dcreate2(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, hid_t lcpl_id, hid_t dcpl_id, - hid_t dapl_id) +static hid_t +H5D__create_api_common(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, hid_t lcpl_id, + hid_t dcpl_id, hid_t dapl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr) { - void * dset = NULL; /* New dataset's info */ - H5VL_object_t * vol_obj = NULL; /* object of loc_id */ - H5VL_loc_params_t loc_params; - hid_t ret_value = H5I_INVALID_HID; /* Return value */ + void * dset = NULL; /* New dataset's info */ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ - FUNC_ENTER_API(H5I_INVALID_HID) - H5TRACE7("i", "i*siiiii", loc_id, name, type_id, space_id, lcpl_id, dcpl_id, dapl_id); + FUNC_ENTER_STATIC /* Check arguments */ if (!name) @@ -107,6 +108,10 @@ H5Dcreate2(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, hid_t if (!*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be an empty string") + /* Set up object access arguments */ + if (H5VL_setup_acc_args(loc_id, H5P_CLS_DACC, TRUE, &dapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, H5I_INVALID_HID, "can't set object access arguments") + /* Get link creation property list */ if (H5P_DEFAULT == lcpl_id) lcpl_id = H5P_LINK_CREATE_DEFAULT; @@ -126,36 +131,114 @@ H5Dcreate2(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, hid_t /* Set the LCPL for the API context */ H5CX_set_lcpl(lcpl_id); - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&dapl_id, H5P_CLS_DACC, loc_id, TRUE) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info") - - /* Get the location object */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier") - - /* Set location parameters */ - loc_params.type = H5VL_OBJECT_BY_SELF; - loc_params.obj_type = H5I_get_type(loc_id); - /* Create the dataset */ - if (NULL == (dset = H5VL_dataset_create(vol_obj, &loc_params, name, lcpl_id, type_id, space_id, dcpl_id, - dapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL))) + if (NULL == (dset = H5VL_dataset_create(*vol_obj_ptr, &loc_params, name, lcpl_id, type_id, space_id, + dcpl_id, dapl_id, H5P_DATASET_XFER_DEFAULT, token_ptr))) HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, H5I_INVALID_HID, "unable to create dataset") /* Get an ID for the dataset */ - if ((ret_value = H5VL_register(H5I_DATASET, dset, vol_obj->connector, TRUE)) < 0) + if ((ret_value = H5VL_register(H5I_DATASET, dset, (*vol_obj_ptr)->connector, TRUE)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataset") done: if (H5I_INVALID_HID == ret_value) - if (dset && H5VL_dataset_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) + if (dset && H5VL_dataset_close(*vol_obj_ptr, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release dataset") + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__create_api_common() */ + +/*------------------------------------------------------------------------- + * Function: H5Dcreate2 + * + * Purpose: Creates a new dataset named NAME at LOC_ID, opens the + * dataset for access, and associates with that dataset constant + * and initial persistent properties including the type of each + * datapoint as stored in the file (TYPE_ID), the size of the + * dataset (SPACE_ID), and other initial miscellaneous + * properties (DCPL_ID). + * + * All arguments are copied into the dataset, so the caller is + * allowed to derive new types, dataspaces, and creation + * parameters from the old ones and reuse them in calls to + * create other datasets. + * + * Return: Success: The object ID of the new dataset. At this + * point, the dataset is ready to receive its + * raw data. Attempting to read raw data from + * the dataset will probably return the fill + * value. The dataset should be closed when the + * caller is no longer interested in it. + * + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Dcreate2(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, hid_t lcpl_id, hid_t dcpl_id, + hid_t dapl_id) +{ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE7("i", "i*siiiii", loc_id, name, type_id, space_id, lcpl_id, dcpl_id, dapl_id); + + /* Create the dataset synchronously */ + if ((ret_value = H5D__create_api_common(loc_id, name, type_id, space_id, lcpl_id, dcpl_id, dapl_id, NULL, + NULL)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, H5I_INVALID_HID, "unable to synchronously create dataset") + +done: FUNC_LEAVE_API(ret_value) } /* end H5Dcreate2() */ /*------------------------------------------------------------------------- + * Function: H5Dcreate_async + * + * Purpose: Asynchronous version of H5Dcreate + * + * Return: Success: A dataset ID + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Dcreate_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, const char *name, + hid_t type_id, hid_t space_id, hid_t lcpl_id, hid_t dcpl_id, hid_t dapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE11("i", "*s*sIui*siiiiii", app_file, app_func, app_line, loc_id, name, type_id, space_id, lcpl_id, + dcpl_id, dapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Create the dataset asynchronously */ + if ((ret_value = H5D__create_api_common(loc_id, name, type_id, space_id, lcpl_id, dcpl_id, dapl_id, + token_ptr, &vol_obj)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, H5I_INVALID_HID, "unable to asynchronously create dataset") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE11(FUNC, "*s*sIui*siiiiii", app_file, app_func, app_line, loc_id, name, + type_id, space_id, lcpl_id, dcpl_id, dapl_id, es_id)) < 0) { + if (H5I_dec_app_ref_always_close(ret_value) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, H5I_INVALID_HID, "can't decrement count on dataset ID") + HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Dcreate_async() */ + +/*------------------------------------------------------------------------- * Function: H5Dcreate_anon * * Purpose: Creates a new dataset named NAME at LOC_ID, opens the @@ -239,30 +322,27 @@ done: } /* end H5Dcreate_anon() */ /*------------------------------------------------------------------------- - * Function: H5Dopen2 + * Function: H5D__open_api_common * - * Purpose: Finds a dataset named NAME at LOC_ID, opens it, and returns - * its ID. The dataset should be close when the caller is no - * longer interested in it. - * - * Takes a dataset access property list + * Purpose: This is the common function for opening a dataset * * Return: Success: Object ID of the dataset - * * Failure: H5I_INVALID_HID * *------------------------------------------------------------------------- */ -hid_t -H5Dopen2(hid_t loc_id, const char *name, hid_t dapl_id) +static hid_t +H5D__open_api_common(hid_t loc_id, const char *name, hid_t dapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) { - void * dset = NULL; /* dset object from VOL connector */ - H5VL_object_t * vol_obj = NULL; /* object of loc_id */ - H5VL_loc_params_t loc_params; - hid_t ret_value = H5I_INVALID_HID; /* Return value */ + void * dset = NULL; /* dset object from VOL connector */ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ - FUNC_ENTER_API(H5I_INVALID_HID) - H5TRACE3("i", "i*si", loc_id, name, dapl_id); + FUNC_ENTER_STATIC /* Check args */ if (!name) @@ -270,36 +350,103 @@ H5Dopen2(hid_t loc_id, const char *name, hid_t dapl_id) if (!*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be an empty string") - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&dapl_id, H5P_CLS_DACC, loc_id, FALSE) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info") - - /* get the location object */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier") - - /* Set the location parameters */ - loc_params.type = H5VL_OBJECT_BY_SELF; - loc_params.obj_type = H5I_get_type(loc_id); + /* Set up object access arguments */ + if (H5VL_setup_acc_args(loc_id, H5P_CLS_DACC, FALSE, &dapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, H5I_INVALID_HID, "can't set object access arguments") /* Open the dataset */ - if (NULL == (dset = H5VL_dataset_open(vol_obj, &loc_params, name, dapl_id, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL))) + if (NULL == (dset = H5VL_dataset_open(*vol_obj_ptr, &loc_params, name, dapl_id, H5P_DATASET_XFER_DEFAULT, + token_ptr))) HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open dataset") - /* Register an ID for the dataset */ - if ((ret_value = H5VL_register(H5I_DATASET, dset, vol_obj->connector, TRUE)) < 0) + /* Register an atom for the dataset */ + if ((ret_value = H5VL_register(H5I_DATASET, dset, (*vol_obj_ptr)->connector, TRUE)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register dataset ID") done: if (H5I_INVALID_HID == ret_value) - if (dset && H5VL_dataset_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) + if (dset && H5VL_dataset_close(*vol_obj_ptr, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release dataset") + FUNC_LEAVE_NOAPI(ret_value) +} /* H5D__open_api_common() */ + +/*------------------------------------------------------------------------- + * Function: H5Dopen2 + * + * Purpose: Finds a dataset named NAME at LOC_ID, opens it, and returns + * its ID. The dataset should be close when the caller is no + * longer interested in it. + * + * Takes a dataset access property list + * + * Return: Success: Object ID of the dataset + * + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Dopen2(hid_t loc_id, const char *name, hid_t dapl_id) +{ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE3("i", "i*si", loc_id, name, dapl_id); + + /* Open the dataset synchronously */ + if ((ret_value = H5D__open_api_common(loc_id, name, dapl_id, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to synchronously open dataset") + +done: FUNC_LEAVE_API(ret_value) } /* end H5Dopen2() */ /*------------------------------------------------------------------------- + * Function: H5Dopen_async + * + * Purpose: Asynchronous version of H5Dopen2 + * + * Return: Success: A group ID + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Dopen_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, const char *name, + hid_t dapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE7("i", "*s*sIui*sii", app_file, app_func, app_line, loc_id, name, dapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Open the dataset asynchronously */ + if ((ret_value = H5D__open_api_common(loc_id, name, dapl_id, token_ptr, &vol_obj)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to asynchronously open dataset") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE7(FUNC, "*s*sIui*sii", app_file, app_func, app_line, loc_id, name, dapl_id, + es_id)) < 0) { + if (H5I_dec_app_ref_always_close(ret_value) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, H5I_INVALID_HID, "can't decrement count on dataset ID") + HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Dopen_async() */ + +/*------------------------------------------------------------------------- * Function: H5Dclose * * Purpose: Closes access to a dataset and releases resources used by @@ -333,6 +480,98 @@ done: } /* end H5Dclose() */ /*------------------------------------------------------------------------- + * Function: H5Dclose_async + * + * Purpose: Asynchronous version of H5Dclose + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Dclose_async(const char *app_file, const char *app_func, unsigned app_line, hid_t dset_id, hid_t es_id) +{ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + H5VL_object_t *vol_obj = NULL; /* VOL object of dset_id */ + H5VL_t * connector = NULL; /* VOL connector */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "*s*sIuii", app_file, app_func, app_line, dset_id, es_id); + + /* Check args */ + if (H5I_DATASET != H5I_get_type(dset_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset ID") + + /* Get dataset object's connector */ + if (NULL == (vol_obj = H5VL_vol_object(dset_id))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get VOL object for dataset") + + /* Prepare for possible asynchronous operation */ + if (H5ES_NONE != es_id) { + /* Increase connector's refcount, so it doesn't get closed if closing + * the dataset closes the file */ + connector = vol_obj->connector; + H5VL_conn_inc_rc(connector); + + /* Point at token for operation to set up */ + token_ptr = &token; + } /* end if */ + + /* Decrement the counter on the dataset. It will be freed if the count + * reaches zero. + */ + if (H5I_dec_app_ref_always_close_async(dset_id, token_ptr) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "can't decrement count on dataset ID") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE5(FUNC, "*s*sIuii", app_file, app_func, app_line, dset_id, es_id)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + if (connector && H5VL_conn_dec_rc(connector) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "can't decrement ref count on connector") + + FUNC_LEAVE_API(ret_value) +} /* end H5Dclose_async() */ + +/*------------------------------------------------------------------------- + * Function: H5D__get_space_api_common + * + * Purpose: This is the common function for getting a dataset's dataspace + * + * Return: Success: ID for a copy of the dataspace. + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +static hid_t +H5D__get_space_api_common(hid_t dset_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check args */ + if (NULL == (*vol_obj_ptr = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid dataset identifier") + + /* Get the dataspace */ + if (H5VL_dataset_get(*vol_obj_ptr, H5VL_DATASET_GET_SPACE, H5P_DATASET_XFER_DEFAULT, token_ptr, + &ret_value) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, H5I_INVALID_HID, "unable to get dataspace") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5D__get_space_api_common() */ + +/*------------------------------------------------------------------------- * Function: H5Dget_space * * Purpose: Returns a copy of the file dataspace for a dataset. @@ -348,26 +587,66 @@ done: hid_t H5Dget_space(hid_t dset_id) { - H5VL_object_t *vol_obj = NULL; /* Dataset structure */ - hid_t ret_value = H5I_INVALID_HID; /* Return value */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ FUNC_ENTER_API(H5I_INVALID_HID) H5TRACE1("i", "i", dset_id); - /* Check args */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid dataset identifier") - - /* Get the dataspace */ - if (H5VL_dataset_get(vol_obj, H5VL_DATASET_GET_SPACE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, - &ret_value) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, H5I_INVALID_HID, "unable to get dataspace") + /* Get the dataset's dataspace synchronously */ + if ((ret_value = H5D__get_space_api_common(dset_id, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, H5I_INVALID_HID, "unable to synchronously get dataspace") done: FUNC_LEAVE_API(ret_value) } /* end H5Dget_space() */ /*------------------------------------------------------------------------- + * Function: H5Dget_space_async + * + * Purpose: Asynchronous version of H5Dget_space + * + * Return: Success: ID for a copy of the dataspace. The data + * space should be released by calling + * H5Sclose(). + * + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Dget_space_async(const char *app_file, const char *app_func, unsigned app_line, hid_t dset_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE5("i", "*s*sIuii", app_file, app_func, app_line, dset_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Get the dataset's dataspace asynchronously */ + if ((ret_value = H5D__get_space_api_common(dset_id, token_ptr, &vol_obj)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, H5I_INVALID_HID, "unable to asynchronously get dataspace") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE5(FUNC, "*s*sIuii", app_file, app_func, app_line, dset_id, es_id)) < 0) { + if (H5I_dec_app_ref(ret_value) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, H5I_INVALID_HID, + "can't decrement count on dataspace ID") + HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Dget_space_async() */ + +/*------------------------------------------------------------------------- * Function: H5Dget_space_status * * Purpose: Returns the status of dataspace allocation. @@ -597,6 +876,51 @@ done: } /* end H5Dget_offset() */ /*------------------------------------------------------------------------- + * Function: H5D__read_api_common + * + * Purpose: Common helper routine for sync/async dataset read operations. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D__read_api_common(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t dxpl_id, + void *buf, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check arguments */ + if (mem_space_id < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid memory dataspace ID") + if (file_space_id < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file dataspace ID") + + /* Get dataset pointer */ + if (NULL == (*vol_obj_ptr = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id is not a dataset ID") + + /* Get the default dataset transfer property list if the user didn't provide one */ + if (H5P_DEFAULT == dxpl_id) + dxpl_id = H5P_DATASET_XFER_DEFAULT; + else if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms") + + /* Read the data */ + if (H5VL_dataset_read(*vol_obj_ptr, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, token_ptr) < + 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__read_api_common() */ + +/*------------------------------------------------------------------------- * Function: H5Dread * * Purpose: Reads (part of) a DSET from the file into application @@ -630,36 +954,63 @@ herr_t H5Dread(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t dxpl_id, void *buf /*out*/) { - H5VL_object_t *vol_obj = NULL; - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE6("e", "iiiiix", dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf); - /* Check arguments */ - if (mem_space_id < 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid memory dataspace ID") - if (file_space_id < 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file dataspace ID") + /* Read the data */ + if (H5D__read_api_common(dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, NULL, NULL) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't synchronously read data") - /* Get dataset pointer */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id is not a dataset ID") +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Dread() */ - /* Get the default dataset transfer property list if the user didn't provide one */ - if (H5P_DEFAULT == dxpl_id) - dxpl_id = H5P_DATASET_XFER_DEFAULT; - else if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms") +/*------------------------------------------------------------------------- + * Function: H5Dread_async + * + * Purpose: Asynchronously read dataset elements. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Houjun Tang + * Oct 15, 2019 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Dread_async(const char *app_file, const char *app_func, unsigned app_line, hid_t dset_id, hid_t mem_type_id, + hid_t mem_space_id, hid_t file_space_id, hid_t dxpl_id, void *buf /*out*/, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Dataset VOL object */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE10("e", "*s*sIuiiiiixi", app_file, app_func, app_line, dset_id, mem_type_id, mem_space_id, + file_space_id, dxpl_id, buf, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ /* Read the data */ - if ((ret_value = H5VL_dataset_read(vol_obj, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, - H5_REQUEST_NULL)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data") + if (H5D__read_api_common(dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, token_ptr, + &vol_obj) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't asynchronously read data") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE10(FUNC, "*s*sIuiiiiixi", app_file, app_func, app_line, dset_id, + mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, es_id)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "can't insert token into event set") done: FUNC_LEAVE_API(ret_value) -} /* end H5Dread() */ +} /* end H5Dread_async() */ /*------------------------------------------------------------------------- * Function: H5Dread_chunk @@ -708,6 +1059,51 @@ done: } /* end H5Dread_chunk() */ /*------------------------------------------------------------------------- + * Function: H5D__write_api_common + * + * Purpose: Common helper routine for sync/async dataset write operations. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D__write_api_common(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, + hid_t dxpl_id, const void *buf, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check arguments */ + if (mem_space_id < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid memory dataspace ID") + if (file_space_id < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file dataspace ID") + + /* Get dataset pointer */ + if (NULL == (*vol_obj_ptr = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id is not a dataset ID") + + /* Get the default dataset transfer property list if the user didn't provide one */ + if (H5P_DEFAULT == dxpl_id) + dxpl_id = H5P_DATASET_XFER_DEFAULT; + else if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms") + + /* Write the data */ + if (H5VL_dataset_write(*vol_obj_ptr, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, token_ptr) < + 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__write_api_common() */ + +/*------------------------------------------------------------------------- * Function: H5Dwrite * * Purpose: Writes (part of) a DSET from application memory BUF to the @@ -742,36 +1138,65 @@ herr_t H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t dxpl_id, const void *buf) { - H5VL_object_t *vol_obj = NULL; - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE6("e", "iiiii*x", dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf); - /* Check arguments */ - if (mem_space_id < 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid memory dataspace ID") - if (file_space_id < 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file dataspace ID") + /* Write the data */ + if (H5D__write_api_common(dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, NULL, NULL) < + 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't synchronously write data") - /* Get dataset pointer */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id is not a dataset ID") +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Dwrite() */ - /* Get the default dataset transfer property list if the user didn't provide one */ - if (H5P_DEFAULT == dxpl_id) - dxpl_id = H5P_DATASET_XFER_DEFAULT; - else if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms") +/*------------------------------------------------------------------------- + * Function: H5Dwrite_async + * + * Purpose: For asynchronous VOL with request token + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Houjun Tang + * Oct 15, 2019 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Dwrite_async(const char *app_file, const char *app_func, unsigned app_line, hid_t dset_id, + hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t dxpl_id, const void *buf, + hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Dataset VOL object */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE10("e", "*s*sIuiiiii*xi", app_file, app_func, app_line, dset_id, mem_type_id, mem_space_id, + file_space_id, dxpl_id, buf, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ /* Write the data */ - if ((ret_value = H5VL_dataset_write(vol_obj, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, - H5_REQUEST_NULL)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data") + if (H5D__write_api_common(dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, token_ptr, + &vol_obj) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't asynchronously write data") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE10(FUNC, "*s*sIuiiiii*xi", app_file, app_func, app_line, dset_id, + mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, es_id)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "can't insert token into event set") done: FUNC_LEAVE_API(ret_value) -} /* end H5Dwrite() */ +} /* end H5Dwrite_async() */ /*------------------------------------------------------------------------- * Function: H5Dwrite_chunk @@ -1207,8 +1632,7 @@ H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id, hsize_t *s supported = 0; if (H5VL_introspect_opt_query(vol_obj, H5VL_SUBCLS_DATASET, H5VL_NATIVE_DATASET_GET_VLEN_BUF_SIZE, &supported) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, - "can't check for 'get vlen buf size' operation") + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check for 'get vlen buf size' operation") if (supported & H5VL_OPT_QUERY_SUPPORTED) { /* Make the 'get_vlen_buf_size' callback */ if (H5VL_dataset_optional(vol_obj, H5VL_NATIVE_DATASET_GET_VLEN_BUF_SIZE, H5P_DATASET_XFER_DEFAULT, @@ -1226,27 +1650,28 @@ done: } /* end H5Dvlen_get_buf_size() */ /*------------------------------------------------------------------------- - * Function: H5Dset_extent + * Function: H5D__set_extent_api_common * - * Purpose: Modifies the dimensions of a dataset. - * Can change to a smaller dimension. + * Purpose: This is the common function for changing a dataset's dimensions * - * Return: Non-negative on success, negative on failure + * Return: Non-negative on success, negative on failure * *------------------------------------------------------------------------- */ -herr_t -H5Dset_extent(hid_t dset_id, const hsize_t size[]) +static herr_t +H5D__set_extent_api_common(hid_t dset_id, const hsize_t size[], void **token_ptr, + H5VL_object_t **_vol_obj_ptr) { - H5VL_object_t *vol_obj; /* Dataset for this operation */ - herr_t ret_value = SUCCEED; /* Return value */ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API(FAIL) - H5TRACE2("e", "i*h", dset_id, size); + FUNC_ENTER_STATIC /* Check args */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id parameter is not a valid dataset identifier") + if (NULL == (*vol_obj_ptr = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier") if (!size) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "size array cannot be NULL") @@ -1255,15 +1680,81 @@ H5Dset_extent(hid_t dset_id, const hsize_t size[]) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set collective metadata read info") /* Set the extent */ - if ((ret_value = H5VL_dataset_specific(vol_obj, H5VL_DATASET_SET_EXTENT, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL, size)) < 0) + if ((ret_value = H5VL_dataset_specific(*vol_obj_ptr, H5VL_DATASET_SET_EXTENT, H5P_DATASET_XFER_DEFAULT, + token_ptr, size)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set dataset extent") done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5D__set_extent_api_common() */ + +/*------------------------------------------------------------------------- + * Function: H5Dset_extent + * + * Purpose: Modifies the dimensions of a dataset. + * Can change to a smaller dimension. + * + * Return: Non-negative on success, negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Dset_extent(hid_t dset_id, const hsize_t size[]) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*h", dset_id, size); + + /* Change a datset's dimenions synchronously */ + if ((ret_value = H5D__set_extent_api_common(dset_id, size, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to synchronously change a dataset's dimensions") + +done: FUNC_LEAVE_API(ret_value) } /* end H5Dset_extent() */ /*------------------------------------------------------------------------- + * Function: H5Dset_extent_async + * + * Purpose: Asynchronous version of H5Dset_extent + * + * Return: Non-negative on success, negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Dset_extent_async(const char *app_file, const char *app_func, unsigned app_line, hid_t dset_id, + const hsize_t size[], hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE6("e", "*s*sIui*hi", app_file, app_func, app_line, dset_id, size, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Change a datset's dimenions asynchronously */ + if (H5D__set_extent_api_common(dset_id, size, token_ptr, &vol_obj) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to asynchronously change a dataset's dimensions") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert( + es_id, vol_obj->connector, token, + H5ARG_TRACE6(FUNC, "*s*sIui*hi", app_file, app_func, app_line, dset_id, size, es_id)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Dset_extent_async() */ + +/*------------------------------------------------------------------------- * Function: H5Dflush * * Purpose: Flushes all buffers associated with a dataset. @@ -1302,6 +1793,41 @@ done: } /* H5Dflush */ /*------------------------------------------------------------------------- + * Function: H5Dwait + * + * Purpose: Wait for all operations on a dataset. + * Tang: added for async + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Dwait(hid_t dset_id) +{ + H5VL_object_t *vol_obj; /* Dataset for this operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE1("e", "i", dset_id); + + /* Check args */ + if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id parameter is not a valid dataset identifier") + + /* Set up collective metadata if appropriate */ + if (H5CX_set_loc(dset_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set collective metadata read info") + + if ((ret_value = H5VL_dataset_specific(vol_obj, H5VL_DATASET_WAIT, H5P_DATASET_XFER_DEFAULT, + H5_REQUEST_NULL, dset_id)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTOPERATE, FAIL, "unable to wait dataset") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Dwait*/ + +/*------------------------------------------------------------------------- * Function: H5Drefresh * * Purpose: Refreshes all buffers associated with a dataset. diff --git a/src/H5Dbtree.c b/src/H5Dbtree.c index d0a191f..9147f0e 100644 --- a/src/H5Dbtree.c +++ b/src/H5Dbtree.c @@ -102,7 +102,7 @@ static herr_t H5D__btree_new_node(H5F_t *f, H5B_ins_t, void *_lt_key, void *_ haddr_t *addr_p /*out*/); static int H5D__btree_cmp2(void *_lt_key, void *_udata, void *_rt_key); static int H5D__btree_cmp3(void *_lt_key, void *_udata, void *_rt_key); -static htri_t H5D__btree_found(H5F_t *f, haddr_t addr, const void *_lt_key, void *_udata); +static htri_t H5D__btree_found(H5F_t *f, haddr_t addr, const void *_lt_key, hbool_t *found, void *_udata); static H5B_ins_t H5D__btree_insert(H5F_t *f, haddr_t addr, void *_lt_key, hbool_t *lt_key_changed, void *_md_key, void *_udata, void *_rt_key, hbool_t *rt_key_changed, haddr_t *new_node /*out*/); @@ -407,8 +407,9 @@ H5D__btree_cmp3(void *_lt_key, void *_udata, void *_rt_key) * called with the maximum stored chunk indices less than the * requested chunk indices. * - * Return: Non-negative (TRUE/FALSE) on success with information about the - * chunk returned through the UDATA argument. Negative on failure. + * Return: Non-negative on success with information about the + * chunk returned through the UDATA argument, if *FOUND is true. + * Negative on failure. * * Programmer: Robb Matzke * Thursday, October 9, 1997 @@ -416,31 +417,35 @@ H5D__btree_cmp3(void *_lt_key, void *_udata, void *_rt_key) *------------------------------------------------------------------------- */ static htri_t -H5D__btree_found(H5F_t H5_ATTR_UNUSED *f, haddr_t addr, const void *_lt_key, void *_udata) +H5D__btree_found(H5F_t H5_ATTR_UNUSED *f, haddr_t addr, const void *_lt_key, hbool_t *found, void *_udata) { H5D_chunk_ud_t * udata = (H5D_chunk_ud_t *)_udata; const H5D_btree_key_t *lt_key = (const H5D_btree_key_t *)_lt_key; unsigned u; - htri_t ret_value = TRUE; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC_NOERR /* Check arguments */ HDassert(f); HDassert(H5F_addr_defined(addr)); - HDassert(udata); HDassert(lt_key); + HDassert(found); + HDassert(udata); /* Is this *really* the requested chunk? */ for (u = 0; u < udata->common.layout->ndims; u++) - if (udata->common.scaled[u] >= (lt_key->scaled[u] + 1)) - HGOTO_DONE(FALSE) + if (udata->common.scaled[u] >= (lt_key->scaled[u] + 1)) { + *found = FALSE; + HGOTO_DONE(SUCCEED) + } /* Initialize return values */ HDassert(lt_key->nbytes > 0); udata->chunk_block.offset = addr; udata->chunk_block.length = lt_key->nbytes; udata->filter_mask = lt_key->filter_mask; + *found = TRUE; done: FUNC_LEAVE_NOAPI(ret_value) @@ -990,7 +995,8 @@ done: static herr_t H5D__btree_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata) { - herr_t ret_value = SUCCEED; /* Return value */ + hbool_t found; /* Whether chunk was found */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC @@ -1004,8 +1010,9 @@ H5D__btree_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udat HDassert(udata); /* Go get the chunk information from the B-tree */ - if (H5B_find(idx_info->f, H5B_BTREE, idx_info->storage->idx_addr, udata) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk info") + found = FALSE; + if (H5B_find(idx_info->f, H5B_BTREE, idx_info->storage->idx_addr, &found, udata) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTFIND, FAIL, "can't check for chunk in B-tree") done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5Dbtree2.c b/src/H5Dbtree2.c index 866b794..aa26bf8 100644 --- a/src/H5Dbtree2.c +++ b/src/H5Dbtree2.c @@ -969,6 +969,7 @@ H5D__bt2_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata) H5D_bt2_ud_t bt2_udata; /* User data for v2 B-tree calls */ H5D_chunk_rec_t found_rec; /* Record found from searching for object */ unsigned u; /* Local index variable */ + hbool_t found; /* Whether chunk was found */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC @@ -1010,17 +1011,18 @@ H5D__bt2_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata) bt2_udata.rec.scaled[u] = udata->common.scaled[u]; /* Go get chunk information from v2 B-tree */ - if (H5B2_find(bt2, &bt2_udata, H5D__bt2_found_cb, &found_rec) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree") + found = FALSE; + if (H5B2_find(bt2, &bt2_udata, &found, H5D__bt2_found_cb, &found_rec) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTFIND, FAIL, "can't check for chunk in v2 B-tree") - /* Set common info for the chunk */ - udata->chunk_block.offset = found_rec.chunk_addr; - - /* Check for setting other info */ - if (H5F_addr_defined(udata->chunk_block.offset)) { + /* Check if chunk was found */ + if (found) { /* Sanity check */ HDassert(0 != found_rec.nbytes); + /* Set common info for the chunk */ + udata->chunk_block.offset = found_rec.chunk_addr; + /* Set other info for the chunk */ if (idx_info->pline->nused > 0) { /* filtered chunk */ udata->chunk_block.length = found_rec.nbytes; @@ -1032,6 +1034,7 @@ H5D__bt2_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata) } /* end else */ } /* end if */ else { + udata->chunk_block.offset = HADDR_UNDEF; udata->chunk_block.length = 0; udata->filter_mask = 0; } /* end else */ diff --git a/src/H5Dmpio.c b/src/H5Dmpio.c index 273901a..22b8feb 100644 --- a/src/H5Dmpio.c +++ b/src/H5Dmpio.c @@ -886,14 +886,13 @@ H5D__chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_inf HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish optimized multiple filtered chunk MPI-IO") } /* end if */ - else - if (H5D__link_chunk_filtered_collective_io(io_info, type_info, fm) < 0) - HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish filtered linked chunk MPI-IO") + else if (H5D__link_chunk_filtered_collective_io(io_info, type_info, fm) < 0) + HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish filtered linked chunk MPI-IO") } /* end if */ else /* Perform unfiltered link chunk collective IO */ if (H5D__link_chunk_collective_io(io_info, type_info, fm, sum_chunk) < 0) - HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish linked chunk MPI-IO") + HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish linked chunk MPI-IO") break; case H5D_MULTI_CHUNK_IO: /* direct request to do multi-chunk IO */ @@ -907,7 +906,7 @@ H5D__chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_inf else /* Perform unfiltered multi chunk collective IO */ if (H5D__multi_chunk_collective_io(io_info, type_info, fm) < 0) - HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish optimized multiple chunk MPI-IO") + HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish optimized multiple chunk MPI-IO") break; } /* end switch */ @@ -1378,7 +1377,8 @@ H5D__link_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_in H5CX_set_mpio_actual_io_mode(H5D_MPIO_CHUNK_COLLECTIVE); /* Build a list of selected chunks in the collective io operation */ - if (H5D__construct_filtered_io_info_list(io_info, type_info, fm, &chunk_list, &chunk_list_num_entries) < 0) + if (H5D__construct_filtered_io_info_list(io_info, type_info, fm, &chunk_list, &chunk_list_num_entries) < + 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "couldn't construct filtered I/O info list") if (io_info->op_type == H5D_IO_OP_WRITE) { /* Filtered collective write */ @@ -2967,7 +2967,7 @@ H5D__chunk_redistribute_shared_chunks(const H5D_io_info_t *io_info, const H5D_ty num_send_requests++; } /* end if */ - } /* end for */ + } /* end for */ /* Perform all the recvs on the chunks this rank owns */ for (i = 0, last_assigned_idx = 0; i < *local_chunk_array_num_entries; i++) { diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h index fa83fda..095445b 100644 --- a/src/H5Dpkg.h +++ b/src/H5Dpkg.h @@ -216,9 +216,9 @@ typedef struct H5D_io_info_t { /* QAK: Delete the f_sh field when oloc has a shared file pointer? */ H5F_shared_t *f_sh; /* Pointer to shared file struct that dataset is within */ #ifdef H5_HAVE_PARALLEL - MPI_Comm comm; /* MPI communicator for file */ - hbool_t using_mpi_vfd; /* Whether the file is using an MPI-based VFD */ -#endif /* H5_HAVE_PARALLEL */ + MPI_Comm comm; /* MPI communicator for file */ + hbool_t using_mpi_vfd; /* Whether the file is using an MPI-based VFD */ +#endif /* H5_HAVE_PARALLEL */ H5D_storage_t * store; /* Dataset storage info */ H5D_layout_ops_t layout_ops; /* Dataset layout I/O operation function pointers */ H5D_io_ops_t io_ops; /* I/O operation function pointers */ diff --git a/src/H5Dpublic.h b/src/H5Dpublic.h index 4e40d27..507f75b 100644 --- a/src/H5Dpublic.h +++ b/src/H5Dpublic.h @@ -127,15 +127,22 @@ typedef herr_t (*H5D_gather_func_t)(const void *dst_buf, size_t dst_buf_bytes_us extern "C" { #endif -H5_DLL hid_t H5Dcreate2(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, hid_t lcpl_id, - hid_t dcpl_id, hid_t dapl_id); -H5_DLL hid_t H5Dcreate_anon(hid_t file_id, hid_t type_id, hid_t space_id, hid_t plist_id, hid_t dapl_id); -H5_DLL hid_t H5Dopen2(hid_t file_id, const char *name, hid_t dapl_id); -H5_DLL hid_t H5Dget_space(hid_t dset_id); -H5_DLL herr_t H5Dget_space_status(hid_t dset_id, H5D_space_status_t *allocation); -H5_DLL hid_t H5Dget_type(hid_t dset_id); -H5_DLL hid_t H5Dget_create_plist(hid_t dset_id); -H5_DLL hid_t H5Dget_access_plist(hid_t dset_id); +H5_DLL hid_t H5Dcreate2(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, hid_t lcpl_id, + hid_t dcpl_id, hid_t dapl_id); +H5_DLL hid_t H5Dcreate_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *name, hid_t type_id, hid_t space_id, hid_t lcpl_id, hid_t dcpl_id, + hid_t dapl_id, hid_t es_id); +H5_DLL hid_t H5Dcreate_anon(hid_t file_id, hid_t type_id, hid_t space_id, hid_t plist_id, hid_t dapl_id); +H5_DLL hid_t H5Dopen2(hid_t file_id, const char *name, hid_t dapl_id); +H5_DLL hid_t H5Dopen_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *name, hid_t dapl_id, hid_t es_id); +H5_DLL hid_t H5Dget_space(hid_t dset_id); +H5_DLL hid_t H5Dget_space_async(const char *app_file, const char *app_func, unsigned app_line, hid_t dset_id, + hid_t es_id); +H5_DLL herr_t H5Dget_space_status(hid_t dset_id, H5D_space_status_t *allocation); +H5_DLL hid_t H5Dget_type(hid_t dset_id); +H5_DLL hid_t H5Dget_create_plist(hid_t dset_id); +H5_DLL hid_t H5Dget_access_plist(hid_t dset_id); H5_DLL hsize_t H5Dget_storage_size(hid_t dset_id); H5_DLL herr_t H5Dget_chunk_storage_size(hid_t dset_id, const hsize_t *offset, hsize_t *chunk_bytes); H5_DLL herr_t H5Dget_num_chunks(hid_t dset_id, hid_t fspace_id, hsize_t *nchunks); @@ -146,8 +153,14 @@ H5_DLL herr_t H5Dget_chunk_info(hid_t dset_id, hid_t fspace_id, hsize_t chk_idx H5_DLL haddr_t H5Dget_offset(hid_t dset_id); H5_DLL herr_t H5Dread(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t plist_id, void *buf /*out*/); +H5_DLL herr_t H5Dread_async(const char *app_file, const char *app_func, unsigned app_line, hid_t dset_id, + hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t plist_id, + void *buf /*out*/, hid_t es_id); H5_DLL herr_t H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t plist_id, const void *buf); +H5_DLL herr_t H5Dwrite_async(const char *app_file, const char *app_func, unsigned app_line, hid_t dset_id, + hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t plist_id, + const void *buf, hid_t es_id); H5_DLL herr_t H5Dwrite_chunk(hid_t dset_id, hid_t dxpl_id, uint32_t filters, const hsize_t *offset, size_t data_size, const void *buf); H5_DLL herr_t H5Dread_chunk(hid_t dset_id, hid_t dxpl_id, const hsize_t *offset, uint32_t *filters, @@ -156,19 +169,48 @@ H5_DLL herr_t H5Diterate(void *buf, hid_t type_id, hid_t space_id, H5D_operator H5_DLL herr_t H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id, hsize_t *size); H5_DLL herr_t H5Dfill(const void *fill, hid_t fill_type, void *buf, hid_t buf_type, hid_t space); H5_DLL herr_t H5Dset_extent(hid_t dset_id, const hsize_t size[]); +H5_DLL herr_t H5Dset_extent_async(const char *app_file, const char *app_func, unsigned app_line, + hid_t dset_id, const hsize_t size[], hid_t es_id); H5_DLL herr_t H5Dflush(hid_t dset_id); +H5_DLL herr_t H5Dwait(hid_t dset_id); H5_DLL herr_t H5Drefresh(hid_t dset_id); H5_DLL herr_t H5Dscatter(H5D_scatter_func_t op, void *op_data, hid_t type_id, hid_t dst_space_id, void *dst_buf); H5_DLL herr_t H5Dgather(hid_t src_space_id, const void *src_buf, hid_t type_id, size_t dst_buf_size, void *dst_buf, H5D_gather_func_t op, void *op_data); H5_DLL herr_t H5Dclose(hid_t dset_id); +H5_DLL herr_t H5Dclose_async(const char *app_file, const char *app_func, unsigned app_line, hid_t dset_id, + hid_t es_id); /* Internal API routines */ H5_DLL herr_t H5Ddebug(hid_t dset_id); H5_DLL herr_t H5Dformat_convert(hid_t dset_id); H5_DLL herr_t H5Dget_chunk_index_type(hid_t did, H5D_chunk_index_t *idx_type); +/* API Wrappers for async routines */ +/* (Must be defined _after_ the function prototype) */ +/* (And must only defined when included in application code, not the library) */ +#ifndef H5D_MODULE +#define H5Dcreate_async(...) H5Dcreate_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Dopen_async(...) H5Dopen_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Dget_space_async(...) H5Dget_space_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Dread_async(...) H5Dread_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Dwrite_async(...) H5Dwrite_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Dset_extent_async(...) H5Dset_extent_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Dclose_async(...) H5Dclose_async(__FILE__, __func__, __LINE__, __VA_ARGS__) + +/* Define "wrapper" versions of function calls, to allow compile-time values to + * be passed in by language wrapper or library layer on top of HDF5. + */ +#define H5Dcreate_async_wrap H5_NO_EXPAND(H5Dcreate_async) +#define H5Dopen_async_wrap H5_NO_EXPAND(H5Dopen_async) +#define H5Dget_space_async_wrap H5_NO_EXPAND(H5Dget_space_async) +#define H5Dread_async_wrap H5_NO_EXPAND(H5Dread_async) +#define H5Dwrite_async_wrap H5_NO_EXPAND(H5Dwrite_async) +#define H5Dset_extent_async_wrap H5_NO_EXPAND(H5Dset_extent_async) +#define H5Dclose_async_wrap H5_NO_EXPAND(H5Dclose_async) +#endif /* H5D_MODULE */ + /* Symbols defined for compatibility with previous versions of the HDF5 API. * * Use of these symbols is deprecated. diff --git a/src/H5Dscatgath.c b/src/H5Dscatgath.c index 65bc28a..2976709 100644 --- a/src/H5Dscatgath.c +++ b/src/H5Dscatgath.c @@ -898,4 +898,3 @@ H5D__compound_opt_write(size_t nelmts, const H5D_type_info_t *type_info) FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5D__compound_opt_write() */ - diff --git a/src/H5Dvirtual.c b/src/H5Dvirtual.c index 77f1c8c..1df5d0b 100644 --- a/src/H5Dvirtual.c +++ b/src/H5Dvirtual.c @@ -833,8 +833,8 @@ herr_t H5D__virtual_delete(H5F_t *f, H5O_storage_t *storage) { #ifdef NOT_YET - int heap_rc; /* Reference count of global heap object */ -#endif /* NOT_YET */ + int heap_rc; /* Reference count of global heap object */ +#endif /* NOT_YET */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -85,6 +85,7 @@ static H5E_t * H5E__get_current_stack(void); static herr_t H5E__set_current_stack(H5E_t *estack); static herr_t H5E__close_stack(H5E_t *err_stack, void **request); static ssize_t H5E__get_num(const H5E_t *err_stack); +static herr_t H5E__append_stack(H5E_t *dst_estack, const H5E_t *src_stack); /*********************/ /* Package Variables */ @@ -1667,3 +1668,111 @@ H5Eauto_is_v2(hid_t estack_id, unsigned *is_stack) done: FUNC_LEAVE_API(ret_value) } /* end H5Eauto_is_v2() */ + +/*------------------------------------------------------------------------- + * Function: H5Eappend_stack + * + * Purpose: Appends one error stack to another, optionally closing the + * source stack. + * + * Return: Non-negative value on success/Negative on failure + * + * Programmer: Quincey Koziol + * Wednesday, October 7, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Eappend_stack(hid_t dst_stack_id, hid_t src_stack_id, hbool_t close_source_stack) +{ + H5E_t *dst_stack, *src_stack; /* Error stacks */ + herr_t ret_value = SUCCEED; /* Return value */ + + /* Don't clear the error stack! :-) */ + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "iib", dst_stack_id, src_stack_id, close_source_stack); + + /* Check args */ + if (NULL == (dst_stack = (H5E_t *)H5I_object_verify(dst_stack_id, H5I_ERROR_STACK))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dst_stack_id not a error stack ID") + if (NULL == (src_stack = (H5E_t *)H5I_object_verify(src_stack_id, H5I_ERROR_STACK))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "src_stack_id not a error stack ID") + + /* Append the source stack to the destination stack */ + if (H5E__append_stack(dst_stack, src_stack) < 0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTAPPEND, FAIL, "can't append stack") + + /* Close source error stack, if requested */ + if (close_source_stack) + /* Decrement the counter on the error stack. It will be freed if the + * count reaches zero. + */ + if (H5I_dec_app_ref(src_stack_id) < 0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on source error stack") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Eappend_stack() */ + +/*------------------------------------------------------------------------- + * Function: H5E__append_stack + * + * Purpose: Private function to append error stacks. + * + * Return: Non-negative value on success/Negative on failure + * + * Programmer: Quincey Koziol + * Wednesday, October 7, 2020 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5E__append_stack(H5E_t *dst_stack, const H5E_t *src_stack) +{ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity checks */ + HDassert(dst_stack); + HDassert(src_stack); + + /* Copy the errors from the source stack to the destination stack */ + for (u = 0; u < src_stack->nused; u++) { + const H5E_error2_t *src_error; /* Pointers to source error on stack */ + H5E_error2_t * dst_error; /* Pointers to destination error on stack */ + + /* Get pointers into the current error stack location */ + src_error = &(src_stack->slot[u]); + dst_error = &(dst_stack->slot[dst_stack->nused]); + + /* Increment the IDs to indicate that they are used in this stack */ + if (H5I_inc_ref(src_error->cls_id, FALSE) < 0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to increment ref count on error class") + dst_error->cls_id = src_error->cls_id; + if (H5I_inc_ref(src_error->maj_num, FALSE) < 0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to increment ref count on error message") + dst_error->maj_num = src_error->maj_num; + if (H5I_inc_ref(src_error->min_num, FALSE) < 0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to increment ref count on error message") + dst_error->min_num = src_error->min_num; + if (NULL == (dst_error->func_name = H5MM_xstrdup(src_error->func_name))) + HGOTO_ERROR(H5E_ERROR, H5E_CANTALLOC, FAIL, "memory allocation failed") + if (NULL == (dst_error->file_name = H5MM_xstrdup(src_error->file_name))) + HGOTO_ERROR(H5E_ERROR, H5E_CANTALLOC, FAIL, "memory allocation failed") + dst_error->line = src_error->line; + if (NULL == (dst_error->desc = H5MM_xstrdup(src_error->desc))) + HGOTO_ERROR(H5E_ERROR, H5E_CANTALLOC, FAIL, "memory allocation failed") + + /* Increment # of errors in destination stack */ + dst_stack->nused++; + + /* Check for destination stack full */ + if (dst_stack->nused >= H5E_NSLOTS) + break; + } /* end for */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5E__append_stack() */ diff --git a/src/H5EAtest.c b/src/H5EAtest.c index bbd436e..9a7db42 100644 --- a/src/H5EAtest.c +++ b/src/H5EAtest.c @@ -262,9 +262,9 @@ BEGIN_FUNC(STATIC, NOERR, herr_t, SUCCEED, -, /* Local variables */ #ifndef NDEBUG H5EA__test_ctx_t *ctx = (H5EA__test_ctx_t *)_ctx; /* Callback context to destroy */ -#endif /* NDEBUG */ - uint64_t * elmt = (uint64_t *)_elmt; /* Convenience pointer to native elements */ - const uint8_t *raw = (const uint8_t *)_raw; /* Convenience pointer to raw elements */ +#endif /* NDEBUG */ + uint64_t * elmt = (uint64_t *)_elmt; /* Convenience pointer to native elements */ + const uint8_t *raw = (const uint8_t *)_raw; /* Convenience pointer to raw elements */ /* Sanity checks */ HDassert(raw); diff --git a/src/H5ES.c b/src/H5ES.c new file mode 100644 index 0000000..746406e --- /dev/null +++ b/src/H5ES.c @@ -0,0 +1,378 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5ES.c + * Apr 6 2020 + * Quincey Koziol + * + * Purpose: Implements an "event set" for managing asynchronous + * operations. + * + * Please see the asynchronous I/O RFC document + * for a full description of how they work, etc. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#include "H5ESmodule.h" /* This source code file is part of the H5ES module */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5ESpkg.h" /* Event Sets */ +#include "H5FLprivate.h" /* Free Lists */ +#include "H5Iprivate.h" /* IDs */ + +/****************/ +/* Local Macros */ +/****************/ + +/******************/ +/* Local Typedefs */ +/******************/ + +/********************/ +/* Package Typedefs */ +/********************/ + +/********************/ +/* Local Prototypes */ +/********************/ + +/*********************/ +/* Package Variables */ +/*********************/ + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/*******************/ +/* Local Variables */ +/*******************/ + +/*------------------------------------------------------------------------- + * Function: H5EScreate + * + * Purpose: Creates an event set. + * + * Return: Success: An ID for the event set + * Failure: H5I_INVALID_HID + * + * Programmer: Quincey Koziol + * Wednesday, April 8, 2020 + * + *------------------------------------------------------------------------- + */ +hid_t +H5EScreate(void) +{ + H5ES_t *es; /* Pointer to event set object */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE0("i", ""); + + /* Create the new event set object */ + if (NULL == (es = H5ES__create())) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTCREATE, H5I_INVALID_HID, "can't create event set") + + /* Register the new event set to get an ID for it */ + if ((ret_value = H5I_register(H5I_EVENTSET, es, TRUE)) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register event set") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5EScreate() */ + +/*------------------------------------------------------------------------- + * Function: H5ESget_count + * + * Purpose: Retrieve the # of events in an event set + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Wednesday, April 8, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESget_count(hid_t es_id, size_t *count /*out*/) +{ + H5ES_t *es; /* Event set */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ix", es_id, count); + + /* Check arguments */ + if (NULL == (es = H5I_object_verify(es_id, H5I_EVENTSET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event set identifier") + + /* Retrieve the count, if non-NULL */ + if (count) + *count = H5ES__list_count(&es->active); + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ESget_count() */ + +/*------------------------------------------------------------------------- + * Function: H5ESget_op_counter + * + * Purpose: Retrieve the counter that will be assigned to the next operation + * inserted into the event set. + * + * Note: This is designed for wrapper libraries mainly, to use as a + * mechanism for matching operations inserted into the event + * set with [possible] errors that occur. + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Fiiday, November 6, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESget_op_counter(hid_t es_id, uint64_t *op_counter /*out*/) +{ + H5ES_t *es; /* Event set */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ix", es_id, op_counter); + + /* Check arguments */ + if (NULL == (es = H5I_object_verify(es_id, H5I_EVENTSET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event set identifier") + + /* Retrieve the operation counter, if non-NULL */ + if (op_counter) + *op_counter = es->op_counter; + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ESget_op_counter() */ + +/*------------------------------------------------------------------------- + * Function: H5ESwait + * + * Purpose: Wait (with timeout) for operations in event set to complete + * + * Note: Timeout value is in ns, and is for the H5ESwait call, not each + * individual operation. For example: if '10' is passed as + * a timeout value and the event set waited 4ns for the first + * operation to complete, the remaining operations would be + * allowed to wait for at most 6ns more. i.e. the timeout value + * is "used up" across all operations, until it reaches 0, then + * any remaining operations are only checked for completion, not + * waited on. + * + * Note: This call will stop waiting on operations and will return + * immediately if an operation fails. If a failure occurs, the + * value returned for the # of operations in progress may be + * inaccurate. + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Monday, July 13, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESwait(hid_t es_id, uint64_t timeout, size_t *num_in_progress /*out*/, hbool_t *op_failed /*out*/) +{ + H5ES_t *es; /* Event set */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE4("e", "iULxx", es_id, timeout, num_in_progress, op_failed); + + /* Check arguments */ + if (NULL == (es = H5I_object_verify(es_id, H5I_EVENTSET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event set identifier") + if (NULL == num_in_progress) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL num_in_progress pointer") + if (NULL == op_failed) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL op_failed pointer") + + /* Wait for operations */ + if (H5ES__wait(es, timeout, num_in_progress, op_failed) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTWAIT, FAIL, "can't wait on operations") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ESwait() */ + +/*------------------------------------------------------------------------- + * Function: H5ESget_err_status + * + * Purpose: Check if event set has failed operations + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Thursday, October 15, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESget_err_status(hid_t es_id, hbool_t *err_status /*out*/) +{ + H5ES_t *es; /* Event set */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ix", es_id, err_status); + + /* Check arguments */ + if (NULL == (es = H5I_object_verify(es_id, H5I_EVENTSET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event set identifier") + + /* Retrieve the error flag, if non-NULL */ + if (err_status) + *err_status = es->err_occurred; + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ESget_err_status() */ + +/*------------------------------------------------------------------------- + * Function: H5ESget_err_count + * + * Purpose: Retrieve # of failed operations + * + * Note: Does not wait for active operations to complete, so count may + * not include all failures. + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Thursday, October 15, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESget_err_count(hid_t es_id, size_t *num_errs /*out*/) +{ + H5ES_t *es; /* Event set */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ix", es_id, num_errs); + + /* Check arguments */ + if (NULL == (es = H5I_object_verify(es_id, H5I_EVENTSET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event set identifier") + + /* Retrieve the error flag, if non-NULL */ + if (num_errs) { + if (es->err_occurred) + *num_errs = H5ES__list_count(&es->failed); + else + *num_errs = 0; + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ESget_err_count() */ + +/*------------------------------------------------------------------------- + * Function: H5ESget_err_info + * + * Purpose: Retrieve information about failed operations + * + * Note: The strings retrieved for each error info must be released + * by calling H5free_memory(). + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Friday, November 6, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESget_err_info(hid_t es_id, size_t num_err_info, H5ES_err_info_t err_info[] /*out*/, + size_t *num_cleared /*out*/) +{ + H5ES_t *es; /* Event set */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE4("e", "izxx", es_id, num_err_info, err_info, num_cleared); + + /* Check arguments */ + if (NULL == (es = H5I_object_verify(es_id, H5I_EVENTSET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event set identifier") + if (0 == num_err_info) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "err_info array size is 0") + if (NULL == err_info) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL err_info array pointer") + if (NULL == num_cleared) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL errors cleared pointer") + + /* Retrieve the error information */ + if (H5ES__get_err_info(es, num_err_info, err_info, num_cleared) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTGET, FAIL, "can't retrieve error info for failed operation(s)") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ESget_err_info() */ + +/*------------------------------------------------------------------------- + * Function: H5ESclose + * + * Purpose: Closes an event set. + * + * Note: Fails if active operations are present. + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Wednesday, April 8, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESclose(hid_t es_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE1("e", "i", es_id); + + /* Check arguments */ + if (H5I_EVENTSET != H5I_get_type(es_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an event set") + + /* + * Decrement the counter on the object. It will be freed if the count + * reaches zero. + */ + if (H5I_dec_app_ref(es_id) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTDEC, FAIL, "unable to decrement ref count on event set") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ESclose() */ diff --git a/src/H5ESevent.c b/src/H5ESevent.c new file mode 100644 index 0000000..ffef76d --- /dev/null +++ b/src/H5ESevent.c @@ -0,0 +1,197 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5ESevent.c + * Nov 7 2020 + * Quincey Koziol + * + * Purpose: Operations on "events" for managing asynchronous + * operations. + * + * Please see the asynchronous I/O RFC document + * for a full description of how they work, etc. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#include "H5ESmodule.h" /* This source code file is part of the H5ES module */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5ESpkg.h" /* Event Sets */ +#include "H5FLprivate.h" /* Free Lists */ +#include "H5MMprivate.h" /* Memory management */ + +/****************/ +/* Local Macros */ +/****************/ + +/******************/ +/* Local Typedefs */ +/******************/ + +/********************/ +/* Package Typedefs */ +/********************/ + +/********************/ +/* Local Prototypes */ +/********************/ + +/*********************/ +/* Package Variables */ +/*********************/ + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Declare a static free list to manage H5ES_event_t structs */ +H5FL_DEFINE_STATIC(H5ES_event_t); + +/*------------------------------------------------------------------------- + * Function: H5ES__event_new + * + * Purpose: Allocate and initialize a new event + * + * Return: Non-NULL pointer to new event on success, NULL on failure + * + * Programmer: Quincey Koziol + * Saturday, November 7, 2020 + * + *------------------------------------------------------------------------- + */ +H5ES_event_t * +H5ES__event_new(H5VL_t *connector, void *token) +{ + H5ES_event_t * ev = NULL; /* New event */ + H5VL_object_t *request = NULL; /* Async request token VOL object */ + H5ES_event_t * ret_value = NULL; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Sanity check */ + HDassert(connector); + HDassert(token); + + /* Create vol object for token */ + if (NULL == (request = H5VL_create_object(token, connector))) { + if (H5VL_request_free(token) < 0) + HDONE_ERROR(H5E_EVENTSET, H5E_CANTFREE, NULL, "can't free request") + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTINIT, NULL, "can't create vol object for request token") + } /* end if */ + + /* Allocate space for new event */ + if (NULL == (ev = H5FL_CALLOC(H5ES_event_t))) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, NULL, "can't allocate event object") + + /* Set request for event */ + ev->request = request; + + /* Set return value */ + ret_value = ev; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5ES__event_new() */ + +/*------------------------------------------------------------------------- + * Function: H5ES__event_free + * + * Purpose: Free an event + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Saturday, November 7, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ES__event_free(H5ES_event_t *ev) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Sanity check */ + HDassert(ev); + + if (ev->api_name) + H5MM_xfree_const(ev->api_name); + if (ev->api_args) + H5MM_xfree_const(ev->api_args); + if (ev->app_file) + H5MM_xfree_const(ev->app_file); + if (ev->app_func) + H5MM_xfree_const(ev->app_func); + if (ev->request) { + /* Free the request */ + if (H5VL_request_free(ev->request) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTFREE, FAIL, "unable to free request") + + /* Free the VOL object for the request */ + if (H5VL_free_object(ev->request) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, FAIL, "can't free VOL request object") + } /* end if */ + + H5FL_FREE(H5ES_event_t, ev); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES__event_free() */ + +/*------------------------------------------------------------------------- + * Function: H5ES__event_completed + * + * Purpose: Handle a completed event + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Sunday, November 8, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ES__event_completed(H5ES_event_t *ev, H5ES_event_list_t *el) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Sanity check */ + HDassert(ev); + + /* Remove the event from the event list */ + H5ES__list_remove(el, ev); + + /* Free the event */ + if (H5ES__event_free(ev) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTFREE, FAIL, "unable to free event") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES__event_completed() */ diff --git a/src/H5ESint.c b/src/H5ESint.c new file mode 100644 index 0000000..17d7806 --- /dev/null +++ b/src/H5ESint.c @@ -0,0 +1,666 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5ESint.c + * Apr 8 2020 + * Quincey Koziol + * + * Purpose: Internal "event set" routines for managing asynchronous + * operations. + * + * Please see the asynchronous I/O RFC document + * for a full description of how they work, etc. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#include "H5ESmodule.h" /* This source code file is part of the H5ES module */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5ESpkg.h" /* Event Sets */ +#include "H5FLprivate.h" /* Free Lists */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5RSprivate.h" /* Reference-counted strings */ + +/****************/ +/* Local Macros */ +/****************/ + +/******************/ +/* Local Typedefs */ +/******************/ + +/* Callback context for wait operations */ +typedef struct H5ES_wait_ctx_t { + H5ES_t * es; /* Event set being operated on */ + uint64_t timeout; /* Timeout for wait operation */ + size_t * num_in_progress; /* Count of # of operations that have not completed */ + hbool_t *op_failed; /* Flag to indicate an operation failed */ +} H5ES_wait_ctx_t; + +/* Callback context for get error info (gei) operations */ +typedef struct H5ES_gei_ctx_t { + H5ES_t * es; /* Event set being operated on */ + size_t num_err_info; /* # of elements in err_info[] array */ + size_t curr_err; /* Index of current error in array */ + H5ES_err_info_t *curr_err_info; /* Pointer to current element in err_info[] array */ +} H5ES_gei_ctx_t; + +/********************/ +/* Package Typedefs */ +/********************/ + +/********************/ +/* Local Prototypes */ +/********************/ +static herr_t H5ES__close_cb(void *es, void **request_token); +static herr_t H5ES__handle_fail(H5ES_t *es, H5ES_event_t *ev); +static int H5ES__wait_cb(H5ES_event_t *ev, void *_ctx); +static int H5ES__get_err_info_cb(H5ES_event_t *ev, void *_ctx); +static int H5ES__close_failed_cb(H5ES_event_t *ev, void *_ctx); + +/*********************/ +/* Package Variables */ +/*********************/ + +/* Package initialization variable */ +hbool_t H5_PKG_INIT_VAR = FALSE; + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Event Set ID class */ +static const H5I_class_t H5I_EVENTSET_CLS[1] = {{ + H5I_EVENTSET, /* ID class value */ + 0, /* Class flags */ + 0, /* # of reserved IDs for class */ + (H5I_free_t)H5ES__close_cb /* Callback routine for closing objects of this class */ +}}; + +/* Declare a static free list to manage H5ES_t structs */ +H5FL_DEFINE_STATIC(H5ES_t); + +/*------------------------------------------------------------------------- + * Function: H5ES__init_package + * + * Purpose: Initializes any interface-specific data or routines. + * + * Return: Non-negative on success / Negative on failure + * + * Programmer: Quincey Koziol + * Monday, April 6, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ES__init_package(void) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Initialize the ID group for the event set IDs */ + if (H5I_register_type(H5I_EVENTSET_CLS) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTINIT, FAIL, "unable to initialize interface") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES__init_package() */ + +/*------------------------------------------------------------------------- + * Function: H5ES_term_package + * + * Purpose: Terminate this interface. + * + * Return: Success: Positive if anything is done that might + * affect other interfaces; zero otherwise. + * Failure: Negative + * + * Programmer: Quincey Koziol + * Monday, April 6, 2020 + * + *------------------------------------------------------------------------- + */ +int +H5ES_term_package(void) +{ + int n = 0; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + if (H5_PKG_INIT_VAR) { + /* Destroy the event set ID group */ + n += (H5I_dec_type_ref(H5I_EVENTSET) > 0); + + /* Mark closed */ + if (0 == n) + H5_PKG_INIT_VAR = FALSE; + } /* end if */ + + FUNC_LEAVE_NOAPI(n) +} /* end H5ES_term_package() */ + +/*------------------------------------------------------------------------- + * Function: H5ES__close_cb + * + * Purpose: Called when the ref count reaches zero on an event set's ID + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Monday, April 6, 2020 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5ES__close_cb(void *_es, void H5_ATTR_UNUSED **rt) +{ + H5ES_t *es = (H5ES_t *)_es; /* The event set to close */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity check */ + HDassert(es); + + /* Close the event set object */ + if (H5ES__close(es) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CLOSEERROR, FAIL, "unable to close event set"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES__close_cb() */ + +/*------------------------------------------------------------------------- + * Function: H5ES__create + * + * Purpose: Private function to create an event set object + * + * Return: Success: Pointer to an event set struct + * Failure: NULL + * + * Programmer: Quincey Koziol + * Wednesday, April 8, 2020 + * + *------------------------------------------------------------------------- + */ +H5ES_t * +H5ES__create(void) +{ + H5ES_t *es = NULL; /* Pointer to event set */ + H5ES_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Allocate space for new event set */ + if (NULL == (es = H5FL_CALLOC(H5ES_t))) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, NULL, "can't allocate event set object") + + /* Set the return value */ + ret_value = es; + +done: + if (!ret_value) + if (es && H5ES__close(es) < 0) + HDONE_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, NULL, "unable to free event set") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES__create() */ + +/*------------------------------------------------------------------------- + * Function: H5ES_insert + * + * Purpose: Insert a request token into an event set + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Wednesday, April 8, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ES_insert(hid_t es_id, H5VL_t *connector, void *token, const char *caller, const char *caller_args, ...) +{ + H5ES_t * es = NULL; /* Event set for the operation */ + H5ES_event_t *ev = NULL; /* Event for request */ + H5RS_str_t * rs = NULL; /* Ref-counted string to compose formatted argument string in */ + const char * app_file; /* Application source file name */ + const char * app_func; /* Application source function name */ + const char * s; /* Pointer to internal string from ref-counted string */ + va_list ap; /* Varargs for caller */ + hbool_t arg_started = FALSE; /* Whether the va_list has been started */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(connector); + HDassert(token); + HDassert(caller); + HDassert(caller_args); + + /* Get event set */ + if (NULL == (es = (H5ES_t *)H5I_object_verify(es_id, H5I_EVENTSET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an event set") + + /* Check for errors in event set */ + if (es->err_occurred) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTINSERT, FAIL, "event set has failed operations") + + /* Create new event */ + if (NULL == (ev = H5ES__event_new(connector, token))) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTCREATE, FAIL, "can't create event object") + + /* Start working on the API routines arguments */ + HDva_start(ap, caller_args); + arg_started = TRUE; + + /* Copy the app source information */ + (void)HDva_arg(ap, char *); /* Toss the 'app_file' parameter name */ + app_file = HDva_arg(ap, char *); + if (NULL == (ev->app_file = H5MM_strdup(app_file))) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, FAIL, "can't copy app source file name") + (void)HDva_arg(ap, char *); /* Toss the 'app_func' parameter name */ + app_func = HDva_arg(ap, char *); + if (NULL == (ev->app_func = H5MM_strdup(app_func))) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, FAIL, "can't copy app source function name") + (void)HDva_arg(ap, char *); /* Toss the 'app_line' parameter name */ + ev->app_line = HDva_arg(ap, unsigned); + + /* Set the event's operation counter */ + ev->ev_count = es->op_counter++; + + /* Set the event's timestamp */ + ev->ev_time = H5_now_usec(); + + /* Copy the API routine's name */ + if (NULL == (ev->api_name = H5MM_strdup(caller))) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, FAIL, "can't copy API routine name") + + /* Create the string for the API routine's arguments */ + if (NULL == (rs = H5RS_create(NULL))) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, FAIL, "can't allocate ref-counted string") + + /* Copy the string for the API routine's arguments */ + /* (skip the six characters from the app's file, function and line # arguments) */ + HDassert(0 == HDstrncmp(caller_args, "*s*sIu", 6)); + if (H5_trace_args(rs, caller_args + 6, ap) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTSET, FAIL, "can't create formatted API arguments") + if (NULL == (s = H5RS_get_str(rs))) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTGET, FAIL, "can't get pointer to formatted API arguments") + if (NULL == (ev->api_args = H5MM_strdup(s))) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, FAIL, "can't copy API routine arguments") + + /* Append fully initialized event onto the event set's 'active' list */ + H5ES__list_append(&es->active, ev); + +done: + /* Clean up */ + if (arg_started) + HDva_end(ap); + if (rs) + H5RS_decr(rs); + + /* Release resources on error */ + if (ret_value < 0) + if (ev && H5ES__event_free(ev) < 0) + HDONE_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, FAIL, "unable to release event") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES_insert() */ + +/*------------------------------------------------------------------------- + * Function: H5ES__handle_fail + * + * Purpose: Handle a failed event + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Thursday, October 15, 2020 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5ES__handle_fail(H5ES_t *es, H5ES_event_t *ev) +{ + FUNC_ENTER_STATIC_NOERR + + /* Sanity check */ + HDassert(es); + HDassert(es->active.head); + HDassert(ev); + + /* Set error flag for event set */ + es->err_occurred = TRUE; + + /* Remove event from normal list */ + H5ES__list_remove(&es->active, ev); + + /* Append event onto the event set's error list */ + H5ES__list_append(&es->failed, ev); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5ES__handle_fail() */ + +/*------------------------------------------------------------------------- + * Function: H5ES__wait_cb + * + * Purpose: Common routine for testing / waiting on an operation + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Sunday, November 7, 2020 + * + *------------------------------------------------------------------------- + */ +static int +H5ES__wait_cb(H5ES_event_t *ev, void *_ctx) +{ + H5ES_wait_ctx_t * ctx = (H5ES_wait_ctx_t *)_ctx; /* Callback context */ + H5VL_request_status_t ev_status = H5VL_REQUEST_STATUS_SUCCEED; /* Status from event's operation */ + uint64_t start_time = 0, elapsed_time = 0; /* Start and elapsed times for waiting on an operation */ + int ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity check */ + HDassert(ev); + HDassert(ctx); + + /* Wait on the request */ + if (ctx->timeout != H5ES_WAIT_NONE && ctx->timeout != H5ES_WAIT_FOREVER) + start_time = H5_now_usec(); + if (H5VL_request_wait(ev->request, ctx->timeout, &ev_status) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTWAIT, H5_ITER_ERROR, "unable to test operation") + if (ctx->timeout != H5ES_WAIT_NONE && ctx->timeout != H5ES_WAIT_FOREVER) + elapsed_time = H5_now_usec() - start_time; + + /* Check for status values that indicate we should break out of the loop */ + if (ev_status == H5VL_REQUEST_STATUS_FAIL) { + /* Handle failure */ + if (H5ES__handle_fail(ctx->es, ev) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTSET, H5_ITER_ERROR, "unable to handle failed event") + + /* Record the error */ + *ctx->op_failed = TRUE; + + /* Exit from the iteration */ + ret_value = H5_ITER_STOP; + } /* end if */ + else if (ev_status == H5VL_REQUEST_STATUS_SUCCEED) { + if (H5ES__event_completed(ev, &ctx->es->active) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, H5_ITER_ERROR, "unable to release completed event") + } /* end else-if */ + else if (ev_status == H5VL_REQUEST_STATUS_CANCELED) + /* Should never get a status of 'cancel' back from test / wait operation */ + HGOTO_ERROR(H5E_EVENTSET, H5E_BADVALUE, H5_ITER_ERROR, "received 'cancel' status for operation") + else { + /* Sanity check */ + HDassert(ev_status == H5VL_REQUEST_STATUS_IN_PROGRESS); + + /* Increment "in progress operation" counter */ + (*ctx->num_in_progress)++; + } /* end if */ + + /* Check for updateable timeout */ + if (ctx->timeout != H5ES_WAIT_NONE && ctx->timeout != H5ES_WAIT_FOREVER) { + /* Update timeout for next operation */ + if ((elapsed_time * 1000) > ctx->timeout) + ctx->timeout = H5ES_WAIT_NONE; + else + ctx->timeout -= (elapsed_time * 1000); /* Convert us to ns */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES__wait_cb() */ + +/*------------------------------------------------------------------------- + * Function: H5ES__wait + * + * Purpose: Wait for operations in event set to complete + * + * Note: Timeout value is in ns, and is for H5ES__wait itself. + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Monday, July 13, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ES__wait(H5ES_t *es, uint64_t timeout, size_t *num_in_progress, hbool_t *op_failed) +{ + H5ES_wait_ctx_t ctx; /* Iterator callback context info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Sanity check */ + HDassert(es); + HDassert(num_in_progress); + HDassert(op_failed); + + /* Set user's parameters to known values */ + *num_in_progress = 0; + *op_failed = FALSE; + + /* Set up context for iterator callbacks */ + ctx.es = es; + ctx.timeout = timeout; + ctx.num_in_progress = num_in_progress; + ctx.op_failed = op_failed; + + /* Iterate over the events in the set, waiting for them to complete */ + if (H5ES__list_iterate(&es->active, H5ES__wait_cb, &ctx) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_BADITER, FAIL, "iteration failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES__wait() */ + +/*------------------------------------------------------------------------- + * Function: H5ES__get_err_info_cb + * + * Purpose: Retrieve information about a failed operation + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Monday, November 11, 2020 + * + *------------------------------------------------------------------------- + */ +static int +H5ES__get_err_info_cb(H5ES_event_t *ev, void *_ctx) +{ + H5ES_gei_ctx_t *ctx = (H5ES_gei_ctx_t *)_ctx; /* Callback context */ + int ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity check */ + HDassert(ev); + HDassert(ctx); + + /* Copy operation info for event */ + if (NULL == (ctx->curr_err_info->api_name = H5MM_strdup(ev->api_name))) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, H5_ITER_ERROR, "can't copy HDF5 API name") + if (NULL == (ctx->curr_err_info->api_args = H5MM_strdup(ev->api_args))) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, H5_ITER_ERROR, "can't copy HDF5 API routine arguments") + if (NULL == (ctx->curr_err_info->app_file_name = H5MM_strdup(ev->app_file))) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, H5_ITER_ERROR, "can't copy app source file name") + if (NULL == (ctx->curr_err_info->app_func_name = H5MM_strdup(ev->app_func))) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, H5_ITER_ERROR, "can't copy app function name") + ctx->curr_err_info->app_line_num = ev->app_line; + ctx->curr_err_info->op_ins_count = ev->ev_count; + ctx->curr_err_info->op_ins_ts = ev->ev_time; + + /* Get error stack for event */ + if (H5VL_request_specific(ev->request, H5VL_REQUEST_GET_ERR_STACK, &ctx->curr_err_info->err_stack_id) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTGET, H5_ITER_ERROR, "unable to retrieve error stack for operation") + + /* Remove event from event set's failed list */ + H5ES__list_remove(&ctx->es->failed, ev); + + /* Free event node */ + if (H5ES__event_free(ev) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, H5_ITER_ERROR, "unable to release failed event") + + /* Advance to next element of err_info[] array */ + ctx->curr_err++; + ctx->curr_err_info++; + + /* Stop iteration if err_info[] array is full */ + if (ctx->curr_err == ctx->num_err_info) + ret_value = H5_ITER_STOP; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES__get_err_info_cb() */ + +/*------------------------------------------------------------------------- + * Function: H5ES__get_err_info + * + * Purpose: Retrieve information about failed operations + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Friday, November 6, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ES__get_err_info(H5ES_t *es, size_t num_err_info, H5ES_err_info_t err_info[], size_t *num_cleared) +{ + H5ES_gei_ctx_t ctx; /* Iterator callback context info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Sanity check */ + HDassert(es); + HDassert(num_err_info); + HDassert(err_info); + HDassert(num_cleared); + + /* Set up context for iterator callbacks */ + ctx.es = es; + ctx.num_err_info = num_err_info; + ctx.curr_err = 0; + ctx.curr_err_info = &err_info[0]; + + /* Iterate over the failed events in the set, copying their error info */ + if (H5ES__list_iterate(&es->failed, H5ES__get_err_info_cb, &ctx) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_BADITER, FAIL, "iteration failed") + + /* Set # of failed events cleared from event set's failed list */ + *num_cleared = ctx.curr_err; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES__get_err_info() */ + +/*------------------------------------------------------------------------- + * Function: H5ES__close_failed_cb + * + * Purpose: Release a failed event + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Monday, November 11, 2020 + * + *------------------------------------------------------------------------- + */ +static int +H5ES__close_failed_cb(H5ES_event_t *ev, void *_ctx) +{ + H5ES_t *es = (H5ES_t *)_ctx; /* Callback context */ + int ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Sanity check */ + HDassert(ev); + HDassert(es); + + /* Remove event from event set's failed list */ + H5ES__list_remove(&es->failed, ev); + + /* Free event node */ + if (H5ES__event_free(ev) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, H5_ITER_ERROR, "unable to release failed event") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES__close_failed_cb() */ + +/*------------------------------------------------------------------------- + * Function: H5ES__close + * + * Purpose: Destroy an event set object + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Monday, April 6, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ES__close(H5ES_t *es) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Sanity check */ + HDassert(es); + + /* Fail if active operations still present */ + if (H5ES__list_count(&es->active) > 0) + HGOTO_ERROR( + H5E_EVENTSET, H5E_CANTCLOSEOBJ, FAIL, + "can't close event set while unfinished operations are present (i.e. wait on event set first)") + + /* Iterate over the failed events in the set, releasing them */ + if (H5ES__list_iterate(&es->failed, H5ES__close_failed_cb, (void *)es) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_BADITER, FAIL, "iteration failed") + + /* Release the event set */ + es = H5FL_FREE(H5ES_t, es); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES__close() */ diff --git a/src/H5ESlist.c b/src/H5ESlist.c new file mode 100644 index 0000000..231820c --- /dev/null +++ b/src/H5ESlist.c @@ -0,0 +1,215 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5ESlist.c + * Nov 7 2020 + * Quincey Koziol + * + * Purpose: Operations on "event lists" for managing asynchronous + * operations. + * + * Please see the asynchronous I/O RFC document + * for a full description of how they work, etc. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#include "H5ESmodule.h" /* This source code file is part of the H5ES module */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5ESpkg.h" /* Event Sets */ +#include "H5FLprivate.h" /* Free Lists */ + +/****************/ +/* Local Macros */ +/****************/ + +/******************/ +/* Local Typedefs */ +/******************/ + +/********************/ +/* Package Typedefs */ +/********************/ + +/********************/ +/* Local Prototypes */ +/********************/ + +/*********************/ +/* Package Variables */ +/*********************/ + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/*******************/ +/* Local Variables */ +/*******************/ + +/*------------------------------------------------------------------------- + * Function: H5ES__list_insert + * + * Purpose: Append an event into an event list + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Saturday, November 7, 2020 + * + *------------------------------------------------------------------------- + */ +void +H5ES__list_append(H5ES_event_list_t *el, H5ES_event_t *ev) +{ + FUNC_ENTER_PACKAGE_NOERR + + /* Sanity check */ + HDassert(el); + HDassert(ev); + + /* Append event onto the event list */ + if (NULL == el->tail) + el->head = el->tail = ev; + else { + ev->prev = el->tail; + el->tail->next = ev; + el->tail = ev; + } /* end else */ + + /* Increment the # of events in list */ + el->count++; + + FUNC_LEAVE_NOAPI_VOID +} /* end H5ES__list_append() */ + +/*------------------------------------------------------------------------- + * Function: H5ES__list_count + * + * Purpose: Retrieve # of events in an event list + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Saturday, November 7, 2020 + * + *------------------------------------------------------------------------- + */ +H5_ATTR_PURE size_t +H5ES__list_count(const H5ES_event_list_t *el) +{ + FUNC_ENTER_PACKAGE_NOERR + + /* Sanity check */ + HDassert(el); + + FUNC_LEAVE_NOAPI(el->count) +} /* end H5ES__list_count() */ + +/*------------------------------------------------------------------------- + * Function: H5ES__list_iterate + * + * Purpose: Iterate over events in a list, calling callback for + * each event. + * + * Note: Iteration is safe for deleting the current event. Modifying + * the list in other ways is likely unsafe. + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Saturday, November 7, 2020 + * + *------------------------------------------------------------------------- + */ +int +H5ES__list_iterate(H5ES_event_list_t *el, H5ES_list_iter_func_t cb, void *ctx) +{ + H5ES_event_t *ev; /* Event in list */ + int ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_PACKAGE_NOERR + + /* Sanity check */ + HDassert(el); + HDassert(cb); + + /* Iterate over events in list */ + ev = el->head; + while (ev) { + H5ES_event_t *tmp; /* Temporary event */ + + /* Get pointer to next node, so it's safe if this one is removed */ + tmp = ev->next; + + /* Perform iterator callback */ + if ((ret_value = (*cb)(ev, ctx)) != H5_ITER_CONT) { + if (ret_value < 0) + HERROR(H5E_EVENTSET, H5E_CANTNEXT, "iteration operator failed"); + break; + } /* end if */ + + /* Advance to next node */ + ev = tmp; + } /* end while */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES__list_iterate() */ + +/*------------------------------------------------------------------------- + * Function: H5ES__list_remove + * + * Purpose: Remove an event from an event list + * + * Return: SUCCEED / FAIL + * + * Programmer: Houjun Tang + * Thursday, July 30, 2020 + * + *------------------------------------------------------------------------- + */ +void +H5ES__list_remove(H5ES_event_list_t *el, const H5ES_event_t *ev) +{ + FUNC_ENTER_PACKAGE_NOERR + + /* Sanity check */ + HDassert(el); + HDassert(el->head); + HDassert(ev); + + /* Stitch event out of list */ + if (ev == el->head) + el->head = ev->next; + if (NULL != ev->next) + ev->next->prev = ev->prev; + if (NULL != ev->prev) + ev->prev->next = ev->next; + if (NULL == el->head) + el->tail = NULL; + + /* Decrement the # of events in list */ + el->count--; + + FUNC_LEAVE_NOAPI_VOID +} /* end H5ES__list_remove() */ diff --git a/src/H5ESmodule.h b/src/H5ESmodule.h new file mode 100644 index 0000000..716b96c --- /dev/null +++ b/src/H5ESmodule.h @@ -0,0 +1,32 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Quincey Koziol + * Monday, April 6, 2020 + * + * Purpose: This file contains declarations which define macros for the + * H5ES package. Including this header means that the source file + * is part of the H5ES package. + */ +#ifndef _H5ESmodule_H +#define _H5ESmodule_H + +/* Define the proper control macros for the generic FUNC_ENTER/LEAVE and error + * reporting macros. + */ +#define H5ES_MODULE +#define H5_MY_PKG H5ES +#define H5_MY_PKG_ERR H5E_EVENTSET +#define H5_MY_PKG_INIT YES + +#endif /* _H5ESmodule_H */ diff --git a/src/H5ESpkg.h b/src/H5ESpkg.h new file mode 100644 index 0000000..e4a46cb --- /dev/null +++ b/src/H5ESpkg.h @@ -0,0 +1,101 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Quincey Koziol + * Wednesday, April 8, 2020 + * + * Purpose: This file contains declarations which are visible only within + * the H5ES package. Source files outside the H5ES package should + * include H5ESprivate.h instead. + */ +#if !(defined H5ES_FRIEND || defined H5ES_MODULE) +#error "Do not include this file outside the H5ES package!" +#endif + +#ifndef _H5ESpkg_H +#define _H5ESpkg_H + +/* Get package's private header */ +#include "H5ESprivate.h" + +/* Other private headers needed by this file */ + +/**************************/ +/* Package Private Macros */ +/**************************/ + +/****************************/ +/* Package Private Typedefs */ +/****************************/ + +/* Typedef for event nodes */ +typedef struct H5ES_event_t { + H5VL_object_t * request; /* Request token for event */ + struct H5ES_event_t *prev, *next; /* Previous and next event nodes */ + + /* Useful info for debugging and error reporting */ + const char *api_name; /* Name of API routine for event */ + const char *api_args; /* Arguments to API routine */ + const char *app_file; /* Name of source file from application */ + const char *app_func; /* Name of source function from application */ + unsigned app_line; /* Line # of source file from application */ + uint64_t ev_count; /* This event is the n'th operation in the event set */ + uint64_t ev_time; /* Timestamp for this event (in ms from UNIX epoch) */ +} H5ES_event_t; + +/* Typedef for lists of event set operations */ +typedef struct H5ES_event_list_t { + size_t count; /* # of events in list */ + H5ES_event_t *head, *tail; /* Head & tail of events in list */ +} H5ES_event_list_t; + +/* Typedef for event set objects */ +struct H5ES_t { + uint64_t op_counter; /* Count of operations inserted into this set */ + + /* Active events */ + H5ES_event_list_t active; /* List of active events in set */ + + /* Failed events */ + hbool_t err_occurred; /* Flag for error from an operation */ + H5ES_event_list_t failed; /* List of failed events in set */ +}; + +/* Event list iterator callback function */ +typedef int (*H5ES_list_iter_func_t)(H5ES_event_t *ev, void *ctx); + +/*****************************/ +/* Package Private Variables */ +/*****************************/ + +/******************************/ +/* Package Private Prototypes */ +/******************************/ +H5_DLL H5ES_t *H5ES__create(void); +H5_DLL herr_t H5ES__wait(H5ES_t *es, uint64_t timeout, size_t *num_in_progress, hbool_t *op_failed); +H5_DLL herr_t H5ES__get_err_info(H5ES_t *es, size_t num_err_info, H5ES_err_info_t err_info[], + size_t *num_cleared); +H5_DLL herr_t H5ES__close(H5ES_t *es); + +/* Event list operations */ +H5_DLL void H5ES__list_append(H5ES_event_list_t *el, H5ES_event_t *ev); +H5_DLL size_t H5ES__list_count(const H5ES_event_list_t *el); +H5_DLL int H5ES__list_iterate(H5ES_event_list_t *el, H5ES_list_iter_func_t cb, void *ctx); +H5_DLL void H5ES__list_remove(H5ES_event_list_t *el, const H5ES_event_t *ev); + +/* Event operations */ +H5_DLL H5ES_event_t *H5ES__event_new(H5VL_t *connector, void *token); +H5_DLL herr_t H5ES__event_free(H5ES_event_t *ev); +H5_DLL herr_t H5ES__event_completed(H5ES_event_t *ev, H5ES_event_list_t *el); + +#endif /* _H5ESpkg_H */ diff --git a/src/H5ESprivate.h b/src/H5ESprivate.h new file mode 100644 index 0000000..87765c0 --- /dev/null +++ b/src/H5ESprivate.h @@ -0,0 +1,54 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5ESprivate.h + * Apr 6 2020 + * Quincey Koziol + * + * Purpose: Private header for library accessible event set routines. + * + *------------------------------------------------------------------------- + */ + +#ifndef _H5ESprivate_H +#define _H5ESprivate_H + +/* Include package's public header */ +#include "H5ESpublic.h" /* Event Sets */ + +/* Private headers needed by this file */ +#include "H5VLprivate.h" /* Virtual Object Layer */ + +/**************************/ +/* Library Private Macros */ +/**************************/ + +/****************************/ +/* Library Private Typedefs */ +/****************************/ + +/* Typedef for event set objects */ +typedef struct H5ES_t H5ES_t; + +/*****************************/ +/* Library-private Variables */ +/*****************************/ + +/***************************************/ +/* Library-private Function Prototypes */ +/***************************************/ +herr_t H5ES_insert(hid_t es_id, H5VL_t *connector, void *token, const char *caller, const char *caller_args, + ...); + +#endif /* _H5ESprivate_H */ diff --git a/src/H5ESpublic.h b/src/H5ESpublic.h index dad929e..2884198 100644 --- a/src/H5ESpublic.h +++ b/src/H5ESpublic.h @@ -24,18 +24,89 @@ /* Public Macros */ /*****************/ +/* Default value for "no event set" / synchronous execution */ +#define H5ES_NONE (hid_t)0 + +/* Special "wait" timeout values */ +#define H5ES_WAIT_FOREVER (UINT64_MAX) /* Wait until all operations complete */ +#define H5ES_WAIT_NONE \ + (0) /* Don't wait for operations to complete, \ + * just check their status. \ + * (this allows H5ESwait to behave \ + * like a 'test' operation) \ + */ + /*******************/ /* Public Typedefs */ /*******************/ /* Asynchronous operation status */ typedef enum H5ES_status_t { - H5ES_STATUS_IN_PROGRESS, /* Operation has not yet completed */ - H5ES_STATUS_SUCCEED, /* Operation has completed, successfully */ - H5ES_STATUS_FAIL, /* Operation has completed, but failed */ - H5ES_STATUS_CANCELED /* Operation has not completed and was canceled */ + H5ES_STATUS_IN_PROGRESS, /* Operation(s) have not yet completed */ + H5ES_STATUS_SUCCEED, /* Operation(s) have completed, successfully */ + H5ES_STATUS_FAIL /* An operation has completed, but failed */ } H5ES_status_t; +/* Information about failed operations in event set */ +typedef struct H5ES_err_info_t { + /* Operation info */ + char * api_name; /* Name of HDF5 API routine called */ + char * api_args; /* "Argument string" for arguments to HDF5 API routine called */ + char * app_file_name; /* Name of source file where the HDF5 API routine was called */ + char * app_func_name; /* Name of function where the HDF5 API routine was called */ + unsigned app_line_num; /* Line # of source file where the HDF5 API routine was called */ + uint64_t op_ins_count; /* Counter of operation's insertion into event set */ + uint64_t op_ins_ts; /* Timestamp for when the operation was inserted into the event set */ + + /* Error info */ + hid_t err_stack_id; /* ID for error stack from failed operation */ +} H5ES_err_info_t; + +/* +H5ES_op_info_t: + const char *: API name (H5Dwrite_async, ...) + const char *: Arg string + const char *: Appl. source file name + const char *: Appl. source function + unsigned: Appl. source file line + uint64_t: Insert Time Timestamp + uint64_t: "event count" - n'th event inserted into event set + uint64_t: Execution Time timestamp (*) + +More Possible Info for H5ES_op_info_t: + Parent Operation's request token (*) -> "parent event count"? -- Could be + used to "prune" child operations from reported errors, with flag + to H5ESget_err_info? + +H5ES_err_info_t: + H5ES_op_info_t: (above) + hid_t: Error stack (*) + +Possible debugging routines: (Should also be configured from Env Var) + H5ESdebug_signal(hid_t es_id, signal_t sig, uint64_t <event count>); + H5ESdebug_err_trace_log(hid_t es_id, const char *filename); + H5ESdebug_err_trace_fh(hid_t es_id, FILE *fh); + H5ESdebug_err_signal(hid_t es_id, signal_t sig); +[Possibly option to allow operations to be inserted into event set with error?] + + Example usage: + es_id = H5EScreate(); + H5ESdebug...(es_id, ...); + ... + H5Dwrite_async(..., es_id); + +How to Trace Async Operations? + <Example of stacking Logging VOL Connector w/Async VOL Connector> + +"Library / wrapper developer" version of API routines: (Auto-generated) + H5Dwrite_async_wrap(const char *app_file, const char *app_func, + unsigned app_line_num, dset_id, mem_type_id, mem_space_id, ..., es_id); + + vs. + + H5Dwrite_async(dset_id, mem_type_id, mem_space_id, ..., es_id); +*/ + /********************/ /* Public Variables */ /********************/ @@ -48,6 +119,16 @@ typedef enum H5ES_status_t { extern "C" { #endif +H5_DLL hid_t H5EScreate(void); +H5_DLL herr_t H5ESwait(hid_t es_id, uint64_t timeout, size_t *num_in_progress, hbool_t *err_occurred); +H5_DLL herr_t H5ESget_count(hid_t es_id, size_t *count); +H5_DLL herr_t H5ESget_op_counter(hid_t es_id, uint64_t *counter); +H5_DLL herr_t H5ESget_err_status(hid_t es_id, hbool_t *err_occurred); +H5_DLL herr_t H5ESget_err_count(hid_t es_id, size_t *num_errs); +H5_DLL herr_t H5ESget_err_info(hid_t es_id, size_t num_err_info, H5ES_err_info_t err_info[], + size_t *err_cleared); +H5_DLL herr_t H5ESclose(hid_t es_id); + #ifdef __cplusplus } #endif diff --git a/src/H5Epublic.h b/src/H5Epublic.h index 8f9b473..2bb7996 100644 --- a/src/H5Epublic.h +++ b/src/H5Epublic.h @@ -159,6 +159,7 @@ H5_DLL herr_t H5Eclose_msg(hid_t err_id); H5_DLL hid_t H5Ecreate_msg(hid_t cls, H5E_type_t msg_type, const char *msg); H5_DLL hid_t H5Ecreate_stack(void); H5_DLL hid_t H5Eget_current_stack(void); +H5_DLL herr_t H5Eappend_stack(hid_t dst_stack_id, hid_t src_stack_id, hbool_t close_source_stack); H5_DLL herr_t H5Eclose_stack(hid_t stack_id); H5_DLL ssize_t H5Eget_class_name(hid_t class_id, char *name, size_t size); H5_DLL herr_t H5Eset_current_stack(hid_t err_stack_id); @@ -24,6 +24,7 @@ #include "H5ACprivate.h" /* Metadata cache */ #include "H5CXprivate.h" /* API Contexts */ #include "H5Eprivate.h" /* Error handling */ +#include "H5ESprivate.h" /* Event Sets */ #include "H5Fpkg.h" /* File access */ #include "H5FLprivate.h" /* Free lists */ #include "H5Iprivate.h" /* IDs */ @@ -67,6 +68,15 @@ static int H5F__get_all_count_cb(void H5_ATTR_UNUSED *obj_ptr, hid_t H5_ATTR_UNU /* Callback for getting IDs for open objects in a file */ static int H5F__get_all_ids_cb(void H5_ATTR_UNUSED *obj_ptr, hid_t obj_id, void *key); +/* Helper routines for sync/async API calls */ +static herr_t H5F__post_open_api_common(H5VL_object_t *vol_obj, void **token_ptr); +static hid_t H5F__create_api_common(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id, + void **token_ptr); +static hid_t H5F__open_api_common(const char *filename, unsigned flags, hid_t fapl_id, void **token_ptr); +static hid_t H5F__reopen_api_common(hid_t file_id, void **token_ptr); +static herr_t H5F__flush_api_common(hid_t object_id, H5F_scope_t scope, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); + /*********************/ /* Package Variables */ /*********************/ @@ -447,40 +457,53 @@ done: } /* end H5Fis_accessible() */ /*------------------------------------------------------------------------- - * Function: H5Fcreate + * Function: H5F__post_open_api_common * - * Purpose: This is the primary function for creating HDF5 files . The - * flags parameter determines whether an existing file will be - * overwritten or not. All newly created files are opened for - * both reading and writing. All flags may be combined with the - * bit-wise OR operator (`|') to change the behavior of the file - * create call. + * Purpose: This is the common function for 'post open' operations * - * The more complex behaviors of a file's creation and access - * are controlled through the file-creation and file-access - * property lists. The value of H5P_DEFAULT for a template - * value indicates that the library should use the default - * values for the appropriate template. + * Return: SUCCEED/FAIL * - * See also: H5Fpublic.h for the list of supported flags. H5Ppublic.h for - * the list of file creation and file access properties. + *------------------------------------------------------------------------- + */ +static herr_t +H5F__post_open_api_common(H5VL_object_t *vol_obj, void **token_ptr) +{ + uint64_t supported; /* Whether 'post open' operation is supported by VOL connector */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check for 'post open' callback */ + supported = 0; + if (H5VL_introspect_opt_query(vol_obj, H5VL_SUBCLS_FILE, H5VL_NATIVE_FILE_POST_OPEN, &supported) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't check for 'post open' operation") + if (supported & H5VL_OPT_QUERY_SUPPORTED) + /* Make the 'post open' callback */ + if (H5VL_file_optional(vol_obj, H5VL_NATIVE_FILE_POST_OPEN, H5P_DATASET_XFER_DEFAULT, token_ptr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to make file 'post open' callback") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F__post_open_api_common() */ + +/*------------------------------------------------------------------------- + * Function: H5F__create_api_common + * + * Purpose: This is the common function for creating new HDF5 files. * * Return: Success: A file ID * Failure: H5I_INVALID_HID *------------------------------------------------------------------------- */ -hid_t -H5Fcreate(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id) +static hid_t +H5F__create_api_common(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id, void **token_ptr) { void * new_file = NULL; /* File struct for new file */ - H5P_genplist_t * plist; /* Property list pointer */ - H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */ - H5VL_object_t * vol_obj = NULL; /* VOL object for file */ - uint64_t supported; /* Whether 'post open' operation is supported by VOL connector */ - hid_t ret_value; /* return value */ + H5P_genplist_t * plist; /* Property list pointer */ + H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ - FUNC_ENTER_API(H5I_INVALID_HID) - H5TRACE4("i", "*sIuii", filename, flags, fcpl_id, fapl_id); + FUNC_ENTER_STATIC /* Check/fix arguments */ if (!filename || !*filename) @@ -528,40 +551,71 @@ H5Fcreate(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id) /* Create a new file or truncate an existing file through the VOL */ if (NULL == (new_file = H5VL_file_create(&connector_prop, filename, flags, fcpl_id, fapl_id, - H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL))) + H5P_DATASET_XFER_DEFAULT, token_ptr))) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, H5I_INVALID_HID, "unable to create file") /* Get an ID for the file */ if ((ret_value = H5VL_register_using_vol_id(H5I_FILE, new_file, connector_prop.connector_id, TRUE)) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register file handle") +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F__create_api_common() */ + +/*------------------------------------------------------------------------- + * Function: H5Fcreate + * + * Purpose: This is the primary function for creating HDF5 files . The + * flags parameter determines whether an existing file will be + * overwritten or not. All newly created files are opened for + * both reading and writing. All flags may be combined with the + * bit-wise OR operator (`|') to change the behavior of the file + * create call. + * + * The more complex behaviors of a file's creation and access + * are controlled through the file-creation and file-access + * property lists. The value of H5P_DEFAULT for a template + * value indicates that the library should use the default + * values for the appropriate template. + * + * See also: H5Fpublic.h for the list of supported flags. H5Ppublic.h for + * the list of file creation and file access properties. + * + * Return: Success: A file ID + * + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Fcreate(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id) +{ + H5VL_object_t *vol_obj = NULL; /* File object */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE4("i", "*sIuii", filename, flags, fcpl_id, fapl_id); + + /* Create the file synchronously */ + if ((ret_value = H5F__create_api_common(filename, flags, fcpl_id, fapl_id, NULL)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, H5I_INVALID_HID, "unable to synchronously create file") + /* Get the file object */ if (NULL == (vol_obj = H5VL_vol_object(ret_value))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid object identifier") + HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, H5I_INVALID_HID, "invalid object identifier") - /* Make the 'post open' callback */ - supported = 0; - if (H5VL_introspect_opt_query(vol_obj, H5VL_SUBCLS_FILE, H5VL_NATIVE_FILE_POST_OPEN, &supported) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't check for 'post open' operation") - if (supported & H5VL_OPT_QUERY_SUPPORTED) - if (H5VL_file_optional(vol_obj, H5VL_NATIVE_FILE_POST_OPEN, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, H5I_INVALID_HID, "unable to make file 'post open' callback") + /* Perform 'post open' operation */ + if (H5F__post_open_api_common(vol_obj, NULL) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, H5I_INVALID_HID, "'post open' operation failed") done: FUNC_LEAVE_API(ret_value) } /* end H5Fcreate() */ /*------------------------------------------------------------------------- - * Function: H5Fopen + * Function: H5Fcreate_async * - * Purpose: This is the primary function for accessing existing HDF5 - * files. The FLAGS argument determines whether writing to an - * existing file will be allowed or not. All flags may be - * combined with the bit-wise OR operator (`|') to change the - * behavior of the file open call. The more complex behaviors - * of a file's access are controlled through the file-access - * property list. + * Purpose: Asynchronous version of H5Fcreate * * See Also: H5Fpublic.h for a list of possible values for FLAGS. * @@ -570,17 +624,78 @@ done: *------------------------------------------------------------------------- */ hid_t -H5Fopen(const char *filename, unsigned flags, hid_t fapl_id) +H5Fcreate_async(const char *app_file, const char *app_func, unsigned app_line, const char *filename, + unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t es_id) { - void * new_file = NULL; /* File struct for new file */ - H5P_genplist_t * plist; /* Property list pointer */ - H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */ - H5VL_object_t * vol_obj = NULL; /* VOL object for file */ - uint64_t supported; /* Whether 'post open' operation is supported by VOL connector */ - hid_t ret_value; /* Return value */ + H5VL_object_t *vol_obj = NULL; /* File object */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ FUNC_ENTER_API(H5I_INVALID_HID) - H5TRACE3("i", "*sIui", filename, flags, fapl_id); + H5TRACE8("i", "*s*sIu*sIuiii", app_file, app_func, app_line, filename, flags, fcpl_id, fapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Create the file, possibly asynchronously */ + if ((ret_value = H5F__create_api_common(filename, flags, fcpl_id, fapl_id, token_ptr)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, H5I_INVALID_HID, "unable to asynchronously create file") + + /* Get the file object */ + if (NULL == (vol_obj = H5VL_vol_object(ret_value))) + HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, H5I_INVALID_HID, "invalid object identifier") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE8(FUNC, "*s*sIu*sIuiii", app_file, app_func, app_line, filename, flags, + fcpl_id, fapl_id, es_id)) < 0) { + if (H5I_dec_app_ref(ret_value) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTDEC, H5I_INVALID_HID, "can't decrement count on file ID") + HGOTO_ERROR(H5E_FILE, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ + + /* Reset token for 'post open' operation */ + /* (Unnecessary if create operation didn't change it, but not worth checking -QAK) */ + token = NULL; + + /* Perform 'post open' operation */ + if (H5F__post_open_api_common(vol_obj, token_ptr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, H5I_INVALID_HID, "'post open' operation failed") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE8(FUNC, "*s*sIu*sIuiii", app_file, app_func, app_line, filename, flags, + fcpl_id, fapl_id, es_id)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Fcreate_async() */ + +/*------------------------------------------------------------------------- + * Function: H5F__open_api_common + * + * Purpose: This is the common function for accessing existing HDF5 + * files. + * + * Return: Success: A file ID + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +static hid_t +H5F__open_api_common(const char *filename, unsigned flags, hid_t fapl_id, void **token_ptr) +{ + H5F_t * new_file = NULL; /* File struct for new file */ + H5P_genplist_t * plist; /* Property list pointer */ + H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_STATIC /* Check arguments */ if (!filename || !*filename) @@ -615,51 +730,146 @@ H5Fopen(const char *filename, unsigned flags, hid_t fapl_id) HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set VOL connector info in API context") /* Open the file through the VOL layer */ - if (NULL == (new_file = H5VL_file_open(&connector_prop, filename, flags, fapl_id, - H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL))) + if (NULL == (new_file = (H5F_t *)H5VL_file_open(&connector_prop, filename, flags, fapl_id, + H5P_DATASET_XFER_DEFAULT, token_ptr))) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, H5I_INVALID_HID, "unable to open file") /* Get an ID for the file */ if ((ret_value = H5VL_register_using_vol_id(H5I_FILE, new_file, connector_prop.connector_id, TRUE)) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register file handle") +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F__open_api_common() */ + +/*------------------------------------------------------------------------- + * Function: H5Fopen + * + * Purpose: This is the primary function for accessing existing HDF5 + * files. The FLAGS argument determines whether writing to an + * existing file will be allowed or not. All flags may be + * combined with the bit-wise OR operator (`|') to change the + * behavior of the file open call. The more complex behaviors + * of a file's access are controlled through the file-access + * property list. + * + * See Also: H5Fpublic.h for a list of possible values for FLAGS. + * + * Return: Success: A file ID + * + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Fopen(const char *filename, unsigned flags, hid_t fapl_id) +{ + H5VL_object_t *vol_obj = NULL; /* File object */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE3("i", "*sIui", filename, flags, fapl_id); + + /* Open the file synchronously */ + if ((ret_value = H5F__open_api_common(filename, flags, fapl_id, NULL)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, H5I_INVALID_HID, "unable to synchronously open file") + /* Get the file object */ if (NULL == (vol_obj = H5VL_vol_object(ret_value))) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "invalid object identifier") + HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, H5I_INVALID_HID, "invalid object identifier") - /* Make the 'post open' callback */ - supported = 0; - if (H5VL_introspect_opt_query(vol_obj, H5VL_SUBCLS_FILE, H5VL_NATIVE_FILE_POST_OPEN, &supported) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't check for 'post open' operation") - if (supported & H5VL_OPT_QUERY_SUPPORTED) - if (H5VL_file_optional(vol_obj, H5VL_NATIVE_FILE_POST_OPEN, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, H5I_INVALID_HID, "unable to make file 'post open' callback") + /* Perform 'post open' operation */ + if (H5F__post_open_api_common(vol_obj, NULL) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, H5I_INVALID_HID, "'post open' operation failed") done: FUNC_LEAVE_API(ret_value) } /* end H5Fopen() */ /*------------------------------------------------------------------------- - * Function: H5Fflush + * Function: H5Fopen_async * - * Purpose: Flushes all outstanding buffers of a file to disk but does - * not remove them from the cache. The OBJECT_ID can be a file, - * dataset, group, attribute, or named data type. + * Purpose: Asynchronous version of H5Fopen + * + * See Also: H5Fpublic.h for a list of possible values for FLAGS. + * + * Return: Success: A file ID + * Failure: H5I_INVALID_HID * - * Return: Success: Non-negative - * Failure: Negative *------------------------------------------------------------------------- */ -herr_t -H5Fflush(hid_t object_id, H5F_scope_t scope) +hid_t +H5Fopen_async(const char *app_file, const char *app_func, unsigned app_line, const char *filename, + unsigned flags, hid_t fapl_id, hid_t es_id) { - H5VL_object_t *vol_obj = NULL; /* Object info */ - H5I_type_t obj_type; /* Type of object */ - herr_t ret_value = SUCCEED; /* Return value */ + H5VL_object_t *vol_obj = NULL; /* File object */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ - FUNC_ENTER_API(FAIL) - H5TRACE2("e", "iFs", object_id, scope); + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE7("i", "*s*sIu*sIuii", app_file, app_func, app_line, filename, flags, fapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Open the file, possibly asynchronously */ + if ((ret_value = H5F__open_api_common(filename, flags, fapl_id, token_ptr)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, H5I_INVALID_HID, "unable to asynchronously open file") + + /* Get the file object */ + if (NULL == (vol_obj = H5VL_vol_object(ret_value))) + HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, H5I_INVALID_HID, "invalid object identifier") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE7(FUNC, "*s*sIu*sIuii", app_file, app_func, app_line, filename, flags, + fapl_id, es_id)) < 0) { + if (H5I_dec_app_ref(ret_value) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTDEC, H5I_INVALID_HID, "can't decrement count on file ID") + HGOTO_ERROR(H5E_FILE, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ + + /* Reset token for 'post open' operation */ + /* (Unnecessary if create operation didn't change it, but not worth checking -QAK) */ + token = NULL; + + /* Perform 'post open' operation */ + if (H5F__post_open_api_common(vol_obj, token_ptr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, H5I_INVALID_HID, "'post open' operation failed") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE7(FUNC, "*s*sIu*sIuii", app_file, app_func, app_line, filename, flags, + fapl_id, es_id)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Fopen_async() */ + +/*------------------------------------------------------------------------- + * Function: H5F__flush_api_common + * + * Purpose: This is the common function for flushing an HDF5 file. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F__flush_api_common(hid_t object_id, H5F_scope_t scope, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5I_type_t obj_type; /* Type of object to use */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC /* Get the type of object we're flushing + sanity check */ obj_type = H5I_get_type(object_id); @@ -668,19 +878,87 @@ H5Fflush(hid_t object_id, H5F_scope_t scope) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object") /* Get the file object */ - if (NULL == (vol_obj = H5VL_vol_object(object_id))) + if (NULL == (*vol_obj_ptr = H5VL_vol_object(object_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier") /* Flush the object */ - if (H5VL_file_specific(vol_obj, H5VL_FILE_FLUSH, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, (int)obj_type, + if (H5VL_file_specific(*vol_obj_ptr, H5VL_FILE_FLUSH, H5P_DATASET_XFER_DEFAULT, token_ptr, (int)obj_type, (int)scope) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush file") done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5F__flush_api_common() */ + +/*------------------------------------------------------------------------- + * Function: H5Fflush + * + * Purpose: Flushes all outstanding buffers of a file to disk but does + * not remove them from the cache. The OBJECT_ID can be a file, + * dataset, group, attribute, or named data type. + * + * Return: Success: Non-negative + * Failure: Negative + *------------------------------------------------------------------------- + */ +herr_t +H5Fflush(hid_t object_id, H5F_scope_t scope) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "iFs", object_id, scope); + + /* Flush the file synchronously */ + if (H5F__flush_api_common(object_id, scope, NULL, NULL) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to synchronously flush file") + +done: FUNC_LEAVE_API(ret_value) } /* end H5Fflush() */ /*------------------------------------------------------------------------- + * Function: H5Fflush_async + * + * Purpose: Asynchronous version of H5Fflush + * + * Return: Success: Non-negative + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5Fflush_async(const char *app_file, const char *app_func, unsigned app_line, hid_t object_id, + H5F_scope_t scope, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE6("e", "*s*sIuiFsi", app_file, app_func, app_line, object_id, scope, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Flush the file asynchronously */ + if (H5F__flush_api_common(object_id, scope, token_ptr, &vol_obj) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to asynchronously flush file") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert( + es_id, vol_obj->connector, token, + H5ARG_TRACE6(FUNC, "*s*sIuiFsi", app_file, app_func, app_line, object_id, scope, es_id)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Fflush_async() */ + +/*------------------------------------------------------------------------- * Function: H5Fclose * * Purpose: This function closes the file specified by FILE_ID by @@ -717,6 +995,65 @@ done: } /* end H5Fclose() */ /*------------------------------------------------------------------------- + * Function: H5Fclose_async + * + * Purpose: Asynchronous version of H5Fclose + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5Fclose_async(const char *app_file, const char *app_func, unsigned app_line, hid_t file_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + H5VL_t * connector = NULL; /* VOL connector */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "*s*sIuii", app_file, app_func, app_line, file_id, es_id); + + /* Check arguments */ + if (H5I_FILE != H5I_get_type(file_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file ID") + + /* Prepare for possible asynchronous operation */ + if (H5ES_NONE != es_id) { + /* Get file object's connector */ + if (NULL == (vol_obj = H5VL_vol_object(file_id))) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get VOL object for file") + + /* Increase connector's refcount, so it doesn't get closed if closing + * this file ID closes the file */ + connector = vol_obj->connector; + H5VL_conn_inc_rc(connector); + + /* Point at token for operation to set up */ + token_ptr = &token; + } /* end if */ + + /* Asynchronously decrement reference count on ID. + * When it reaches zero the file will be closed. + */ + if (H5I_dec_app_ref_async(file_id, token_ptr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "decrementing file ID failed") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE5(FUNC, "*s*sIuii", app_file, app_func, app_line, file_id, es_id)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + if (connector && H5VL_conn_dec_rc(connector) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "can't decrement ref count on connector") + + FUNC_LEAVE_API(ret_value) +} /* end H5Fclose_async() */ + +/*------------------------------------------------------------------------- * Function: H5Fdelete * * Purpose: Deletes an HDF5 file. @@ -888,37 +1225,31 @@ done: } /* end H5Funmount() */ /*------------------------------------------------------------------------- - * Function: H5Freopen - * - * Purpose: Reopen a file. The new file handle which is returned points - * to the same file as the specified file handle. Both handles - * share caches and other information. The only difference - * between the handles is that the new handle is not mounted - * anywhere and no files are mounted on it. + * Function: H5F__reopen_api_common * - * Return: Success: New file ID + * Purpose: This is the common function for reopening an HDF5 file + * files. * + * Return: Success: A file ID * Failure: H5I_INVALID_HID * *------------------------------------------------------------------------- */ -hid_t -H5Freopen(hid_t file_id) +static hid_t +H5F__reopen_api_common(hid_t file_id, void **token_ptr) { - void * file = NULL; /* File struct for new file */ - H5VL_object_t *vol_obj = NULL; /* VOL object for file */ - uint64_t supported; /* Whether 'post open' operation is supported by VOL connector */ + void * file = NULL; /* File struct for new file */ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ hid_t ret_value = H5I_INVALID_HID; /* Return value */ - FUNC_ENTER_API(H5I_INVALID_HID) - H5TRACE1("i", "i", file_id); + FUNC_ENTER_STATIC /* Get the file object */ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid file identifier") /* Reopen the file */ - if (H5VL_file_specific(vol_obj, H5VL_FILE_REOPEN, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &file) < 0) + if (H5VL_file_specific(vol_obj, H5VL_FILE_REOPEN, H5P_DATASET_XFER_DEFAULT, token_ptr, &file) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, H5I_INVALID_HID, "unable to reopen file via the VOL connector") /* Make sure that worked */ @@ -929,24 +1260,114 @@ H5Freopen(hid_t file_id) if ((ret_value = H5VL_register(H5I_FILE, file, vol_obj->connector, TRUE)) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register file handle") +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F__reopen_api_common() */ + +/*------------------------------------------------------------------------- + * Function: H5Freopen + * + * Purpose: Reopen a file. The new file handle which is returned points + * to the same file as the specified file handle. Both handles + * share caches and other information. The only difference + * between the handles is that the new handle is not mounted + * anywhere and no files are mounted on it. + * + * Return: Success: New file ID + * + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Freopen(hid_t file_id) +{ + H5VL_object_t *vol_obj = NULL; /* File object */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE1("i", "i", file_id); + + /* Reopen the file synchronously */ + if ((ret_value = H5F__reopen_api_common(file_id, NULL)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, H5I_INVALID_HID, "unable to synchronously reopen file") + /* Get the file object */ if (NULL == (vol_obj = H5VL_vol_object(ret_value))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid object identifier") + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't get handle for re-opened file") - /* Make the 'post open' callback */ - supported = 0; - if (H5VL_introspect_opt_query(vol_obj, H5VL_SUBCLS_FILE, H5VL_NATIVE_FILE_POST_OPEN, &supported) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't check for 'post open' operation") - if (supported & H5VL_OPT_QUERY_SUPPORTED) - if (H5VL_file_optional(vol_obj, H5VL_NATIVE_FILE_POST_OPEN, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, H5I_INVALID_HID, "unable to make file 'post open' callback") + /* Perform 'post open' operation */ + if (H5F__post_open_api_common(vol_obj, NULL) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, H5I_INVALID_HID, "'post open' operation failed") done: + /* XXX (VOL MERGE): If registration fails, file will not be closed */ FUNC_LEAVE_API(ret_value) } /* end H5Freopen() */ /*------------------------------------------------------------------------- + * Function: H5Freopen_async + * + * Purpose: Asynchronous version of H5Freopen + * + * See Also: H5Fpublic.h for a list of possible values for FLAGS. + * + * Return: Success: A file ID + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Freopen_async(const char *app_file, const char *app_func, unsigned app_line, hid_t file_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE5("i", "*s*sIuii", app_file, app_func, app_line, file_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Reopen the file, possibly asynchronously */ + if ((ret_value = H5F__reopen_api_common(file_id, token_ptr)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, H5I_INVALID_HID, "unable to asynchronously reopen file") + + /* Get the file object */ + if (NULL == (vol_obj = H5VL_vol_object(ret_value))) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't get handle for re-opened file") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE5(FUNC, "*s*sIuii", app_file, app_func, app_line, file_id, es_id)) < 0) { + if (H5I_dec_app_ref(ret_value) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTDEC, H5I_INVALID_HID, "can't decrement count on file ID") + HGOTO_ERROR(H5E_FILE, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ + + /* Reset token for 'post open' operation */ + /* (Unnecessary if create operation didn't change it, but not worth checking -QAK) */ + token = NULL; + + /* Perform 'post open' operation */ + if (H5F__post_open_api_common(vol_obj, token_ptr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, H5I_INVALID_HID, "'post open' operation failed") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE5(FUNC, "*s*sIuii", app_file, app_func, app_line, file_id, es_id)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Freopen_async() */ + +/*------------------------------------------------------------------------- * Function: H5Fget_intent * * Purpose: Public API to retrieve the file's 'intent' flags passed @@ -1990,3 +2411,40 @@ H5Fset_dset_no_attrs_hint(hid_t file_id, hbool_t minimize) done: FUNC_LEAVE_API(ret_value) } /* H5Fset_dset_no_attrs_hint */ + +/*------------------------------------------------------------------------- + * Function: H5Fwait + * + * Purpose: Wait for all operations on a dataset. + * Tang: added for async + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5Fwait(hid_t file_id) +{ + H5VL_object_t *vol_obj; /* File for this operation */ + H5I_type_t obj_type; /* Type of object */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE1("e", "i", file_id); + + /* Get the type of object we're flushing + sanity check */ + obj_type = H5I_get_type(file_id); + if (H5I_FILE != obj_type && H5I_GROUP != obj_type && H5I_DATATYPE != obj_type && + H5I_DATASET != obj_type && H5I_ATTR != obj_type) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object") + + if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "file_id parameter is not a valid file identifier") + + if ((ret_value = H5VL_file_specific(vol_obj, H5VL_FILE_WAIT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, + file_id)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPERATE, FAIL, "unable to wait file") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Fwait() */ diff --git a/src/H5FAtest.c b/src/H5FAtest.c index 350530a..de9e6d7 100644 --- a/src/H5FAtest.c +++ b/src/H5FAtest.c @@ -200,7 +200,7 @@ BEGIN_FUNC(STATIC, NOERR, herr_t, SUCCEED, -, #ifndef NDEBUG H5FA__test_ctx_t *ctx = (H5FA__test_ctx_t *)_ctx; /* Callback context to destroy */ #endif /* NDEBUG */ - const uint64_t *elmt = (const uint64_t *)_elmt; /* Convenience pointer to native elements */ + const uint64_t *elmt = (const uint64_t *)_elmt; /* Convenience pointer to native elements */ /* Sanity checks */ HDassert(raw); @@ -241,9 +241,9 @@ BEGIN_FUNC(STATIC, NOERR, herr_t, SUCCEED, -, /* Local variables */ #ifndef NDEBUG H5FA__test_ctx_t *ctx = (H5FA__test_ctx_t *)_ctx; /* Callback context to destroy */ -#endif /* NDEBUG */ - uint64_t * elmt = (uint64_t *)_elmt; /* Convenience pointer to native elements */ - const uint8_t *raw = (const uint8_t *)_raw; /* Convenience pointer to raw elements */ +#endif /* NDEBUG */ + uint64_t * elmt = (uint64_t *)_elmt; /* Convenience pointer to native elements */ + const uint8_t *raw = (const uint8_t *)_raw; /* Convenience pointer to raw elements */ /* Sanity checks */ HDassert(raw); diff --git a/src/H5FScache.c b/src/H5FScache.c index fc61edd..3f8ce2b 100644 --- a/src/H5FScache.c +++ b/src/H5FScache.c @@ -1004,10 +1004,11 @@ H5FS__cache_sinfo_deserialize(const void *_image, size_t H5_ATTR_NDEBUG_UNUSED l /* Check for any serialized sections */ if (fspace->serial_sect_count > 0) { hsize_t old_tot_sect_count; /* Total section count from header */ - hsize_t H5_ATTR_NDEBUG_UNUSED old_serial_sect_count; /* Total serializable section count from header */ - hsize_t H5_ATTR_NDEBUG_UNUSED old_ghost_sect_count; /* Total ghost section count from header */ - hsize_t H5_ATTR_NDEBUG_UNUSED old_tot_space; /* Total space managed from header */ - unsigned sect_cnt_size; /* The size of the section size counts */ + hsize_t H5_ATTR_NDEBUG_UNUSED + old_serial_sect_count; /* Total serializable section count from header */ + hsize_t H5_ATTR_NDEBUG_UNUSED old_ghost_sect_count; /* Total ghost section count from header */ + hsize_t H5_ATTR_NDEBUG_UNUSED old_tot_space; /* Total space managed from header */ + unsigned sect_cnt_size; /* The size of the section size counts */ /* Compute the size of the section counts */ sect_cnt_size = H5VM_limit_enc_size((uint64_t)fspace->serial_sect_count); diff --git a/src/H5Fint.c b/src/H5Fint.c index 92b70ce..6ea2841 100644 --- a/src/H5Fint.c +++ b/src/H5Fint.c @@ -695,6 +695,7 @@ H5F__get_objects_cb(void *obj_ptr, hid_t obj_id, void *key) 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, H5_ITER_ERROR, "unknown or invalid data object") @@ -2621,8 +2622,8 @@ H5F__build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl, const char *n hid_t new_fapl_id = H5I_INVALID_HID; /* ID for duplicated FAPL */ #ifdef H5_HAVE_SYMLINK /* This has to be declared here to avoid unfreed resources on errors */ - char *realname = NULL; /* Fully resolved path name of file */ -#endif /* H5_HAVE_SYMLINK */ + char *realname = NULL; /* Fully resolved path name of file */ +#endif /* H5_HAVE_SYMLINK */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index f4268e5..7445d36 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -30,7 +30,7 @@ typedef struct H5F_t H5F_t; /* Private headers needed by this file */ #include "H5MMprivate.h" /* Memory management */ #ifdef H5_HAVE_PARALLEL -#include "H5Pprivate.h" /* Property lists */ +#include "H5Pprivate.h" /* Property lists */ #endif /* H5_HAVE_PARALLEL */ #include "H5VMprivate.h" /* Vectors and arrays */ #include "H5VLprivate.h" /* Virtual Object Layer */ @@ -532,33 +532,33 @@ typedef struct H5F_t H5F_t; #define H5F_DEFAULT_CSET H5T_CSET_ASCII /* ========= File Creation properties ============ */ -#define H5F_CRT_USER_BLOCK_NAME "block_size" /* Size of the file user block in bytes */ +#define H5F_CRT_USER_BLOCK_NAME "block_size" /* Size of the file user block in bytes */ #define H5F_CRT_SYM_LEAF_NAME "symbol_leaf" /* 1/2 rank for symbol table leaf nodes */ #define H5F_CRT_SYM_LEAF_DEF 4 -#define H5F_CRT_BTREE_RANK_NAME "btree_rank" /* 1/2 rank for btree internal nodes */ +#define H5F_CRT_BTREE_RANK_NAME "btree_rank" /* 1/2 rank for btree internal nodes */ #define H5F_CRT_ADDR_BYTE_NUM_NAME "addr_byte_num" /* Byte number in an address */ -#define H5F_CRT_OBJ_BYTE_NUM_NAME "obj_byte_num" /* Byte number for object size */ +#define H5F_CRT_OBJ_BYTE_NUM_NAME "obj_byte_num" /* Byte number for object size */ #define H5F_CRT_SUPER_VERS_NAME "super_version" /* Version number of the superblock */ /* Number of shared object header message indexes */ #define H5F_CRT_SHMSG_NINDEXES_NAME "num_shmsg_indexes" #define H5F_CRT_SHMSG_INDEX_TYPES_NAME "shmsg_message_types" /* Types of message in each index */ /* Minimum size of messages in each index */ #define H5F_CRT_SHMSG_INDEX_MINSIZE_NAME "shmsg_message_minsize" -#define H5F_CRT_SHMSG_LIST_MAX_NAME "shmsg_list_max" /* Shared message list maximum size */ -#define H5F_CRT_SHMSG_BTREE_MIN_NAME "shmsg_btree_min" /* Shared message B-tree minimum size */ -#define H5F_CRT_FILE_SPACE_STRATEGY_NAME "file_space_strategy" /* File space handling strategy */ -#define H5F_CRT_FREE_SPACE_PERSIST_NAME "free_space_persist" /* Free-space persisting status */ +#define H5F_CRT_SHMSG_LIST_MAX_NAME "shmsg_list_max" /* Shared message list maximum size */ +#define H5F_CRT_SHMSG_BTREE_MIN_NAME "shmsg_btree_min" /* Shared message B-tree minimum size */ +#define H5F_CRT_FILE_SPACE_STRATEGY_NAME "file_space_strategy" /* File space handling strategy */ +#define H5F_CRT_FREE_SPACE_PERSIST_NAME "free_space_persist" /* Free-space persisting status */ #define H5F_CRT_FREE_SPACE_THRESHOLD_NAME "free_space_threshold" /* Free space section threshold */ #define H5F_CRT_FILE_SPACE_PAGE_SIZE_NAME "file_space_page_size" /* File space page size */ /* ========= File Access properties ============ */ #define H5F_ACS_META_CACHE_INIT_CONFIG_NAME \ - "mdc_initCacheCfg" /* Initial metadata cache resize configuration */ + "mdc_initCacheCfg" /* Initial metadata cache resize configuration */ #define H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME "rdcc_nslots" /* Size of raw data chunk cache(slots) */ #define H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME "rdcc_nbytes" /* Size of raw data chunk cache(bytes) */ -#define H5F_ACS_PREEMPT_READ_CHUNKS_NAME "rdcc_w0" /* Preemption read chunks first */ -#define H5F_ACS_ALIGN_THRHD_NAME "threshold" /* Threshold for alignment */ -#define H5F_ACS_ALIGN_NAME "align" /* Alignment */ +#define H5F_ACS_PREEMPT_READ_CHUNKS_NAME "rdcc_w0" /* Preemption read chunks first */ +#define H5F_ACS_ALIGN_THRHD_NAME "threshold" /* Threshold for alignment */ +#define H5F_ACS_ALIGN_NAME "align" /* Alignment */ #define H5F_ACS_META_BLOCK_SIZE_NAME \ "meta_block_size" /* Minimum metadata allocation block size (when aggregating metadata allocations) */ #define H5F_ACS_SIEVE_BUF_SIZE_NAME \ @@ -566,35 +566,35 @@ typedef struct H5F_t H5F_t; #define H5F_ACS_SDATA_BLOCK_SIZE_NAME \ "sdata_block_size" /* Minimum "small data" allocation block size (when aggregating "small" raw data \ allocations) */ -#define H5F_ACS_GARBG_COLCT_REF_NAME "gc_ref" /* Garbage-collect references */ -#define H5F_ACS_FILE_DRV_NAME "vfd_info" /* File driver ID & info */ +#define H5F_ACS_GARBG_COLCT_REF_NAME "gc_ref" /* Garbage-collect references */ +#define H5F_ACS_FILE_DRV_NAME "vfd_info" /* File driver ID & info */ #define H5F_ACS_VOL_CONN_NAME "vol_connector_info" /* VOL connector ID & info */ -#define H5F_ACS_CLOSE_DEGREE_NAME "close_degree" /* File close degree */ -#define H5F_ACS_FAMILY_OFFSET_NAME "family_offset" /* Offset position in file for family file driver */ +#define H5F_ACS_CLOSE_DEGREE_NAME "close_degree" /* File close degree */ +#define H5F_ACS_FAMILY_OFFSET_NAME "family_offset" /* Offset position in file for family file driver */ #define H5F_ACS_FAMILY_NEWSIZE_NAME \ "family_newsize" /* New member size of family driver. (private property only used by h5repart) */ #define H5F_ACS_FAMILY_TO_SINGLE_NAME \ "family_to_single" /* Whether to convert family to a single-file driver. (private property only used by \ h5repart) */ -#define H5F_ACS_MULTI_TYPE_NAME "multi_type" /* Data type in multi file driver */ -#define H5F_ACS_LIBVER_LOW_BOUND_NAME "libver_low_bound" /* 'low' bound of library format versions */ +#define H5F_ACS_MULTI_TYPE_NAME "multi_type" /* Data type in multi file driver */ +#define H5F_ACS_LIBVER_LOW_BOUND_NAME "libver_low_bound" /* 'low' bound of library format versions */ #define H5F_ACS_LIBVER_HIGH_BOUND_NAME "libver_high_bound" /* 'high' bound of library format versions */ #define H5F_ACS_WANT_POSIX_FD_NAME \ "want_posix_fd" /* Internal: query the file descriptor from the core VFD, instead of the memory address \ */ #define H5F_ACS_METADATA_READ_ATTEMPTS_NAME "metadata_read_attempts" /* # of metadata read attempts */ -#define H5F_ACS_OBJECT_FLUSH_CB_NAME "object_flush_cb" /* Object flush callback */ -#define H5F_ACS_EFC_SIZE_NAME "efc_size" /* Size of external file cache */ +#define H5F_ACS_OBJECT_FLUSH_CB_NAME "object_flush_cb" /* Object flush callback */ +#define H5F_ACS_EFC_SIZE_NAME "efc_size" /* Size of external file cache */ #define H5F_ACS_FILE_IMAGE_INFO_NAME \ "file_image_info" /* struct containing initial file image and callback info */ #define H5F_ACS_CLEAR_STATUS_FLAGS_NAME \ "clear_status_flags" /* Whether to clear superblock status_flags (private property only used by h5clear) \ */ -#define H5F_ACS_NULL_FSM_ADDR_NAME "null_fsm_addr" /* Nullify addresses of free-space managers */ - /* Private property used only by h5clear */ -#define H5F_ACS_SKIP_EOF_CHECK_NAME "skip_eof_check" /* Skip EOF check */ - /* Private property used only by h5clear */ -#define H5F_ACS_USE_MDC_LOGGING_NAME "use_mdc_logging" /* Whether to use metadata cache logging */ +#define H5F_ACS_NULL_FSM_ADDR_NAME "null_fsm_addr" /* Nullify addresses of free-space managers */ +/* Private property used only by h5clear */ +#define H5F_ACS_SKIP_EOF_CHECK_NAME "skip_eof_check" /* Skip EOF check */ +/* Private property used only by h5clear */ +#define H5F_ACS_USE_MDC_LOGGING_NAME "use_mdc_logging" /* Whether to use metadata cache logging */ #define H5F_ACS_MDC_LOG_LOCATION_NAME "mdc_log_location" /* Name of metadata cache log location */ #define H5F_ACS_START_MDC_LOG_ON_ACCESS_NAME \ "start_mdc_log_on_access" /* Whether logging starts on file create/open */ @@ -640,7 +640,7 @@ typedef struct H5F_t H5F_t; 3 /* With file locking and consistency flags (at least this version for SWMR support) */ #define HDF5_SUPERBLOCK_VERSION_LATEST HDF5_SUPERBLOCK_VERSION_3 /* The maximum super block format */ #define HDF5_SUPERBLOCK_VERSION_V18_LATEST \ - HDF5_SUPERBLOCK_VERSION_2 /* The latest superblock version for v18 */ + HDF5_SUPERBLOCK_VERSION_2 /* The latest superblock version for v18 */ #define HDF5_FREESPACE_VERSION 0 /* of the Free-Space Info */ #define HDF5_OBJECTDIR_VERSION 0 /* of the Object Directory format */ #define HDF5_SHAREDHEADER_VERSION 0 /* of the Shared-Header Info */ @@ -648,14 +648,15 @@ typedef struct H5F_t H5F_t; /* B-tree internal 'K' values */ #define HDF5_BTREE_SNODE_IK_DEF 16 -#define HDF5_BTREE_CHUNK_IK_DEF 32 /* Note! this value is assumed \ - to be 32 for version 0 \ - of the superblock and \ - if it is changed, the code \ - must compensate. -QAK \ - */ +#define HDF5_BTREE_CHUNK_IK_DEF \ + 32 /* Note! this value is assumed \ + to be 32 for version 0 \ + of the superblock and \ + if it is changed, the code \ + must compensate. -QAK \ + */ #define HDF5_BTREE_IK_MAX_ENTRIES 65536 /* 2^16 - 2 bytes for storing entries (children) */ - /* See format specification on version 1 B-trees */ +/* See format specification on version 1 B-trees */ /* Default file space handling strategy */ #define H5F_FILE_SPACE_STRATEGY_DEF H5F_FSPACE_STRATEGY_FSM_AGGR @@ -690,7 +691,7 @@ typedef struct H5F_t H5F_t; #define H5F_PAGED_AGGR(F) (F->shared->fs_strategy == H5F_FSPACE_STRATEGY_PAGE && F->shared->fs_page_size) /* Metadata read attempt values */ -#define H5F_METADATA_READ_ATTEMPTS 1 /* Default # of read attempts for non-SWMR access */ +#define H5F_METADATA_READ_ATTEMPTS 1 /* Default # of read attempts for non-SWMR access */ #define H5F_SWMR_METADATA_READ_ATTEMPTS 100 /* Default # of read attempts for SWMR access */ /* Macros to define signatures of all objects in the file */ @@ -806,7 +807,7 @@ typedef enum H5F_mem_page_t { } H5F_mem_page_t; /* Aliases for H5F_mem_page_t enum values */ -#define H5F_MEM_PAGE_META H5F_MEM_PAGE_SUPER /* Small-sized meta data */ +#define H5F_MEM_PAGE_META H5F_MEM_PAGE_SUPER /* Small-sized meta data */ #define H5F_MEM_PAGE_GENERIC H5F_MEM_PAGE_LARGE_SUPER /* Large-sized generic: meta and raw */ /* Type of prefix for opening prefixed files */ diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h index 7981372..851d64d 100644 --- a/src/H5Fpublic.h +++ b/src/H5Fpublic.h @@ -84,8 +84,9 @@ #define H5F_OBJ_DATATYPE (0x0008u) /**< Named datatype objects */ #define H5F_OBJ_ATTR (0x0010u) /**< Attribute objects */ #define H5F_OBJ_ALL (H5F_OBJ_FILE | H5F_OBJ_DATASET | H5F_OBJ_GROUP | H5F_OBJ_DATATYPE | H5F_OBJ_ATTR) -#define H5F_OBJ_LOCAL (0x0020u) /**< Restrict search to objects opened through current file ID - (as opposed to objects opened through any file ID accessing this file) */ +#define H5F_OBJ_LOCAL \ + (0x0020u) /**< Restrict search to objects opened through current file ID \ + (as opposed to objects opened through any file ID accessing this file) */ #define H5F_FAMILY_DEFAULT (hsize_t)0 @@ -356,6 +357,8 @@ H5_DLL htri_t H5Fis_accessible(const char *container_name, hid_t fapl_id); * */ H5_DLL hid_t H5Fcreate(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id); +H5_DLL hid_t H5Fcreate_async(const char *app_file, const char *app_func, unsigned app_line, + const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t es_id); /** * \ingroup H5F * @@ -446,6 +449,8 @@ H5_DLL hid_t H5Fcreate(const char *filename, unsigned flags, hid_t fcpl_id, hid_ * */ H5_DLL hid_t H5Fopen(const char *filename, unsigned flags, hid_t fapl_id); +H5_DLL hid_t H5Fopen_async(const char *app_file, const char *app_func, unsigned app_line, + const char *filename, unsigned flags, hid_t access_plist, hid_t es_id); /** * \ingroup H5F * @@ -472,6 +477,8 @@ H5_DLL hid_t H5Fopen(const char *filename, unsigned flags, hid_t fapl_id); * */ H5_DLL hid_t H5Freopen(hid_t file_id); +H5_DLL hid_t H5Freopen_async(const char *app_file, const char *app_func, unsigned app_line, hid_t file_id, + hid_t es_id); /** * \ingroup H5F * @@ -502,6 +509,8 @@ H5_DLL hid_t H5Freopen(hid_t file_id); * */ H5_DLL herr_t H5Fflush(hid_t object_id, H5F_scope_t scope); +H5_DLL herr_t H5Fflush_async(const char *app_file, const char *app_func, unsigned app_line, hid_t object_id, + H5F_scope_t scope, hid_t es_id); /** * \example H5Fclose.c * After creating an HDF5 file with H5Fcreate(), we close it with @@ -551,6 +560,8 @@ H5_DLL herr_t H5Fflush(hid_t object_id, H5F_scope_t scope); * */ H5_DLL herr_t H5Fclose(hid_t file_id); +H5_DLL herr_t H5Fclose_async(const char *app_file, const char *app_func, unsigned app_line, hid_t file_id, + hid_t es_id); /** * \ingroup H5F * @@ -988,8 +999,8 @@ H5_DLL ssize_t H5Fget_file_image(hid_t file_id, void *buf_ptr, size_t buf_len); * </tr> * <tr> * <td><em>hbool_t</em> <code>open_trace_file</code> </td> - * <td>OUT: Boolean field indicating whether the <code>trace_file_name</code> field should be used to open - * a trace file for the cache. This field will always be set to <code>0</code> in this context.</td> + * <td>OUT: Boolean field indicating whether the <code>trace_file_name</code> field should be used to + * open a trace file for the cache. This field will always be set to <code>0</code> in this context.</td> * </tr> * <tr> * <td><em>hbool_t</em> <code>close_trace_file</code> </td> @@ -997,9 +1008,8 @@ H5_DLL ssize_t H5Fget_file_image(hid_t file_id, void *buf_ptr, size_t buf_len); * will always be set to <code>0</code> in this context.</td></tr> * <tr> * <td><em>char*</em><code>trace_file_name</code> </td> - * <td>OUT: Full path name of the trace file to be opened if the <code>open_trace_file</code> field is set - * to <code>1</code>. This field will always be set to the empty string in this context.</td></tr> - * <tr> + * <td>OUT: Full path name of the trace file to be opened if the <code>open_trace_file</code> field is + * set to <code>1</code>. This field will always be set to the empty string in this context.</td></tr> <tr> * <td><em>hbool_t</em> <code>evictions_enabled</code> </td> * <td>OUT: Boolean flag indicating whether metadata cache entry evictions are * enabled.</td> @@ -1042,8 +1052,8 @@ H5_DLL ssize_t H5Fget_file_image(hid_t file_id, void *buf_ptr, size_t buf_len); * <table> * <tr> * <td><em>enum H5C_cache_incr_mode</em> <code>incr_mode</code> </td> - * <td>OUT: Enumerated value indicating the operational mode of the automatic cache size increase code. At - * present, only the following values are legal:<p>\c H5C_incr__off: Automatic cache size increase is + * <td>OUT: Enumerated value indicating the operational mode of the automatic cache size increase code. + * At present, only the following values are legal:<p>\c H5C_incr__off: Automatic cache size increase is * disabled.</p><p>\c H5C_incr__threshold: Automatic cache size increase is enabled using the hit rate * threshold algorithm.</p></td> * </tr> @@ -1071,8 +1081,8 @@ H5_DLL ssize_t H5Fget_file_image(hid_t file_id, void *buf_ptr, size_t buf_len); * <td><em>enum H5C_cache_flash_incr_mode</em> <code>flash_incr_mode</code> </td> * <td>OUT: Enumerated value indicating the operational mode of the flash cache size increase code. At * present, only the following values are legal:<p>\c H5C_flash_incr__off: Flash cache size increase is - * disabled.</p><p>\c H5C_flash_incr__add_space: Flash cache size increase is enabled using the add space - * algorithm.</p></td> + * disabled.</p><p>\c H5C_flash_incr__add_space: Flash cache size increase is enabled using the add + * space algorithm.</p></td> * </tr> * <tr> * <td><em>double</em> <code>flash_threshold</code> </td> @@ -1083,8 +1093,8 @@ H5_DLL ssize_t H5Fget_file_image(hid_t file_id, void *buf_ptr, size_t buf_len); * <tr> * <td><em>double</em> <code>flash_multiple</code> </td> * <td>OUT: The factor by which the size of the triggering entry / entry size increase is multiplied to - * obtain the initial cache size increment. This increment may be reduced to reflect existing free space - * in the cache and the <code>max_size</code> field above.</td> + * obtain the initial cache size increment. This increment may be reduced to reflect existing free + * space in the cache and the <code>max_size</code> field above.</td> * </tr> * </table> * @@ -1095,13 +1105,12 @@ H5_DLL ssize_t H5Fget_file_image(hid_t file_id, void *buf_ptr, size_t buf_len); * </tr> * <tr> * <td><em>enum H5C_cache_decr_mode</em> <code>decr_mode</code> </td> - * <td>OUT: Enumerated value indicating the operational mode of the automatic cache size decrease code. At - * present, the following values are legal:<p>H5C_decr__off: Automatic cache size decrease is disabled, - * and the remaining decrement fields are ignored.</p><p>H5C_decr__threshold: Automatic cache size - * decrease is enabled using the hit rate threshold algorithm.</p><p>H5C_decr__age_out: Automatic cache - * size decrease is enabled using the ageout algorithm.</p><p>H5C_decr__age_out_with_threshold: - * Automatic cache size decrease is enabled using the ageout with hit rate threshold - * algorithm</p></td> + * <td>OUT: Enumerated value indicating the operational mode of the automatic cache size decrease code. + * At present, the following values are legal:<p>H5C_decr__off: Automatic cache size decrease is disabled, and + * the remaining decrement fields are ignored.</p><p>H5C_decr__threshold: Automatic cache size decrease is + * enabled using the hit rate threshold algorithm.</p><p>H5C_decr__age_out: Automatic cache size decrease is + * enabled using the ageout algorithm.</p><p>H5C_decr__age_out_with_threshold: Automatic cache size decrease + * is enabled using the ageout with hit rate threshold algorithm</p></td> * </tr> * <tr><td><em>double</em> <code>upper_hr_threshold</code> </td> * <td>OUT: Upper hit rate threshold. This value is only used if the decr_mode is either @@ -1144,7 +1153,8 @@ H5_DLL ssize_t H5Fget_file_image(hid_t file_id, void *buf_ptr, size_t buf_len); * <tr><td><em>int</em> <code>dirty_bytes_threshold</code> </td> * <td>OUT: Threshold number of bytes of dirty metadata generation for triggering synchronizations of the * metadata caches serving the target file in the parallel case.<p>Synchronization occurs whenever the - * number of bytes of dirty metadata created since the last synchronization exceeds this limit.</p></td> + * number of bytes of dirty metadata created since the last synchronization exceeds this + * limit.</p></td> * </tr> * </table> * @@ -1180,59 +1190,57 @@ H5_DLL herr_t H5Fget_mdc_config(hid_t file_id, H5AC_cache_config_t *config_ptr); * <tr> * <td><em>hbool_t</em> <code>rpt_fcn_enabled</code></td> * <td>IN: Boolean flag indicating whether the adaptive cache resize report function is enabled. This - * field should almost always be set to disabled (<code>0</code>). Since resize algorithm activity is reported - * via stdout, it MUST be set to disabled (<code>0</code>) on Windows machines.<p>The report function is not - * supported code, and can be expected to change between versions of the library. Use it at your own + * field should almost always be set to disabled (<code>0</code>). Since resize algorithm activity is + * reported via stdout, it MUST be set to disabled (<code>0</code>) on Windows machines.<p>The report function + * is not supported code, and can be expected to change between versions of the library. Use it at your own * risk.</p></td> * </tr> * <tr> * <td><em>hbool_t</em> <code>open_trace_File</code></td> * <td>IN: Boolean field indicating whether the <code>trace_file_name</code> field should be used to open - * a trace file for the cache.<p>The trace file is a debuging feature that allows the capture of top level - * metadata cache requests for purposes of debugging and/or optimization. This field should normally be set - * to <code>0</code>, as trace file collection imposes considerable overhead.</p><p>This field should only be - * set to <code>1</code> when the <code>trace_file_name</code> contains the full path of the desired trace - * file, and either there is no open trace file on the cache, or the <code>close_trace_file</code> field is - * also <code>1</code>.</p><p>The trace file feature is unsupported unless used at the direction of The HDF - * Group. It is intended to allow The HDF Group to collect a trace of cache activity in cases of occult - * failures and/or poor performance seen in the field, so as to aid in reproduction in the lab. If you use it - * absent the direction of The HDF Group, you are on your - * own.</p></td> + * a trace file for the cache.<p>The trace file is a debuging feature that allows the capture of top + * level metadata cache requests for purposes of debugging and/or optimization. This field should normally be + * set to <code>0</code>, as trace file collection imposes considerable overhead.</p><p>This field should only + * be set to <code>1</code> when the <code>trace_file_name</code> contains the full path of the desired trace + * file, and either there is no open trace file on the cache, or the <code>close_trace_file</code> + * field is also <code>1</code>.</p><p>The trace file feature is unsupported unless used at the direction of + * The HDF Group. It is intended to allow The HDF Group to collect a trace of cache activity in cases of + * occult failures and/or poor performance seen in the field, so as to aid in reproduction in the lab. If you + * use it absent the direction of The HDF Group, you are on your own.</p></td> * </tr> * <tr><td><em>hbool_t</em> <code>close_trace_file</code></td> * <td>IN: Boolean field indicating whether the current trace file (if any) should be closed.<p>See the - * above comments on the <code>open_trace_file</code> field. This field should be set to <code>0</code> unless - * there is an open trace file on the cache that you wish to close.</p><p>The trace file feature is - * unsupported unless used at the direction of The HDF Group. It is intended to allow The HDF Group to collect - * a trace of cache activity in cases of occult failures and/or poor performance seen in the field, so as to - * aid in reproduction in the lab. If you use it absent the direction of The HDF Group, you are on your - * own.</p></td> + * above comments on the <code>open_trace_file</code> field. This field should be set to + * <code>0</code> unless there is an open trace file on the cache that you wish to close.</p><p>The trace file + * feature is unsupported unless used at the direction of The HDF Group. It is intended to allow The HDF Group + * to collect a trace of cache activity in cases of occult failures and/or poor performance seen in the field, + * so as to aid in reproduction in the lab. If you use it absent the direction of The HDF Group, you are on + * your own.</p></td> * </tr> * <tr> * <td><em>char</em> <code>trace_file_name[]</code></td> * <td>IN: Full path of the trace file to be opened if the <code>open_trace_file</code> field is set - * to <code>1</code>.<p>In the parallel case, an ascii representation of the mpi rank of the process will be - * appended to the file name to yield a unique trace file name for each process.</p><p>The length of the path - * must not exceed #H5AC__MAX_TRACE_FILE_NAME_LEN characters.</p><p>The trace file feature is - * unsupported unless used at the direction of The HDF Group. It is intended to allow The HDF Group to collect - * a trace of cache activity in cases of occult failures and/or poor performance seen in the field, so as to - * aid in reproduction in the lab. If you use it absent the direction of The HDF Group, you are on your - * own.</p></td> + * to <code>1</code>.<p>In the parallel case, an ascii representation of the mpi rank of the process + * will be appended to the file name to yield a unique trace file name for each process.</p><p>The length of + * the path must not exceed #H5AC__MAX_TRACE_FILE_NAME_LEN characters.</p><p>The trace file feature is + * unsupported unless used at the direction of The HDF Group. It is intended to allow The HDF Group + * to collect a trace of cache activity in cases of occult failures and/or poor performance seen in the field, + * so as to aid in reproduction in the lab. If you use it absent the direction of The HDF Group, you are on + * your own.</p></td> * </tr> * <tr> * <td><em>hbool_t</em> <code>evictions_enabled</code></td> * <td>IN: A boolean flag indicating whether evictions from the metadata cache are enabled. This flag is - * initially set to enabled (<code>1</code>).<p>In rare circumstances, the raw data throughput requirements - * may be so high that the user wishes to postpone metadata writes so as to reserve I/O throughput for raw - * data. The <code>evictions_enabled</code> field exists to allow this. However, this is an extreme step, and - * you have no business doing it unless you have read the User Guide section on metadata caching, and have - * considered all other options carefully.</p><p>The <code>evictions_enabled</code> field may not be set to - * disabled (<code>0</code>) unless all adaptive cache resizing code is disabled via - * the <code>incr_mode</code>, <code>flash_incr_mode</code>, and <code>decr_mode</code> fields.</p><p>When - * this flag is set to disabled (<code>0</code>), the metadata cache will not attempt to evict entries to make - * space for new entries, and thus will grow without bound.</p><p>Evictions will be re-enabled when this field - * is set back to <code>1</code>. This should be done as soon as - * possible.</p></td> + * initially set to enabled (<code>1</code>).<p>In rare circumstances, the raw data throughput + * requirements may be so high that the user wishes to postpone metadata writes so as to reserve I/O + * throughput for raw data. The <code>evictions_enabled</code> field exists to allow this. However, this is an + * extreme step, and you have no business doing it unless you have read the User Guide section on metadata + * caching, and have considered all other options carefully.</p><p>The <code>evictions_enabled</code> field + * may not be set to disabled (<code>0</code>) unless all adaptive cache resizing code is disabled via the + * <code>incr_mode</code>, <code>flash_incr_mode</code>, and <code>decr_mode</code> fields.</p><p>When this + * flag is set to disabled (<code>0</code>), the metadata cache will not attempt to evict entries to make + * space for new entries, and thus will grow without bound.</p><p>Evictions will be re-enabled when + * this field is set back to <code>1</code>. This should be done as soon as possible.</p></td> * </tr> * <tr> * <td><em>hbool_t</em> <code>set_initial_size</code></td> @@ -1242,24 +1250,24 @@ H5_DLL herr_t H5Fget_mdc_config(hid_t file_id, H5AC_cache_config_t *config_ptr); * <tr> * <td><em>size_t</em> <code>initial_size</code></td> * <td>IN: If <code>set_initial_size</code> is set to <code>1</code>, then <code>initial_size</code> must - * contain the desired initial size in bytes. This value must lie in the closed interval <code>[min_size, - * max_size]</code>. (see below)</td> + * contain the desired initial size in bytes. This value must lie in the closed interval + * <code>[min_size, max_size]</code>. (see below)</td> * </tr> * <tr><td><em>double</em> <code>min_clean_fraction</code></td> * <td>IN: This field specifies the minimum fraction of the cache that must be kept either clean or - * empty.<p>The value must lie in the interval [0.0, 1.0]. 0.01 is a good place to start in the serial case. - * In the parallel case, a larger value is needed -- - * see <a href="/display/HDF5/Metadata+Caching+in+HDF5">Metadata Caching in HDF5</a> in the collection - * "Advanced Topics in HDF5."</p></td> + * empty.<p>The value must lie in the interval [0.0, 1.0]. 0.01 is a good place to start in the serial + * case. In the parallel case, a larger value is needed -- see <a + * href="/display/HDF5/Metadata+Caching+in+HDF5">Metadata Caching in HDF5</a> in the collection "Advanced + * Topics in HDF5."</p></td> * </tr> * <tr><td><em>size_t</em> <code>max_size</code></td> - * <td>IN: Upper bound (in bytes) on the range of values that the adaptive cache resize code can select as - * the maximum cache size.</td> + * <td>IN: Upper bound (in bytes) on the range of values that the adaptive cache resize code can select + * as the maximum cache size.</td> * </tr> * <tr> * <td><em>size_t</em> <code>min_size</code></td> - * <td>IN: Lower bound (in bytes) on the range of values that the adaptive cache resize code can select as - * the maximum cache size.</td> + * <td>IN: Lower bound (in bytes) on the range of values that the adaptive cache resize code can select + * as the maximum cache size.</td> * </tr> * <tr><td><em>long int</em> <code>epoch_length</code></td> * <td>IN: Number of cache accesses between runs of the adaptive cache resize code. 50,000 is a good @@ -1272,27 +1280,25 @@ H5_DLL herr_t H5Fget_mdc_config(hid_t file_id, H5AC_cache_config_t *config_ptr); * <tr> * <td><em>enum H5C_cache_incr_mode</em> <code>incr_mode</code></td> * <td>IN: Enumerated value indicating the operational mode of the automatic cache size increase code. At - * present, only two values are legal:<p>\c H5C_incr__off: Automatic cache size increase is disabled, and the - * remaining increment fields are ignored.</p><p>\c H5C_incr__threshold: Automatic cache size increase is enabled - * using the hit rate threshold - * algorithm.</p></td> + * present, only two values are legal:<p>\c H5C_incr__off: Automatic cache size increase is disabled, + * and the remaining increment fields are ignored.</p><p>\c H5C_incr__threshold: Automatic cache size increase + * is enabled using the hit rate threshold algorithm.</p></td> * </tr> * <tr> * <td><em>double</em> <code>lower_hr_threshold</code></td> * <td>IN: Hit rate threshold used by the hit rate threshold cache size increment algorithm.<p>When the - * hit rate over an epoch is below this threshold and the cache is full, the maximum size of the cache is - * multiplied by increment (below), and then clipped as necessary to stay within max_size, and possibly - * max_increment.</p><p>This field must lie in the interval [0.0, 1.0]. 0.8 or 0.9 is a good starting + * hit rate over an epoch is below this threshold and the cache is full, the maximum size of the + * cache is multiplied by increment (below), and then clipped as necessary to stay within max_size, and + * possibly max_increment.</p><p>This field must lie in the interval [0.0, 1.0]. 0.8 or 0.9 is a good starting * point.</p></td> * </tr> * <tr> * <td><em>double</em> <code>increment</code></td> * <td>IN: Factor by which the hit rate threshold cache size increment algorithm multiplies the current - * maximum cache size to obtain a tentative new cache size.<p>The actual cache size increase will be clipped - * to satisfy the max_size specified in the general configuration, and possibly max_increment below.</p><p>The - * parameter must be greater than or equal to 1.0 -- 2.0 is a reasonable value.</p><p>If you set it to 1.0, - * you will effectively disable cache size - * increases.</p></td> + * maximum cache size to obtain a tentative new cache size.<p>The actual cache size increase will be + * clipped to satisfy the max_size specified in the general configuration, and possibly max_increment + * below.</p><p>The parameter must be greater than or equal to 1.0 -- 2.0 is a reasonable value.</p><p>If you + * set it to 1.0, you will effectively disable cache size increases.</p></td> * </tr> * <tr> * <td><em>hbool_t</em> <code>apply_max_increment</code></td> @@ -1308,21 +1314,21 @@ H5_DLL herr_t H5Fget_mdc_config(hid_t file_id, H5AC_cache_config_t *config_ptr); * <td><em>enum H5C_cache_flash_incr_mode</em> <code>flash_incr_mode</code></td> * <td>IN: Enumerated value indicating the operational mode of the flash cache size increase code. At * present, only the following values are legal:<p>\c H5C_flash_incr__off: Flash cache size increase is - * disabled.</p><p>\c H5C_flash_incr__add_space: Flash cache size increase is enabled using the add space - * algorithm.</p></td> + * disabled.</p><p>\c H5C_flash_incr__add_space: Flash cache size increase is enabled using the add + * space algorithm.</p></td> * </tr> * <tr> * <td><em>double</em> <code>flash_threshold</code></td> * <td>IN: The factor by which the current maximum cache size is multiplied to obtain the minimum size - * entry / entry size increase which may trigger a flash cache size increase.<p>At present, this value must - * lie in the range [0.1, 1.0].</p></td> + * entry / entry size increase which may trigger a flash cache size increase.<p>At present, this value + * must lie in the range [0.1, 1.0].</p></td> * </tr> * <tr> * <td><em>double</em> <code>flash_multiple</code></td> * <td>IN: The factor by which the size of the triggering entry / entry size increase is multiplied to - * obtain the initial cache size increment. This increment may be reduced to reflect existing free space in - * the cache and the <code>max_size</code> field above.<p>At present, this field must lie in the range [0.1, - * 10.0].</p></td> + * obtain the initial cache size increment. This increment may be reduced to reflect existing free + * space in the cache and the <code>max_size</code> field above.<p>At present, this field must lie in the + * range [0.1, 10.0].</p></td> * </tr> * </table> * @@ -1332,31 +1338,29 @@ H5_DLL herr_t H5Fget_mdc_config(hid_t file_id, H5AC_cache_config_t *config_ptr); * <td><em>enum H5C_cache_decr_mode</em> <code>decr_mode</code></td> * <td>IN: Enumerated value indicating the operational mode of the automatic cache size decrease code. At * present, the following values are legal:<p>\c H5C_decr__off: Automatic cache size decrease is - * disabled.</p><p>\c H5C_decr__threshold: Automatic cache size decrease is enabled using the hit rate threshold - * algorithm.</p><p>\c H5C_decr__age_out: Automatic cache size decrease is enabled using the ageout - * algorithm.</p><p>\c H5C_decr__age_out_with_threshold: Automatic cache size decrease is enabled using the - * ageout with hit rate threshold - * algorithm</p></td> + * disabled.</p><p>\c H5C_decr__threshold: Automatic cache size decrease is enabled using the hit + * rate threshold algorithm.</p><p>\c H5C_decr__age_out: Automatic cache size decrease is enabled using the + * ageout algorithm.</p><p>\c H5C_decr__age_out_with_threshold: Automatic cache size decrease is enabled using + * the ageout with hit rate threshold algorithm</p></td> * </tr> * <tr> * <td><em>double</em> <code>upper_hr_threshold</code></td> * <td>IN: Hit rate threshold for the hit rate threshold and ageout with hit rate threshold cache size - * decrement algorithms.<p>When \c decr_mode is \c H5C_decr__threshold, and the hit rate over a given epoch exceeds - * the supplied threshold, the current maximum cache size is multiplied by decrement to obtain a tentative new - * (and smaller) maximum cache size.</p><p>When \c decr_mode is \c H5C_decr__age_out_with_threshold, there is no - * attempt to find and evict aged out entries unless the hit rate in the previous epoch exceeded the supplied - * threshold.</p><p>This field must lie in the interval [0.0, 1.0].</p><p>For \c H5C_incr__threshold, .9995 or - * .99995 is a good place to start.</p><p>For \c H5C_decr__age_out_with_threshold, .999 might be more - * useful.</p></td> + * decrement algorithms.<p>When \c decr_mode is \c H5C_decr__threshold, and the hit rate over a given + * epoch exceeds the supplied threshold, the current maximum cache size is multiplied by decrement to obtain a + * tentative new (and smaller) maximum cache size.</p><p>When \c decr_mode is \c + * H5C_decr__age_out_with_threshold, there is no attempt to find and evict aged out entries unless the hit + * rate in the previous epoch exceeded the supplied threshold.</p><p>This field must lie in the interval + * [0.0, 1.0].</p><p>For \c H5C_incr__threshold, .9995 or .99995 is a good place to start.</p><p>For \c + * H5C_decr__age_out_with_threshold, .999 might be more useful.</p></td> * </tr> * <tr> * <td><em>double</em> <code>decrement</code></td> * <td>IN: In the hit rate threshold cache size decrease algorithm, this parameter contains the factor by - * which the current max cache size is multiplied to produce a tentative new cache size.<p>The actual cache - * size decrease will be clipped to satisfy the min_size specified in the general configuration, and possibly - * max_decrement below.</p><p>The parameter must be be in the interval [0.0, 1.0].</p><p>If you set it to 1.0, - * you will effectively disable cache size decreases. 0.9 is a reasonable starting - * point.</p></td> + * which the current max cache size is multiplied to produce a tentative new cache size.<p>The actual + * cache size decrease will be clipped to satisfy the min_size specified in the general configuration, and + * possibly max_decrement below.</p><p>The parameter must be be in the interval [0.0, 1.0].</p><p>If you set + * it to 1.0, you will effectively disable cache size decreases. 0.9 is a reasonable starting point.</p></td> * </tr> * <tr> * <td><em>hbool_t</em> <code>apply_max_decrement</code></td> @@ -1371,8 +1375,8 @@ H5_DLL herr_t H5Fget_mdc_config(hid_t file_id, H5AC_cache_config_t *config_ptr); * <tr> * <td><em>int</em> <code>epochs_before_eviction</code></td> * <td>IN: In the ageout based cache size reduction algorithms, this field contains the minimum number of - * epochs an entry must remain unaccessed in cache before the cache size reduction algorithm tries to evict - * it. 3 is a reasonable value.</td> + * epochs an entry must remain unaccessed in cache before the cache size reduction algorithm tries to + * evict it. 3 is a reasonable value.</td> * </tr> * <tr> * <td><em>hbool_t</em> <code>apply_empty_reserve</code></td> @@ -1381,9 +1385,9 @@ H5_DLL herr_t H5Fget_mdc_config(hid_t file_id, H5AC_cache_config_t *config_ptr); * </tr> * <tr> * <td><em>double</em> <code>empty_reserve</code></td> - * <td>IN: Empty reserve as a fraction of maximum cache size if applicable.<p>When so directed, the ageout - * based algorithms will not decrease the maximum cache size unless the empty reserve can be met.</p><p>The - * parameter must lie in the interval [0.0, 1.0]. 0.1 or 0.05 is a good place to + * <td>IN: Empty reserve as a fraction of maximum cache size if applicable.<p>When so directed, the + * ageout based algorithms will not decrease the maximum cache size unless the empty reserve can be + * met.</p><p>The parameter must lie in the interval [0.0, 1.0]. 0.1 or 0.05 is a good place to * start.</p></td> * </tr> * </table> @@ -1393,11 +1397,11 @@ H5_DLL herr_t H5Fget_mdc_config(hid_t file_id, H5AC_cache_config_t *config_ptr); * <tr> * <td><em>int</em> <code>dirty_bytes_threshold</code></td> * <td>IN: Threshold number of bytes of dirty metadata generation for triggering synchronizations of the - * metadata caches serving the target file in the parallel case.<p>Synchronization occurs whenever the number - * of bytes of dirty metadata created since the last synchronization exceeds this limit.</p><p>This field only - * applies to the parallel case. While it is ignored elsewhere, it can still draw a value out of bounds - * error.</p><p>It must be consistant across all caches on any given file.</p><p>By default, this field is set - * to 256 KB. It shouldn't be more than half the current maximum cache size times the minimum clean + * metadata caches serving the target file in the parallel case.<p>Synchronization occurs whenever the + * number of bytes of dirty metadata created since the last synchronization exceeds this limit.</p><p>This + * field only applies to the parallel case. While it is ignored elsewhere, it can still draw a value out of + * bounds error.</p><p>It must be consistant across all caches on any given file.</p><p>By default, this field + * is set to 256 KB. It shouldn't be more than half the current maximum cache size times the minimum clean * fraction.</p></td> * </tr> * </table> @@ -1640,7 +1644,8 @@ H5_DLL herr_t H5Fget_info2(hid_t obj_id, H5F_info2_t *file_info); * <tr><td>18</td><td>Fixed array data block</td></tr> * <tr><td>19</td><td>Fixed array data block page</td></tr> * <tr><td>20</td><td>File's superblock (version 2)</td></tr> - * <tr><td colspan=2><sup>*</sup> All entries are of version 0 (zero) unless indicated otherwise.</td></tr> + * <tr><td colspan=2><sup>*</sup> All entries are of version 0 (zero) unless indicated + * otherwise.</td></tr> * </table> * * \note On a system that is not atomic, the library might possibly read inconsistent @@ -1927,8 +1932,7 @@ H5_DLL herr_t H5Fstop_mdc_logging(hid_t file_id); * * \since 1.10.0 */ -H5_DLL herr_t H5Fget_mdc_logging_status(hid_t file_id, hbool_t *is_enabled, - hbool_t *is_currently_logging); +H5_DLL herr_t H5Fget_mdc_logging_status(hid_t file_id, hbool_t *is_enabled, hbool_t *is_currently_logging); /** * \ingroup SWMR * @@ -2065,6 +2069,7 @@ H5_DLL herr_t H5Fget_dset_no_attrs_hint(hid_t file_id, hbool_t *minimize); * */ H5_DLL herr_t H5Fset_dset_no_attrs_hint(hid_t file_id, hbool_t minimize); +H5_DLL herr_t H5Fwait(hid_t file_id); #ifdef H5_HAVE_PARALLEL /** @@ -2159,6 +2164,26 @@ H5_DLL herr_t H5Fset_mpi_atomicity(hid_t file_id, hbool_t flag); H5_DLL herr_t H5Fget_mpi_atomicity(hid_t file_id, hbool_t *flag); #endif /* H5_HAVE_PARALLEL */ +/* API Wrappers for async routines */ +/* (Must be defined _after_ the function prototype) */ +/* (And must only defined when included in application code, not the library) */ +#ifndef H5F_MODULE +#define H5Fcreate_async(...) H5Fcreate_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Fopen_async(...) H5Fopen_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Freopen_async(...) H5Freopen_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Fflush_async(...) H5Fflush_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Fclose_async(...) H5Fclose_async(__FILE__, __func__, __LINE__, __VA_ARGS__) + +/* Define "wrapper" versions of function calls, to allow compile-time values to + * be passed in by language wrapper or library layer on top of HDF5. + */ +#define H5Fcreate_async_wrap H5_NO_EXPAND(H5Fcreate_async) +#define H5Fopen_async_wrap H5_NO_EXPAND(H5Fopen_async) +#define H5Freopen_async_wrap H5_NO_EXPAND(H5Freopen_async) +#define H5Fflush_async_wrap H5_NO_EXPAND(H5Fflush_async) +#define H5Fclose_async_wrap H5_NO_EXPAND(H5Fclose_async) +#endif /* H5F_MODULE */ + /* Symbols defined for compatibility with previous versions of the HDF5 API. * * Use of these symbols is deprecated. @@ -83,6 +83,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5CXprivate.h" /* API Contexts */ #include "H5Eprivate.h" /* Error handling */ +#include "H5ESprivate.h" /* Event Sets */ #include "H5Gpkg.h" /* Groups */ #include "H5Iprivate.h" /* IDs */ #include "H5Pprivate.h" /* Property lists */ @@ -104,6 +105,20 @@ /* Local Prototypes */ /********************/ +/* Helper routines for sync/async API calls */ +static hid_t H5G__create_api_common(hid_t loc_id, const char *name, hid_t lcpl_id, hid_t gcpl_id, + hid_t gapl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr); +static hid_t H5G__open_api_common(hid_t loc_id, const char *name, hid_t gapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static herr_t H5G__get_info_api_common(hid_t loc_id, H5G_info_t *group_info /*out*/, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static herr_t H5G__get_info_by_name_api_common(hid_t loc_id, const char *name, H5G_info_t *group_info /*out*/, + hid_t lapl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr); +static herr_t H5G__get_info_by_idx_api_common(hid_t loc_id, const char *group_name, H5_index_t idx_type, + H5_iter_order_t order, hsize_t n, + H5G_info_t *group_info /*out*/, hid_t lapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); + /*********************/ /* Package Variables */ /*********************/ @@ -117,38 +132,27 @@ /*******************/ /*------------------------------------------------------------------------- - * Function: H5Gcreate2 - * - * Purpose: Creates a new group relative to LOC_ID, giving it the - * specified creation property list GCPL_ID and access - * property list GAPL_ID. The link to the new group is - * created with the LCPL_ID. - * - * Usage: H5Gcreate2(loc_id, char *name, lcpl_id, gcpl_id, gapl_id) - * hid_t loc_id; IN: File or group identifier - * const char *name; IN: Absolute or relative name of the new group - * hid_t lcpl_id; IN: Property list for link creation - * hid_t gcpl_id; IN: Property list for group creation - * hid_t gapl_id; IN: Property list for group access + * Function: H5G__create_api_common * - * Return: Success: The object ID of a new, empty group open for - * writing. Call H5Gclose() when finished with - * the group. + * Purpose: This is the common function for creating HDF5 groups. * + * Return: Success: A group ID * Failure: H5I_INVALID_HID * *------------------------------------------------------------------------- */ -hid_t -H5Gcreate2(hid_t loc_id, const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id) +static hid_t +H5G__create_api_common(hid_t loc_id, const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, + void **token_ptr, H5VL_object_t **_vol_obj_ptr) { - void * grp = NULL; /* Structure for new group */ - H5VL_object_t * vol_obj = NULL; /* object of loc_id */ - H5VL_loc_params_t loc_params; - hid_t ret_value = H5I_INVALID_HID; /* Return value */ + void * grp = NULL; /* Structure for new group */ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ - FUNC_ENTER_API(H5I_INVALID_HID) - H5TRACE5("i", "i*siii", loc_id, name, lcpl_id, gcpl_id, gapl_id); + FUNC_ENTER_STATIC /* Check arguments */ if (!name) @@ -156,6 +160,10 @@ H5Gcreate2(hid_t loc_id, const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t g if (!*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be an empty string") + /* Set up object access arguments */ + if (H5VL_setup_acc_args(loc_id, H5P_CLS_GACC, TRUE, &gapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTSET, H5I_INVALID_HID, "can't set object access arguments") + /* Check link creation property list */ if (H5P_DEFAULT == lcpl_id) lcpl_id = H5P_LINK_CREATE_DEFAULT; @@ -171,36 +179,109 @@ H5Gcreate2(hid_t loc_id, const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t g /* Set the LCPL for the API context */ H5CX_set_lcpl(lcpl_id); - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&gapl_id, H5P_CLS_GACC, loc_id, TRUE) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info") - - /* Get the location object */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier") - - /* Set the location parameters */ - loc_params.type = H5VL_OBJECT_BY_SELF; - loc_params.obj_type = H5I_get_type(loc_id); - /* Create the group */ - if (NULL == (grp = H5VL_group_create(vol_obj, &loc_params, name, lcpl_id, gcpl_id, gapl_id, - H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL))) + if (NULL == (grp = H5VL_group_create(*vol_obj_ptr, &loc_params, name, lcpl_id, gcpl_id, gapl_id, + H5P_DATASET_XFER_DEFAULT, token_ptr))) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5I_INVALID_HID, "unable to create group") /* Get an ID for the group */ - if ((ret_value = H5VL_register(H5I_GROUP, grp, vol_obj->connector, TRUE)) < 0) + if ((ret_value = H5VL_register(H5I_GROUP, grp, (*vol_obj_ptr)->connector, TRUE)) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to get ID for group handle") done: if (H5I_INVALID_HID == ret_value) - if (grp && H5VL_group_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) + if (grp && H5VL_group_close(*vol_obj_ptr, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release group") + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G__create_api_common() */ + +/*------------------------------------------------------------------------- + * Function: H5Gcreate2 + * + * Purpose: Creates a new group relative to LOC_ID, giving it the + * specified creation property list GCPL_ID and access + * property list GAPL_ID. The link to the new group is + * created with the LCPL_ID. + * + * Usage: H5Gcreate2(loc_id, char *name, lcpl_id, gcpl_id, gapl_id) + * hid_t loc_id; IN: File or group identifier + * const char *name; IN: Absolute or relative name of the new group + * hid_t lcpl_id; IN: Property list for link creation + * hid_t gcpl_id; IN: Property list for group creation + * hid_t gapl_id; IN: Property list for group access + * + * Return: Success: The object ID of a new, empty group open for + * writing. Call H5Gclose() when finished with + * the group. + * + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Gcreate2(hid_t loc_id, const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id) +{ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE5("i", "i*siii", loc_id, name, lcpl_id, gcpl_id, gapl_id); + + /* Create the group synchronously */ + if ((ret_value = H5G__create_api_common(loc_id, name, lcpl_id, gcpl_id, gapl_id, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, H5I_INVALID_HID, "unable to synchronously create group") + +done: FUNC_LEAVE_API(ret_value) } /* end H5Gcreate2() */ /*------------------------------------------------------------------------- + * Function: H5Gcreate_async + * + * Purpose: Asynchronous version of H5Gcreate + * + * Return: Success: A group ID + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Gcreate_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, const char *name, + hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE9("i", "*s*sIui*siiii", app_file, app_func, app_line, loc_id, name, lcpl_id, gcpl_id, gapl_id, + es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Create the group asynchronously */ + if ((ret_value = H5G__create_api_common(loc_id, name, lcpl_id, gcpl_id, gapl_id, token_ptr, &vol_obj)) < + 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, H5I_INVALID_HID, "unable to asynchronously create group") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE9(FUNC, "*s*sIui*siiii", app_file, app_func, app_line, loc_id, name, + lcpl_id, gcpl_id, gapl_id, es_id)) < 0) { + if (H5I_dec_app_ref_always_close(ret_value) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, H5I_INVALID_HID, "can't decrement count on group ID") + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Gcreate_async() */ + +/*------------------------------------------------------------------------- * Function: H5Gcreate_anon * * Purpose: Creates a new group relative to LOC_ID, giving it the @@ -280,30 +361,27 @@ done: } /* end H5Gcreate_anon() */ /*------------------------------------------------------------------------- - * Function: H5Gopen2 + * Function: H5G__open_api_common * - * Purpose: Opens an existing group for modification. When finished, - * call H5Gclose() to close it and release resources. - * - * This function allows the user the pass in a Group Access - * Property List, which H5Gopen1() does not. - * - * Return: Success: Object ID of the group + * Purpose: This is the common function for opening HDF5 groups. * + * Return: Success: A group ID * Failure: H5I_INVALID_HID * *------------------------------------------------------------------------- */ -hid_t -H5Gopen2(hid_t loc_id, const char *name, hid_t gapl_id) +static hid_t +H5G__open_api_common(hid_t loc_id, const char *name, hid_t gapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) { - void * grp = NULL; /* Group opened */ - H5VL_object_t * vol_obj = NULL; /* object of loc_id */ - H5VL_loc_params_t loc_params; - hid_t ret_value = H5I_INVALID_HID; /* Return value */ + void * grp = NULL; /* Group opened */ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ - FUNC_ENTER_API(H5I_INVALID_HID) - H5TRACE3("i", "i*si", loc_id, name, gapl_id); + FUNC_ENTER_STATIC /* Check args */ if (!name) @@ -311,35 +389,102 @@ H5Gopen2(hid_t loc_id, const char *name, hid_t gapl_id) if (!*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be an empty string") - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&gapl_id, H5P_CLS_GACC, loc_id, FALSE) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info") - - /* Get the location object */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier") + /* Set up object access arguments */ + if (H5VL_setup_acc_args(loc_id, H5P_CLS_GACC, FALSE, &gapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTSET, H5I_INVALID_HID, "can't set object access arguments") - /* Open the group */ - loc_params.type = H5VL_OBJECT_BY_SELF; - loc_params.obj_type = H5I_get_type(loc_id); - - if (NULL == (grp = H5VL_group_open(vol_obj, &loc_params, name, gapl_id, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL))) + if (NULL == (grp = H5VL_group_open(*vol_obj_ptr, &loc_params, name, gapl_id, H5P_DATASET_XFER_DEFAULT, + token_ptr))) HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open group") /* Register an ID for the group */ - if ((ret_value = H5VL_register(H5I_GROUP, grp, vol_obj->connector, TRUE)) < 0) + if ((ret_value = H5VL_register(H5I_GROUP, grp, (*vol_obj_ptr)->connector, TRUE)) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register group") done: if (H5I_INVALID_HID == ret_value) - if (grp && H5VL_group_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) + if (grp && H5VL_group_close(*vol_obj_ptr, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release group") + FUNC_LEAVE_NOAPI(ret_value) +} /* H5G__open_api_common() */ + +/*------------------------------------------------------------------------- + * Function: H5Gopen2 + * + * Purpose: Opens an existing group for modification. When finished, + * call H5Gclose() to close it and release resources. + * + * This function allows the user the pass in a Group Access + * Property List, which H5Gopen1() does not. + * + * Return: Success: Object ID of the group + * + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Gopen2(hid_t loc_id, const char *name, hid_t gapl_id) +{ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE3("i", "i*si", loc_id, name, gapl_id); + + /* Open the group synchronously */ + if ((ret_value = H5G__open_api_common(loc_id, name, gapl_id, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, H5I_INVALID_HID, "unable to synchronously open group") + +done: FUNC_LEAVE_API(ret_value) } /* end H5Gopen2() */ /*------------------------------------------------------------------------- + * Function: H5Gopen_async + * + * Purpose: Asynchronous version of H5Gopen2 + * + * Return: Success: A group ID + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Gopen_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, const char *name, + hid_t gapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE7("i", "*s*sIui*sii", app_file, app_func, app_line, loc_id, name, gapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Open the group asynchronously */ + if ((ret_value = H5G__open_api_common(loc_id, name, gapl_id, token_ptr, &vol_obj)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, H5I_INVALID_HID, "unable to asynchronously open group") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE7(FUNC, "*s*sIui*sii", app_file, app_func, app_line, loc_id, name, gapl_id, + es_id)) < 0) { + if (H5I_dec_app_ref_always_close(ret_value) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, H5I_INVALID_HID, "can't decrement count on group ID") + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Gopen_async() */ + +/*------------------------------------------------------------------------- * Function: H5Gget_create_plist * * Purpose: Returns a copy of the group creation property list. @@ -375,6 +520,49 @@ done: } /* end H5Gget_create_plist() */ /*------------------------------------------------------------------------- + * Function: H5G__get_info_api_common + * + * Purpose: This is the common function for retrieving information + * about a group. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G__get_info_api_common(hid_t loc_id, H5G_info_t *group_info /*out*/, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + H5I_type_t id_type; /* Type of ID */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check args */ + id_type = H5I_get_type(loc_id); + if (!(H5I_GROUP == id_type || H5I_FILE == id_type)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid group (or file) ID") + if (!group_info) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "group_info parameter cannot be NULL") + + /* Set up object access arguments */ + if (H5VL_setup_self_args(loc_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set object access arguments") + + /* Retrieve group information */ + if (H5VL_group_get(*vol_obj_ptr, H5VL_GROUP_GET_INFO, H5P_DATASET_XFER_DEFAULT, token_ptr, &loc_params, + group_info) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get group info") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5G__get_info_api_common() */ + +/*------------------------------------------------------------------------- * Function: H5Gget_info * * Purpose: Retrieve information about a group. @@ -386,35 +574,97 @@ done: herr_t H5Gget_info(hid_t loc_id, H5G_info_t *group_info /*out*/) { - H5VL_object_t * vol_obj; - H5I_type_t id_type; /* Type of ID */ - H5VL_loc_params_t loc_params; - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE2("e", "ix", loc_id, group_info); + /* Retrieve group information synchronously */ + if (H5G__get_info_api_common(loc_id, group_info, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to synchronously get group info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Gget_info() */ + +/*------------------------------------------------------------------------- + * Function: H5Gget_info_async + * + * Purpose: Asynchronous version of H5Gget_info + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5Gget_info_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + H5G_info_t *group_info /*out*/, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE6("e", "*s*sIuixi", app_file, app_func, app_line, loc_id, group_info, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Retrieve group information asynchronously */ + if (H5G__get_info_api_common(loc_id, group_info, token_ptr, &vol_obj) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to asynchronously get group info") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert( + es_id, vol_obj->connector, token, + H5ARG_TRACE6(FUNC, "*s*sIuixi", app_file, app_func, app_line, loc_id, group_info, es_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Gget_info_async() */ + +/*------------------------------------------------------------------------- + * Function: H5G__get_info_by_name_api_common + * + * Purpose: This is the common function for retrieving information + * about a group. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G__get_info_by_name_api_common(hid_t loc_id, const char *name, H5G_info_t *group_info /*out*/, + hid_t lapl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + /* Check args */ - id_type = H5I_get_type(loc_id); - if (!(H5I_GROUP == id_type || H5I_FILE == id_type)) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid group (or file) ID") if (!group_info) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "group_info parameter cannot be NULL") - /* Get group location */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") + /* Set up object access arguments */ + if (H5VL_setup_name_args(loc_id, name, H5P_CLS_LACC, FALSE, lapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set object access arguments") - /* Retrieve the group's information */ - loc_params.type = H5VL_OBJECT_BY_SELF; - loc_params.obj_type = id_type; - if (H5VL_group_get(vol_obj, H5VL_GROUP_GET_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &loc_params, + /* Retrieve group information */ + if (H5VL_group_get(*vol_obj_ptr, H5VL_GROUP_GET_INFO, H5P_DATASET_XFER_DEFAULT, token_ptr, &loc_params, group_info) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get group info") done: - FUNC_LEAVE_API(ret_value) -} /* end H5Gget_info() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* H5G__get_info_by_name_api_common() */ /*------------------------------------------------------------------------- * Function: H5Gget_info_by_name @@ -429,43 +679,99 @@ done: herr_t H5Gget_info_by_name(hid_t loc_id, const char *name, H5G_info_t *group_info /*out*/, hid_t lapl_id) { - H5VL_object_t * vol_obj; - H5VL_loc_params_t loc_params; - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE4("e", "i*sxi", loc_id, name, group_info, lapl_id); + /* Retrieve group information synchronously */ + if (H5G__get_info_by_name_api_common(loc_id, name, group_info, lapl_id, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't synchronously retrieve group info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Gget_info_by_name() */ + +/*------------------------------------------------------------------------- + * Function: H5Gget_info_by_name_async + * + * Purpose: Asynchronous version of H5Gget_info_by_name + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5Gget_info_by_name_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *name, H5G_info_t *group_info /*out*/, hid_t lapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE8("e", "*s*sIui*sxii", app_file, app_func, app_line, loc_id, name, group_info, lapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Retrieve group information asynchronously */ + if (H5G__get_info_by_name_api_common(loc_id, name, group_info, lapl_id, token_ptr, &vol_obj) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't asynchronously retrieve group info") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE8(FUNC, "*s*sIui*sxii", app_file, app_func, app_line, loc_id, name, + group_info, lapl_id, es_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Gget_info_by_name_async() */ + +/*------------------------------------------------------------------------- + * Function: H5G__get_info_by_idx_api_common + * + * Purpose: This is the common function for retrieving information + * about a group. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G__get_info_by_idx_api_common(hid_t loc_id, const char *group_name, H5_index_t idx_type, + H5_iter_order_t order, hsize_t n, H5G_info_t *group_info /*out*/, + hid_t lapl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + /* 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 (!group_info) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "group_info parameter cannot be NULL") - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set access property list info") - - /* Get the location object */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_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); + /* Set up object access arguments */ + if (H5VL_setup_idx_args(loc_id, group_name, idx_type, order, n, H5P_CLS_LACC, FALSE, lapl_id, vol_obj_ptr, + &loc_params) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set object access arguments") - /* Retrieve the group's information */ - if (H5VL_group_get(vol_obj, H5VL_GROUP_GET_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &loc_params, + /* Retrieve group information */ + if (H5VL_group_get(*vol_obj_ptr, H5VL_GROUP_GET_INFO, H5P_DATASET_XFER_DEFAULT, token_ptr, &loc_params, group_info) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve group info") + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get group info") done: - FUNC_LEAVE_API(ret_value) -} /* end H5Gget_info_by_name() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* H5G__get_info_by_idx_api_common() */ /*------------------------------------------------------------------------- * Function: H5Gget_info_by_idx @@ -481,50 +787,62 @@ herr_t H5Gget_info_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, H5G_info_t *group_info /*out*/, hid_t lapl_id) { - H5VL_object_t * vol_obj; - H5VL_loc_params_t loc_params; - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE7("e", "i*sIiIohxi", loc_id, group_name, idx_type, order, n, group_info, lapl_id); - /* Check args */ - if (!group_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "group_name parameter cannot be NULL") - if (!*group_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "group_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") - if (!group_info) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "group_info parameter cannot be NULL") + /* Retrieve group information synchronously */ + if (H5G__get_info_by_idx_api_common(loc_id, group_name, idx_type, order, n, group_info, lapl_id, NULL, + NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't synchronously retrieve group info") - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set access property list info") +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Gget_info_by_idx() */ - /* Get the location object */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_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 = group_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); - - /* Retrieve the group's information */ - if (H5VL_group_get(vol_obj, H5VL_GROUP_GET_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &loc_params, - group_info) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve group info") +/*------------------------------------------------------------------------- + * Function: H5Gget_info_by_idx_async + * + * Purpose: Asynchronous version of H5Gget_info_by_idx + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5Gget_info_by_idx_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *group_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, + H5G_info_t *group_info /*out*/, hid_t lapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE11("e", "*s*sIui*sIiIohxii", app_file, app_func, app_line, loc_id, group_name, idx_type, order, n, + group_info, lapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Retrieve group information asynchronously */ + if (H5G__get_info_by_idx_api_common(loc_id, group_name, idx_type, order, n, group_info, lapl_id, + token_ptr, &vol_obj) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't asynchronously retrieve group info") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE11(FUNC, "*s*sIui*sIiIohxii", app_file, app_func, app_line, loc_id, + group_name, idx_type, order, n, group_info, lapl_id, es_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert token into event set") done: FUNC_LEAVE_API(ret_value) -} /* end H5Gget_info_by_idx() */ +} /* H5Gget_info_by_idx_async() */ /*------------------------------------------------------------------------- * Function: H5Gclose @@ -559,6 +877,65 @@ done: } /* end H5Gclose() */ /*------------------------------------------------------------------------- + * Function: H5Gclose_async + * + * Purpose: Asynchronous version of H5Gclose + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5Gclose_async(const char *app_file, const char *app_func, unsigned app_line, hid_t group_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + H5VL_t * connector = NULL; /* VOL connector */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "*s*sIuii", app_file, app_func, app_line, group_id, es_id); + + /* Check arguments */ + if (H5I_GROUP != H5I_get_type(group_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group ID") + + /* Prepare for possible asynchronous operation */ + if (H5ES_NONE != es_id) { + /* Get group object's connector */ + if (NULL == (vol_obj = H5VL_vol_object(group_id))) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get VOL object for group") + + /* Increase connector's refcount, so it doesn't get closed if closing + * the group closes the file */ + connector = vol_obj->connector; + H5VL_conn_inc_rc(connector); + + /* Point at token for operation to set up */ + token_ptr = &token; + } /* end if */ + + /* Decrement the counter on the group ID. It will be freed if the count + * reaches zero. + */ + if (H5I_dec_app_ref_async(group_id, token_ptr) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "decrementing group ID failed") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE5(FUNC, "*s*sIuii", app_file, app_func, app_line, group_id, es_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + if (connector && H5VL_conn_dec_rc(connector) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "can't decrement ref count on connector") + + FUNC_LEAVE_API(ret_value) +} /* end H5Gclose_async() */ + +/*------------------------------------------------------------------------- * Function: H5Gflush * * Purpose: Flushes all buffers associated with a group to disk. diff --git a/src/H5Gcompact.c b/src/H5Gcompact.c index c2bbd7c..bca6477 100644 --- a/src/H5Gcompact.c +++ b/src/H5Gcompact.c @@ -52,7 +52,7 @@ typedef struct { /* upward */ H5O_link_t *lnk; /* Link struct to fill in */ - hbool_t found; /* Flag to indicate that the object was found */ + hbool_t * found; /* Pointer to flag to indicate that the object was found */ } H5G_iter_lkp_t; /* Private macros */ @@ -450,7 +450,7 @@ H5G__compact_lookup_cb(const void *_mesg, unsigned H5_ATTR_UNUSED idx, void *_ud } /* end if */ /* Indicate that the correct link was found */ - udata->found = TRUE; + *udata->found = TRUE; /* Stop iteration now */ HGOTO_DONE(H5_ITER_STOP) @@ -472,23 +472,24 @@ done: * *------------------------------------------------------------------------- */ -htri_t -H5G__compact_lookup(const H5O_loc_t *oloc, const char *name, H5O_link_t *lnk) +herr_t +H5G__compact_lookup(const H5O_loc_t *oloc, const char *name, hbool_t *found, H5O_link_t *lnk) { - H5G_iter_lkp_t udata; /* User data for iteration callback */ - H5O_mesg_operator_t op; /* Message operator */ - htri_t ret_value = FAIL; /* Return value */ + H5G_iter_lkp_t udata; /* User data for iteration callback */ + H5O_mesg_operator_t op; /* Message operator */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* check arguments */ - HDassert(lnk && oloc->file); HDassert(name && *name); + HDassert(found); + HDassert(lnk && oloc->file); /* Set up user data for iteration */ udata.name = name; udata.lnk = lnk; - udata.found = FALSE; + udata.found = found; /* Iterate through the link messages, adding them to the table */ op.op_type = H5O_MESG_OP_APP; @@ -496,9 +497,6 @@ H5G__compact_lookup(const H5O_loc_t *oloc, const char *name, H5O_link_t *lnk) if (H5O_msg_iterate(oloc, H5O_LINK_ID, &op, &udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "error iterating over link messages") - /* Determine if we found the link we were looking for */ - ret_value = (htri_t)udata.found; - done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__compact_lookup() */ diff --git a/src/H5Gdense.c b/src/H5Gdense.c index ddc9720..ce9c107 100644 --- a/src/H5Gdense.c +++ b/src/H5Gdense.c @@ -479,20 +479,20 @@ done: * * Purpose: Look up a link within a group that uses dense link storage * - * Return: Non-negative (TRUE/FALSE) on success/Negative on failure + * Return: SUCCEED/FAIL * * Programmer: Quincey Koziol * Sep 11 2006 * *------------------------------------------------------------------------- */ -htri_t -H5G__dense_lookup(H5F_t *f, const H5O_linfo_t *linfo, const char *name, H5O_link_t *lnk) +herr_t +H5G__dense_lookup(H5F_t *f, const H5O_linfo_t *linfo, const char *name, hbool_t *found, H5O_link_t *lnk) { - H5G_bt2_ud_common_t udata; /* User data for v2 B-tree link lookup */ - H5HF_t * fheap = NULL; /* Fractal heap handle */ - H5B2_t * bt2_name = NULL; /* v2 B-tree handle for name index */ - htri_t ret_value = FAIL; /* Return value */ + H5G_bt2_ud_common_t udata; /* User data for v2 B-tree link lookup */ + H5HF_t * fheap = NULL; /* Fractal heap handle */ + H5B2_t * bt2_name = NULL; /* v2 B-tree handle for name index */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -502,6 +502,7 @@ H5G__dense_lookup(H5F_t *f, const H5O_linfo_t *linfo, const char *name, H5O_link HDassert(f); HDassert(linfo); HDassert(name && *name); + HDassert(found); HDassert(lnk); /* Open the fractal heap */ @@ -521,7 +522,7 @@ H5G__dense_lookup(H5F_t *f, const H5O_linfo_t *linfo, const char *name, H5O_link udata.found_op_data = lnk; /* Find & copy the named link in the 'name' index */ - if ((ret_value = H5B2_find(bt2_name, &udata, NULL, NULL)) < 0) + if (H5B2_find(bt2_name, &udata, found, NULL, NULL) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to locate link in name index") done: diff --git a/src/H5Gloc.c b/src/H5Gloc.c index 267c762..73991c5 100644 --- a/src/H5Gloc.c +++ b/src/H5Gloc.c @@ -235,6 +235,9 @@ H5G_loc_real(void *obj, H5I_type_t type, H5G_loc_t *loc) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get group location of a dataspace selection iterator") + case H5I_EVENTSET: + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get group location of a event set") + case H5I_UNINIT: case H5I_BADID: case H5I_NTYPES: diff --git a/src/H5Gname.c b/src/H5Gname.c index 218b8d4..bf1d573 100644 --- a/src/H5Gname.c +++ b/src/H5Gname.c @@ -729,6 +729,7 @@ H5G__name_replace_cb(void *obj_ptr, hid_t obj_id, void *key) 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, FAIL, "unknown data object") diff --git a/src/H5Gnode.c b/src/H5Gnode.c index c66a174..150a3bf 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -75,7 +75,7 @@ static herr_t H5G__node_create(H5F_t *f, H5B_ins_t op, void *_lt_key, void *_ haddr_t *addr_p /*out*/); static int H5G__node_cmp2(void *_lt_key, void *_udata, void *_rt_key); static int H5G__node_cmp3(void *_lt_key, void *_udata, void *_rt_key); -static htri_t H5G__node_found(H5F_t *f, haddr_t addr, const void *_lt_key, void *_udata); +static herr_t H5G__node_found(H5F_t *f, haddr_t addr, const void *_lt_key, hbool_t *found, void *_udata); static H5B_ins_t H5G__node_insert(H5F_t *f, haddr_t addr, void *_lt_key, hbool_t *lt_key_changed, void *_md_key, void *_udata, void *_rt_key, hbool_t *rt_key_changed, haddr_t *new_node_p /*out*/); @@ -463,8 +463,7 @@ done: * UDATA entry field to the symbol table. * * Return: Success: Non-negative (TRUE/FALSE) if found and data - * returned through the UDATA pointer. - * + * returned through the UDATA pointer, if *FOUND is true. * Failure: Negative if not found. * * Programmer: Robb Matzke @@ -472,15 +471,15 @@ done: * *------------------------------------------------------------------------- */ -static htri_t -H5G__node_found(H5F_t *f, haddr_t addr, const void H5_ATTR_UNUSED *_lt_key, void *_udata) +static herr_t +H5G__node_found(H5F_t *f, haddr_t addr, const void H5_ATTR_UNUSED *_lt_key, hbool_t *found, void *_udata) { H5G_bt_lkp_t *udata = (H5G_bt_lkp_t *)_udata; H5G_node_t * sn = NULL; unsigned lt = 0, idx = 0, rt; int cmp = 1; const char * s; - htri_t ret_value = TRUE; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC @@ -489,6 +488,7 @@ H5G__node_found(H5F_t *f, haddr_t addr, const void H5_ATTR_UNUSED *_lt_key, void */ HDassert(f); HDassert(H5F_addr_defined(addr)); + HDassert(found); HDassert(udata && udata->common.heap); /* @@ -515,11 +515,15 @@ H5G__node_found(H5F_t *f, haddr_t addr, const void H5_ATTR_UNUSED *_lt_key, void } /* end while */ if (cmp) - HGOTO_DONE(FALSE) + *found = FALSE; + else { + /* Set the 'found it' flag */ + *found = TRUE; - /* Call user's callback operator */ - if ((udata->op)(&sn->entry[idx], udata->op_data) < 0) - HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "iterator callback failed") + /* Call user's callback operator */ + if ((udata->op)(&sn->entry[idx], udata->op_data) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "iterator callback failed") + } /* end else */ done: if (sn && H5AC_unprotect(f, H5AC_SNODE, addr, sn, H5AC__NO_FLAGS_SET) < 0) diff --git a/src/H5Gobj.c b/src/H5Gobj.c index 40ed72c..13af429 100644 --- a/src/H5Gobj.c +++ b/src/H5Gobj.c @@ -1079,12 +1079,12 @@ done: * *------------------------------------------------------------------------- */ -htri_t -H5G__obj_lookup(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk) +herr_t +H5G__obj_lookup(const H5O_loc_t *grp_oloc, const char *name, hbool_t *found, H5O_link_t *lnk) { - H5O_linfo_t linfo; /* Link info message */ - htri_t linfo_exists; /* Whether the link info message exists */ - htri_t ret_value = FALSE; /* Return value */ + H5O_linfo_t linfo; /* Link info message */ + htri_t linfo_exists; /* Whether the link info message exists */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE_TAG(grp_oloc->addr) @@ -1099,18 +1099,18 @@ H5G__obj_lookup(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk) /* Check for dense link storage */ if (H5F_addr_defined(linfo.fheap_addr)) { /* Get the object's info from the dense link storage */ - if ((ret_value = H5G__dense_lookup(grp_oloc->file, &linfo, name, lnk)) < 0) + if (H5G__dense_lookup(grp_oloc->file, &linfo, name, found, lnk) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object") } /* end if */ else { /* Get the object's info from the link messages */ - if ((ret_value = H5G__compact_lookup(grp_oloc, name, lnk)) < 0) + if (H5G__compact_lookup(grp_oloc, name, found, lnk) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object") } /* end else */ } /* end if */ else /* Get the object's info from the symbol table */ - if ((ret_value = H5G__stab_lookup(grp_oloc, name, lnk)) < 0) + if (H5G__stab_lookup(grp_oloc, name, found, lnk) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object") done: diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index e93e2da..174d72d 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -364,7 +364,7 @@ H5_DLL ssize_t H5G__stab_get_name_by_idx(const H5O_loc_t *oloc, H5_iter_order_t H5_DLL herr_t H5G__stab_remove(const H5O_loc_t *oloc, H5RS_str_t *grp_full_path_r, const char *name); H5_DLL herr_t H5G__stab_remove_by_idx(const H5O_loc_t *oloc, H5RS_str_t *grp_full_path_r, H5_iter_order_t order, hsize_t n); -H5_DLL herr_t H5G__stab_lookup(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk); +H5_DLL herr_t H5G__stab_lookup(const H5O_loc_t *grp_oloc, const char *name, hbool_t *found, H5O_link_t *lnk); H5_DLL herr_t H5G__stab_lookup_by_idx(const H5O_loc_t *grp_oloc, H5_iter_order_t order, hsize_t n, H5O_link_t *lnk); #ifndef H5_STRICT_FORMAT_CHECKS @@ -417,7 +417,8 @@ H5_DLL herr_t H5G__compact_remove_by_idx(const H5O_loc_t *oloc, const H5O_linfo H5_DLL herr_t H5G__compact_iterate(const H5O_loc_t *oloc, const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, H5G_lib_iterate_t op, void *op_data); -H5_DLL htri_t H5G__compact_lookup(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk); +H5_DLL herr_t H5G__compact_lookup(const H5O_loc_t *grp_oloc, const char *name, hbool_t *found, + H5O_link_t *lnk); H5_DLL herr_t H5G__compact_lookup_by_idx(const H5O_loc_t *oloc, const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, H5O_link_t *lnk); @@ -426,7 +427,8 @@ H5_DLL herr_t H5G__dense_build_table(H5F_t *f, const H5O_linfo_t *linfo, H5_ind H5_iter_order_t order, H5G_link_table_t *ltable); H5_DLL herr_t H5G__dense_create(H5F_t *f, H5O_linfo_t *linfo, const H5O_pline_t *pline); H5_DLL herr_t H5G__dense_insert(H5F_t *f, const H5O_linfo_t *linfo, const H5O_link_t *lnk); -H5_DLL htri_t H5G__dense_lookup(H5F_t *f, const H5O_linfo_t *linfo, const char *name, H5O_link_t *lnk); +H5_DLL herr_t H5G__dense_lookup(H5F_t *f, const H5O_linfo_t *linfo, const char *name, hbool_t *found, + H5O_link_t *lnk); H5_DLL herr_t H5G__dense_lookup_by_idx(H5F_t *f, const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, H5O_link_t *lnk); H5_DLL herr_t H5G__dense_iterate(H5F_t *f, const H5O_linfo_t *linfo, H5_index_t idx_type, @@ -449,7 +451,7 @@ H5_DLL htri_t H5G__obj_get_linfo(const H5O_loc_t *grp_oloc, H5O_linfo_t *linfo); H5_DLL herr_t H5G__obj_iterate(const H5O_loc_t *grp_oloc, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, H5G_lib_iterate_t op, void *op_data); H5_DLL herr_t H5G__obj_info(const H5O_loc_t *oloc, H5G_info_t *grp_info); -H5_DLL htri_t H5G__obj_lookup(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk); +H5_DLL herr_t H5G__obj_lookup(const H5O_loc_t *grp_oloc, const char *name, hbool_t *found, H5O_link_t *lnk); #ifndef H5_NO_DEPRECATED_SYMBOLS H5_DLL herr_t H5G__get_objinfo(const H5G_loc_t *loc, const char *name, hbool_t follow_link, H5G_stat_t *statbuf /*out*/); diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index a9a2903..a037e54 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -168,14 +168,14 @@ typedef enum H5G_link_iterate_op_type_t { #ifndef H5_NO_DEPRECATED_SYMBOLS H5G_LINK_OP_OLD, /* "Old" application callback */ #endif /* H5_NO_DEPRECATED_SYMBOLS */ - H5G_LINK_OP_NEW /* "New" application callback */ + H5G_LINK_OP_NEW /* "New" application callback */ } H5G_link_iterate_op_type_t; typedef struct { H5G_link_iterate_op_type_t op_type; union { #ifndef H5_NO_DEPRECATED_SYMBOLS - H5G_iterate_t op_old; /* "Old" application callback for each link */ + H5G_iterate_t op_old; /* "Old" application callback for each link */ #endif /* H5_NO_DEPRECATED_SYMBOLS */ H5L_iterate2_t op_new; /* "New" application callback for each link */ } op_func; diff --git a/src/H5Gpublic.h b/src/H5Gpublic.h index fd0106b..f209c3d 100644 --- a/src/H5Gpublic.h +++ b/src/H5Gpublic.h @@ -70,16 +70,53 @@ extern "C" { #endif H5_DLL hid_t H5Gcreate2(hid_t loc_id, const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id); +H5_DLL hid_t H5Gcreate_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, hid_t es_id); H5_DLL hid_t H5Gcreate_anon(hid_t loc_id, hid_t gcpl_id, hid_t gapl_id); H5_DLL hid_t H5Gopen2(hid_t loc_id, const char *name, hid_t gapl_id); +H5_DLL hid_t H5Gopen_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *name, hid_t gapl_id, hid_t es_id); H5_DLL hid_t H5Gget_create_plist(hid_t group_id); H5_DLL herr_t H5Gget_info(hid_t loc_id, H5G_info_t *ginfo); +H5_DLL herr_t H5Gget_info_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + H5G_info_t *group_info /*out*/, hid_t es_id); H5_DLL herr_t H5Gget_info_by_name(hid_t loc_id, const char *name, H5G_info_t *ginfo, hid_t lapl_id); +H5_DLL herr_t H5Gget_info_by_name_async(const char *app_file, const char *app_func, unsigned app_line, + hid_t loc_id, const char *name, H5G_info_t *group_info /*out*/, + hid_t lapl_id, hid_t es_id); H5_DLL herr_t H5Gget_info_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, H5G_info_t *ginfo, hid_t lapl_id); -H5_DLL herr_t H5Gclose(hid_t group_id); +H5_DLL herr_t H5Gget_info_by_idx_async(const char *app_file, const char *app_func, unsigned app_line, + hid_t loc_id, const char *group_name, H5_index_t idx_type, + H5_iter_order_t order, hsize_t n, H5G_info_t *group_info /*out*/, + hid_t lapl_id, hid_t es_id); H5_DLL herr_t H5Gflush(hid_t group_id); H5_DLL herr_t H5Grefresh(hid_t group_id); +H5_DLL herr_t H5Gclose(hid_t group_id); +H5_DLL herr_t H5Gclose_async(const char *app_file, const char *app_func, unsigned app_line, hid_t group_id, + hid_t es_id); + +/* API Wrappers for async routines */ +/* (Must be defined _after_ the function prototype) */ +/* (And must only defined when included in application code, not the library) */ +#ifndef H5G_MODULE +#define H5Gcreate_async(...) H5Gcreate_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Gopen_async(...) H5Gopen_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Gget_info_async(...) H5Gget_info_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Gget_info_by_name_async(...) H5Gget_info_by_name_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Gget_info_by_idx_async(...) H5Gget_info_by_idx_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Gclose_async(...) H5Gclose_async(__FILE__, __func__, __LINE__, __VA_ARGS__) + +/* Define "wrapper" versions of function calls, to allow compile-time values to + * be passed in by language wrapper or library layer on top of HDF5. + */ +#define H5Gcreate_async_wrap H5_NO_EXPAND(H5Gcreate_async) +#define H5Gopen_async_wrap H5_NO_EXPAND(H5Gopen_async) +#define H5Gget_info_async_wrap H5_NO_EXPAND(H5Gget_info_async) +#define H5Gget_info_by_name_async_wrap H5_NO_EXPAND(H5Gget_info_by_name_async) +#define H5Gget_info_by_idx_async_wrap H5_NO_EXPAND(H5Gget_info_by_idx_async) +#define H5Gclose_async_wrap H5_NO_EXPAND(H5Gclose_async) +#endif /* H5G_MODULE */ /* Symbols defined for compatibility with previous versions of the HDF5 API. * @@ -98,7 +135,7 @@ H5_DLL herr_t H5Grefresh(hid_t group_id); /* Macros for types of objects in a group (see H5G_obj_t definition) */ #define H5G_NTYPES 256 /* Max possible number of types */ -#define H5G_NLIBTYPES 8 /* Number of internal types */ +#define H5G_NLIBTYPES 8 /* Number of internal types */ #define H5G_NUSERTYPES (H5G_NTYPES - H5G_NLIBTYPES) #define H5G_USERTYPE(X) (8 + (X)) /* User defined types */ diff --git a/src/H5Gstab.c b/src/H5Gstab.c index c93fae6..0f8d43b 100644 --- a/src/H5Gstab.c +++ b/src/H5Gstab.c @@ -833,20 +833,21 @@ done: * *------------------------------------------------------------------------- */ -htri_t -H5G__stab_lookup(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk) +herr_t +H5G__stab_lookup(const H5O_loc_t *grp_oloc, const char *name, hbool_t *found, H5O_link_t *lnk) { - H5HL_t * heap = NULL; /* Pointer to local heap */ - H5G_bt_lkp_t bt_udata; /* Data to pass through B-tree */ - H5G_stab_fnd_ud_t udata; /* 'User data' to give to callback */ - H5O_stab_t stab; /* Symbol table message */ - htri_t ret_value = FAIL; /* Return value */ + H5HL_t * heap = NULL; /* Pointer to local heap */ + H5G_bt_lkp_t bt_udata; /* Data to pass through B-tree */ + H5G_stab_fnd_ud_t udata; /* 'User data' to give to callback */ + H5O_stab_t stab; /* Symbol table message */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* check arguments */ HDassert(grp_oloc && grp_oloc->file); HDassert(name && *name); + HDassert(found); HDassert(lnk); /* Retrieve the symbol table message for the group */ @@ -869,7 +870,7 @@ H5G__stab_lookup(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk) bt_udata.op_data = &udata; /* Search the B-tree */ - if ((ret_value = H5B_find(grp_oloc->file, H5B_SNODE, stab.btree_addr, &bt_udata)) < 0) + if (H5B_find(grp_oloc->file, H5B_SNODE, stab.btree_addr, found, &bt_udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "not found") done: diff --git a/src/H5Gtest.c b/src/H5Gtest.c index 0cdb380..92a0e4d 100644 --- a/src/H5Gtest.c +++ b/src/H5Gtest.c @@ -607,6 +607,7 @@ H5G__user_path_test(hid_t obj_id, char *user_path, size_t *user_path_len, unsign 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, FAIL, "unknown data object type") diff --git a/src/H5Gtraverse.c b/src/H5Gtraverse.c index 3de8cfa..2204209 100644 --- a/src/H5Gtraverse.c +++ b/src/H5Gtraverse.c @@ -535,7 +535,7 @@ H5G__traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target, H5G /* Traverse the path */ while ((name = H5G__component(name, &nchars)) && *name) { const char *s; /* Temporary string pointer */ - htri_t lookup_status; /* Status from object lookup */ + hbool_t lookup_status; /* Status from object lookup */ hbool_t obj_exists; /* Whether the object exists */ /* @@ -564,7 +564,8 @@ H5G__traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target, H5G } /* end if */ /* Get information for object in current group */ - if ((lookup_status = H5G__obj_lookup(grp_loc.oloc, comp, &lnk /*out*/)) < 0) + lookup_status = FALSE; + if (H5G__obj_lookup(grp_loc.oloc, comp, &lookup_status, &lnk /*out*/) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't look up component") obj_exists = FALSE; diff --git a/src/H5HFcache.c b/src/H5HFcache.c index a9f89e0..ef2c4b2 100644 --- a/src/H5HFcache.c +++ b/src/H5HFcache.c @@ -1302,9 +1302,9 @@ H5HF__cache_iblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_NDEBUG H5HF_indirect_t *iblock = (H5HF_indirect_t *)_thing; /* Indirect block info */ uint8_t * image = (uint8_t *)_image; /* Pointer into raw data buffer */ #ifndef NDEBUG - unsigned nchildren = 0; /* Track # of children */ - size_t max_child = 0; /* Track max. child entry used */ -#endif /* NDEBUG */ + unsigned nchildren = 0; /* Track # of children */ + size_t max_child = 0; /* Track max. child entry used */ +#endif /* NDEBUG */ uint32_t metadata_chksum; /* Computed metadata checksum value */ size_t u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ diff --git a/src/H5HFhuge.c b/src/H5HFhuge.c index b981797..b6b3d47 100644 --- a/src/H5HFhuge.c +++ b/src/H5HFhuge.c @@ -508,6 +508,8 @@ H5HF__huge_get_obj_len(H5HF_hdr_t *hdr, const uint8_t *id, size_t *obj_len_p) } /* end else */ } /* end if */ else { + hbool_t found = FALSE; /* Whether entry was found */ + /* Check if v2 B-tree is open yet */ if (NULL == hdr->huge_bt2) { /* Open existing v2 B-tree */ @@ -524,7 +526,10 @@ H5HF__huge_get_obj_len(H5HF_hdr_t *hdr, const uint8_t *id, size_t *obj_len_p) UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size) /* Look up object in v2 B-tree */ - if (H5B2_find(hdr->huge_bt2, &search_rec, H5HF__huge_bt2_filt_indir_found, &found_rec) != TRUE) + if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_filt_indir_found, &found_rec) < + 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree") + if (!found) HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree") /* Retrieve the object's length */ @@ -538,7 +543,9 @@ H5HF__huge_get_obj_len(H5HF_hdr_t *hdr, const uint8_t *id, size_t *obj_len_p) UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size) /* Look up object in v2 B-tree */ - if (H5B2_find(hdr->huge_bt2, &search_rec, H5HF__huge_bt2_indir_found, &found_rec) != TRUE) + if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_indir_found, &found_rec) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree") + if (!found) HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree") /* Retrieve the object's length */ @@ -587,6 +594,8 @@ H5HF__huge_get_obj_off(H5HF_hdr_t *hdr, const uint8_t *id, hsize_t *obj_off_p) H5F_addr_decode(hdr->f, &id, &obj_addr); } /* end if */ else { + hbool_t found = FALSE; /* Whether entry was found */ + /* Sanity check */ HDassert(H5F_addr_defined(hdr->huge_bt2_addr)); @@ -606,7 +615,10 @@ H5HF__huge_get_obj_off(H5HF_hdr_t *hdr, const uint8_t *id, hsize_t *obj_off_p) UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size) /* Look up object in v2 B-tree */ - if (H5B2_find(hdr->huge_bt2, &search_rec, H5HF__huge_bt2_filt_indir_found, &found_rec) != TRUE) + if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_filt_indir_found, &found_rec) < + 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree") + if (!found) HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree") /* Retrieve the object's address & length */ @@ -620,7 +632,9 @@ H5HF__huge_get_obj_off(H5HF_hdr_t *hdr, const uint8_t *id, hsize_t *obj_off_p) UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size) /* Look up object in v2 B-tree */ - if (H5B2_find(hdr->huge_bt2, &search_rec, H5HF__huge_bt2_indir_found, &found_rec) != TRUE) + if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_indir_found, &found_rec) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree") + if (!found) HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree") /* Retrieve the object's address & length */ @@ -679,6 +693,8 @@ H5HF__huge_op_real(H5HF_hdr_t *hdr, const uint8_t *id, hbool_t is_read, H5HF_ope UINT32DECODE(id, filter_mask); } /* end if */ else { + hbool_t found = FALSE; /* Whether entry was found */ + /* Sanity check */ HDassert(H5F_addr_defined(hdr->huge_bt2_addr)); @@ -698,7 +714,10 @@ H5HF__huge_op_real(H5HF_hdr_t *hdr, const uint8_t *id, hbool_t is_read, H5HF_ope UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size) /* Look up object in v2 B-tree */ - if (H5B2_find(hdr->huge_bt2, &search_rec, H5HF__huge_bt2_filt_indir_found, &found_rec) != TRUE) + if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_filt_indir_found, &found_rec) < + 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree") + if (!found) HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree") /* Retrieve the object's address & length */ @@ -714,7 +733,9 @@ H5HF__huge_op_real(H5HF_hdr_t *hdr, const uint8_t *id, hbool_t is_read, H5HF_ope UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size) /* Look up object in v2 B-tree */ - if (H5B2_find(hdr->huge_bt2, &search_rec, H5HF__huge_bt2_indir_found, &found_rec) != TRUE) + if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_indir_found, &found_rec) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree") + if (!found) HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree") /* Retrieve the object's address & length */ @@ -827,8 +848,9 @@ H5HF__huge_write(H5HF_hdr_t *hdr, const uint8_t *id, const void *obj) H5F_DECODE_LENGTH(hdr->f, id, obj_size); } /* end if */ else { - H5HF_huge_bt2_indir_rec_t found_rec; /* Record found from tracking object */ - H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */ + H5HF_huge_bt2_indir_rec_t found_rec; /* Record found from tracking object */ + H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */ + hbool_t found = FALSE; /* Whether entry was found */ /* Sanity check */ HDassert(H5F_addr_defined(hdr->huge_bt2_addr)); @@ -845,7 +867,9 @@ H5HF__huge_write(H5HF_hdr_t *hdr, const uint8_t *id, const void *obj) UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size) /* Look up object in v2 B-tree */ - if (H5B2_find(hdr->huge_bt2, &search_rec, H5HF__huge_bt2_indir_found, &found_rec) != TRUE) + if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_indir_found, &found_rec) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree") + if (!found) HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree") /* Retrieve the object's address & length */ @@ -319,13 +319,47 @@ H5Iregister(H5I_type_t type, const void *object) HGOTO_ERROR(H5E_ID, H5E_BADGROUP, H5I_INVALID_HID, "cannot call public function on library type") /* Register the object */ - ret_value = H5I_register(type, object, TRUE); + if ((ret_value = H5I__register(type, object, TRUE, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object") done: FUNC_LEAVE_API(ret_value) } /* end H5Iregister() */ /*------------------------------------------------------------------------- + * Function: H5Iregister_future + * + * Purpose: Register a "future" object. + * + * Return: Success: New future object ID + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Iregister_future(H5I_type_t type, const void *object, H5I_future_realize_func_t realize_cb, + H5I_future_discard_func_t discard_cb) +{ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE4("i", "It*xIRID", type, object, realize_cb, discard_cb); + + /* Check arguments */ + if (NULL == realize_cb) + HGOTO_ERROR(H5E_ID, H5E_BADVALUE, H5I_INVALID_HID, "NULL pointer for realize_cb not allowed") + if (NULL == discard_cb) + HGOTO_ERROR(H5E_ID, H5E_BADVALUE, H5I_INVALID_HID, "NULL pointer for realize_cb not allowed") + + /* Register the future object */ + if ((ret_value = H5I__register(type, object, TRUE, realize_cb, discard_cb)) < 0) + HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Iregister_future() */ + +/*------------------------------------------------------------------------- * Function: H5Iobject_verify * * Purpose: Find an object pointer for the specified ID, verifying that diff --git a/src/H5Idbg.c b/src/H5Idbg.c index 80be9d0..fbcf23d 100644 --- a/src/H5Idbg.c +++ b/src/H5Idbg.c @@ -136,6 +136,7 @@ H5I__id_dump_cb(void *_item, void H5_ATTR_UNUSED *_key, void *_udata) case H5I_ERROR_MSG: case H5I_ERROR_STACK: case H5I_SPACE_SEL_ITER: + case H5I_EVENTSET: case H5I_NTYPES: default: break; /* Other types of IDs are not stored in files */ diff --git a/src/H5Iint.c b/src/H5Iint.c index b511cb5..4d7c076 100644 --- a/src/H5Iint.c +++ b/src/H5Iint.c @@ -367,27 +367,52 @@ H5I__clear_type_cb(void *_info, void H5_ATTR_UNUSED *key, void *_udata) * one and forcing is off. */ if (udata->force || (info->count - (!udata->app_ref * info->app_count)) <= 1) { - /* Check for a 'free' function and call it, if it exists */ + /* Check if this is an un-realized future object */ H5_GCC_DIAG_OFF("cast-qual") - if (udata->type_info->cls->free_func && - (udata->type_info->cls->free_func)((void *)info->object, H5_REQUEST_NULL) < 0) { /* (Casting away const OK -QAK) */ - if (udata->force) { + if (info->is_future) { + /* Discard the future object */ + if ((info->discard_cb)((void *)info->object) < 0) { + if (udata->force) { #ifdef H5I_DEBUG - if (H5DEBUG(I)) { - HDfprintf(H5DEBUG(I), - "H5I: free type=%d obj=0x%08lx " - "failure ignored\n", - (int)udata->type_info->cls->type, (unsigned long)(info->object)); - } + if (H5DEBUG(I)) { + HDfprintf(H5DEBUG(I), + "H5I: discard type=%d obj=0x%08lx " + "failure ignored\n", + (int)udata->type_info->cls->type, (unsigned long)(info->object)); + } #endif /* H5I_DEBUG */ + /* Indicate node should be removed from list */ + ret_value = TRUE; + } + } + else { /* Indicate node should be removed from list */ ret_value = TRUE; } } else { - /* Indicate node should be removed from list */ - ret_value = TRUE; + /* Check for a 'free' function and call it, if it exists */ + if (udata->type_info->cls->free_func && + (udata->type_info->cls->free_func)((void *)info->object, H5_REQUEST_NULL) < 0) { + if (udata->force) { +#ifdef H5I_DEBUG + if (H5DEBUG(I)) { + HDfprintf(H5DEBUG(I), + "H5I: free type=%d obj=0x%08lx " + "failure ignored\n", + (int)udata->type_info->cls->type, (unsigned long)(info->object)); + } +#endif /* H5I_DEBUG */ + + /* Indicate node should be removed from list */ + ret_value = TRUE; + } + } + else { + /* Indicate node should be removed from list */ + ret_value = TRUE; + } } H5_GCC_DIAG_ON("cast-qual") @@ -435,10 +460,9 @@ H5I__destroy_type(H5I_type_t type) if (type_info == NULL || type_info->init_count <= 0) HGOTO_ERROR(H5E_ID, H5E_BADGROUP, FAIL, "invalid type") - /* Close/clear/destroy all IDs for this type */ - H5E_BEGIN_TRY { - H5I_clear_type(type, TRUE, FALSE); - } H5E_END_TRY /* don't care about errors */ + /* Close/clear/destroy all IDs for this type */ + H5E_BEGIN_TRY { H5I_clear_type(type, TRUE, FALSE); } + H5E_END_TRY /* don't care about errors */ /* Check if we should release the ID class */ if (type_info->cls->flags & H5I_CLASS_IS_APPLICATION) @@ -457,30 +481,34 @@ done: } /* end H5I__destroy_type() */ /*------------------------------------------------------------------------- - * Function: H5I_register + * Function: H5I__register * * Purpose: Registers an OBJECT in a TYPE and returns an ID for it. * This routine does _not_ check for unique-ness of the objects, * if you register an object twice, you will get two different * IDs for it. This routine does make certain that each ID in a * type is unique. IDs are created by getting a unique number - * for the type the ID is in and incorporating the type into + * for the type the ID is in and incorporating the TYPE into * the ID which is returned to the user. * + * IDs are marked as "future" if the realize_cb and discard_cb + * parameters are non-NULL. + * * Return: Success: New object ID * Failure: H5I_INVALID_HID * *------------------------------------------------------------------------- */ hid_t -H5I_register(H5I_type_t type, const void *object, hbool_t app_ref) +H5I__register(H5I_type_t type, const void *object, hbool_t app_ref, H5I_future_realize_func_t realize_cb, + H5I_future_discard_func_t discard_cb) { H5I_type_info_t *type_info = NULL; /* Pointer to the type */ H5I_id_info_t * info = NULL; /* Pointer to the new ID information */ hid_t new_id = H5I_INVALID_HID; /* New ID */ hid_t ret_value = H5I_INVALID_HID; /* Return value */ - FUNC_ENTER_NOAPI(H5I_INVALID_HID) + FUNC_ENTER_PACKAGE /* Check arguments */ if (type <= H5I_BADID || (int)type >= H5I_next_type_g) @@ -488,15 +516,18 @@ H5I_register(H5I_type_t type, const void *object, hbool_t app_ref) type_info = H5I_type_info_array_g[type]; if ((NULL == type_info) || (type_info->init_count <= 0)) HGOTO_ERROR(H5E_ID, H5E_BADGROUP, H5I_INVALID_HID, "invalid type") - if (NULL == (info = H5FL_MALLOC(H5I_id_info_t))) + if (NULL == (info = H5FL_CALLOC(H5I_id_info_t))) HGOTO_ERROR(H5E_ID, H5E_NOSPACE, H5I_INVALID_HID, "memory allocation failed") /* Create the struct & its ID */ - new_id = H5I_MAKE(type, type_info->nextid); - info->id = new_id; - info->count = 1; /* initial reference count */ - info->app_count = !!app_ref; - info->object = object; + new_id = H5I_MAKE(type, type_info->nextid); + info->id = new_id; + info->count = 1; /* initial reference count */ + info->app_count = !!app_ref; + info->object = object; + info->is_future = (NULL != realize_cb); + info->realize_cb = realize_cb; + info->discard_cb = discard_cb; /* Insert into the type */ if (H5SL_insert(type_info->ids, info, &info->id) < 0) @@ -515,6 +546,35 @@ H5I_register(H5I_type_t type, const void *object, hbool_t app_ref) done: FUNC_LEAVE_NOAPI(ret_value) +} /* end H5I__register() */ + +/*------------------------------------------------------------------------- + * Function: H5I_register + * + * Purpose: Library-private wrapper for H5I__register. + * + * Return: Success: New object ID + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5I_register(H5I_type_t type, const void *object, hbool_t app_ref) +{ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_NOAPI(H5I_INVALID_HID) + + /* Sanity checks */ + HDassert(type >= H5I_FILE && type < H5I_NTYPES); + HDassert(object); + + /* Retrieve ID for object */ + if (H5I_INVALID_HID == (ret_value = H5I__register(type, object, app_ref, NULL, NULL))) + HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object") + +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5I_register() */ /*------------------------------------------------------------------------- @@ -566,7 +626,7 @@ H5I_register_using_existing_id(H5I_type_t type, void *object, hbool_t app_ref, h HGOTO_ERROR(H5E_ID, H5E_BADRANGE, FAIL, "invalid type for provided ID") /* Allocate new structure to house this ID */ - if (NULL == (info = H5FL_MALLOC(H5I_id_info_t))) + if (NULL == (info = H5FL_CALLOC(H5I_id_info_t))) HGOTO_ERROR(H5E_ID, H5E_NOSPACE, FAIL, "memory allocation failed") /* Create the struct & insert requested ID */ @@ -574,6 +634,12 @@ H5I_register_using_existing_id(H5I_type_t type, void *object, hbool_t app_ref, h info->count = 1; /* initial reference count*/ info->app_count = !!app_ref; info->object = object; + /* This API call is only used by the native VOL connector, which is + * not asynchronous. + */ + info->is_future = FALSE; + info->realize_cb = NULL; + info->discard_cb = NULL; /* Insert into the type */ if (H5SL_insert(type_info->ids, info, &info->id) < 0) @@ -892,8 +958,7 @@ done: /*------------------------------------------------------------------------- * Function: H5I__dec_ref * - * Purpose: Decrements the number of references outstanding for an ID. - * This will fail if the type is not a reference counted type. + * Purpose: This will fail if the type is not a reference counted type. * The ID type's 'free' function will be called for the ID * if the reference count for the ID reaches 0 and a free * function has been defined at type creation time. @@ -1071,6 +1136,41 @@ done: } /* end H5I_dec_app_ref() */ /*------------------------------------------------------------------------- + * Function: H5I_dec_app_ref_async + * + * Purpose: Asynchronous wrapper for case of modifying the application ref. + * count for an ID as well as normal reference count. + * + * Note: Allows for asynchronous 'close' operation on object, with + * token != H5_REQUEST_NULL. + * + * Return: Success: New app. reference count + * Failure: -1 + * + * Programmer: Houjun Tang + * Oct 21, 2019 + * + *------------------------------------------------------------------------- + */ +int +H5I_dec_app_ref_async(hid_t id, void **token) +{ + int ret_value = 0; /* Return value */ + + FUNC_ENTER_NOAPI((-1)) + + /* Sanity check */ + HDassert(id >= 0); + + /* [Possibly] aynchronously decrement refcount on ID */ + if ((ret_value = H5I__dec_app_ref(id, token)) < 0) + HGOTO_ERROR(H5E_ID, H5E_CANTDEC, (-1), "can't asynchronously decrement ID ref count") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5I_dec_app_ref_async() */ + +/*------------------------------------------------------------------------- * Function: H5I__dec_app_ref_always_close * * Purpose: Wrapper for case of always closing the ID, even when the free @@ -1144,6 +1244,38 @@ done: } /* end H5I_dec_app_ref_always_close() */ /*------------------------------------------------------------------------- + * Function: H5I_dec_app_ref_always_close_async + * + * Purpose: Asynchronous wrapper for case of always closing the ID, even + * when the free routine fails + * + * Note: Allows for asynchronous 'close' operation on object, with + * token != H5_REQUEST_NULL. + * + * Return: Success: New app. reference count + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +int +H5I_dec_app_ref_always_close_async(hid_t id, void **token) +{ + int ret_value = 0; /* Return value */ + + FUNC_ENTER_NOAPI((-1)) + + /* Sanity check */ + HDassert(id >= 0); + + /* [Possibly] aynchronously decrement refcount on ID */ + if ((ret_value = H5I__dec_app_ref_always_close(id, token)) < 0) + HGOTO_ERROR(H5E_ID, H5E_CANTDEC, (-1), "can't asynchronously decrement ID ref count") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5I_dec_app_ref_always_close_async() */ + +/*------------------------------------------------------------------------- * Function: H5I_inc_ref * * Purpose: Increment the reference count for an object. @@ -1455,6 +1587,7 @@ H5I__find_id(hid_t id) { H5I_type_t type; /* ID's type */ H5I_type_info_t *type_info = NULL; /* Pointer to the type */ + H5I_id_info_t * id_info = NULL; /* ID's info */ H5I_id_info_t * ret_value = NULL; /* Return value */ FUNC_ENTER_PACKAGE_NOERR @@ -1469,15 +1602,53 @@ H5I__find_id(hid_t id) /* Check for same ID as we have looked up last time */ if (type_info->last_id_info && type_info->last_id_info->id == id) - ret_value = type_info->last_id_info; + id_info = type_info->last_id_info; else { /* Locate the ID node for the ID */ - ret_value = (H5I_id_info_t *)H5SL_search(type_info->ids, &id); + id_info = (H5I_id_info_t *)H5SL_search(type_info->ids, &id); /* Remember this ID */ - type_info->last_id_info = ret_value; + type_info->last_id_info = id_info; } + /* Check if this is a future ID */ + H5_GCC_DIAG_OFF("cast-qual") + if (id_info && id_info->is_future) { + hid_t actual_id = H5I_INVALID_HID; /* ID for actual object */ + void *future_object; /* Pointer to the future object */ + void *actual_object; /* Pointer to the actual object */ + + /* Invoke the realize callback, to get the actual object */ + if ((id_info->realize_cb)((void *)id_info->object, &actual_id) < 0) + HGOTO_DONE(NULL) + + /* Verify that we received a valid ID, of the same type */ + if (H5I_INVALID_HID == actual_id) + HGOTO_DONE(NULL) + if (H5I_TYPE(id) != H5I_TYPE(actual_id)) + HGOTO_DONE(NULL) + + /* Swap the actual object in for the future object */ + future_object = (void *)id_info->object; + actual_object = H5I__remove_common(type_info, actual_id); + HDassert(actual_object); + id_info->object = actual_object; + + /* Discard the future object */ + if ((id_info->discard_cb)(future_object) < 0) + HGOTO_DONE(NULL) + future_object = NULL; + + /* Change the ID from 'future' to 'actual' */ + id_info->is_future = FALSE; + id_info->realize_cb = NULL; + id_info->discard_cb = NULL; + } + H5_GCC_DIAG_ON("cast-qual") + + /* Set return value */ + ret_value = id_info; + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5I__find_id() */ diff --git a/src/H5Ipkg.h b/src/H5Ipkg.h index 5d9af13..b6e3da3 100644 --- a/src/H5Ipkg.h +++ b/src/H5Ipkg.h @@ -67,6 +67,11 @@ typedef struct H5I_id_info_t { unsigned count; /* Ref. count for this ID */ unsigned app_count; /* Ref. count of application visible IDs */ const void *object; /* Pointer associated with the ID */ + + /* Future ID info */ + hbool_t is_future; /* Whether this ID represents a future object */ + H5I_future_realize_func_t realize_cb; /* 'realize' callback for future object */ + H5I_future_discard_func_t discard_cb; /* 'discard' callback for future object */ } H5I_id_info_t; /* Type information structure used */ @@ -98,10 +103,12 @@ H5_DLLVAR int H5I_next_type_g; /* Package Private Prototypes */ /******************************/ -H5_DLL int H5I__destroy_type(H5I_type_t type); -H5_DLL void * H5I__remove_verify(hid_t id, H5I_type_t type); -H5_DLL int H5I__inc_type_ref(H5I_type_t type); -H5_DLL int H5I__get_type_ref(H5I_type_t type); +H5_DLL hid_t H5I__register(H5I_type_t type, const void *object, hbool_t app_ref, + H5I_future_realize_func_t realize_cb, H5I_future_discard_func_t discard_cb); +H5_DLL int H5I__destroy_type(H5I_type_t type); +H5_DLL void *H5I__remove_verify(hid_t id, H5I_type_t type); +H5_DLL int H5I__inc_type_ref(H5I_type_t type); +H5_DLL int H5I__get_type_ref(H5I_type_t type); H5_DLL H5I_id_info_t *H5I__find_id(hid_t id); /* Testing functions */ diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h index d8d80f9..6395275 100644 --- a/src/H5Iprivate.h +++ b/src/H5Iprivate.h @@ -70,7 +70,9 @@ H5_DLL int H5I_get_ref(hid_t id, hbool_t app_ref); H5_DLL int H5I_inc_ref(hid_t id, hbool_t app_ref); H5_DLL int H5I_dec_ref(hid_t id); H5_DLL int H5I_dec_app_ref(hid_t id); +H5_DLL int H5I_dec_app_ref_async(hid_t id, void **token); H5_DLL int H5I_dec_app_ref_always_close(hid_t id); +H5_DLL int H5I_dec_app_ref_always_close_async(hid_t id, void **token); H5_DLL int H5I_dec_type_ref(H5I_type_t type); H5_DLL herr_t H5I_find_id(const void *object, H5I_type_t type, hid_t *id /*out*/); diff --git a/src/H5Ipublic.h b/src/H5Ipublic.h index 3912252..0075018 100644 --- a/src/H5Ipublic.h +++ b/src/H5Ipublic.h @@ -50,6 +50,7 @@ typedef enum H5I_type_t { H5I_ERROR_MSG, /**< type ID for error messages */ H5I_ERROR_STACK, /**< type ID for error stacks */ H5I_SPACE_SEL_ITER, /**< type ID for dataspace selection iterator */ + H5I_EVENTSET, /**< type ID for event sets */ H5I_NTYPES /**< number of library types, MUST BE LAST! */ } H5I_type_t; @@ -96,6 +97,20 @@ typedef int (*H5I_search_func_t)(void *obj, hid_t id, void *key); typedef herr_t (*H5I_iterate_func_t)(hid_t id, void *udata); //! [H5I_iterate_func_t_snip] +/** + * The type of the realize_cb callback for H5Iregister_future + */ +//! [H5I_future_realize_func_t_snip] +typedef herr_t (*H5I_future_realize_func_t)(void *future_object, hid_t *actual_object_id); +//! [H5I_future_realize_func_t_snip] + +/** + * The type of the discard_cb callback for H5Iregister_future + */ +//! [H5I_future_discard_func_t_snip] +typedef herr_t (*H5I_future_discard_func_t)(void *future_object); +//! [H5I_future_discard_func_t_snip] + #ifdef __cplusplus extern "C" { #endif @@ -112,7 +127,7 @@ extern "C" { * * \return \hid_t{object} * - * \details H5Iregister() allocates and returns a new ID for an object. + * \details H5Iregister() creates and returns a new ID for an object. * * \details The \p type parameter is the identifier for the ID type to which * this new ID will belong. This identifier must have been created by @@ -127,6 +142,82 @@ H5_DLL hid_t H5Iregister(H5I_type_t type, const void *object); /** * \ingroup H5I * + * \brief Registers a "future" object under a type and returns an ID for it + * + * \param[in] type The identifier of the type of the new ID + * \param[in] object Pointer to "future" object for which a new ID is created + * \param[in] realize_cb Function pointer to realize a future object + * \param[in] discard_cb Function pointer to destroy a future object + * + * \return \hid_t{object} + * + * \details H5Iregister_future() creates and returns a new ID for a "future" object. + * Future objects are a special kind of object and represent a + * placeholder for an object that has not yet been created or opened. + * The \p realize_cb will be invoked by the HDF5 library to 'realize' + * the future object as an actual object. A call to H5Iobject_verify() + * will invoke the \p realize_cb callback and if it successfully + * returns, will return the actual object, not the future object. + * + * \details The \p type parameter is the identifier for the ID type to which + * this new future ID will belong. This identifier may have been created + * by a call to H5Iregister_type() or may be one of the HDF5 pre-defined + * ID classes (e.g. H5I_FILE, H5I_GROUP, H5I_DATASPACE, etc). + * + * \details The \p object parameter is a pointer to the memory which the new ID + * will be a reference to. This pointer will be stored by the library, + * but will not be returned to a call to H5Iobject_verify() until the + * \p realize_cb callback has returned the actual pointer for the object. + * + * A NULL value for \p object is allowed. + * + * \details The \p realize_cb parameter is a function pointer that will be + * invoked by the HDF5 library to convert a future object into an + * actual object. The \realize_cb function may be invoked by + * H5Iobject_verify() to return the actual object for a user-defined + * ID class (i.e. an ID class registered with H5Iregister_type()) or + * internally by the HDF5 library in order to use or get information + * from an HDF5 pre-defined ID type. For example, the \p realize_cb + * for a future dataspace object will be called during the process + * of returning information from H5Sget_simple_extent_dims(). + * + * Note that although the \p realize_cb routine returns + * an ID (as a parameter) for the actual object, the HDF5 library + * will swap the actual object in that ID for the future object in + * the future ID. This ensures that the ID value for the object + * doesn't change for the user when the object is realized. + * + * Note that the \p realize_cb callback could receive a NULL value + * for a future object pointer, if one was used when H5Iregister_future() + * was initially called. This is permitted as a means of allowing + * the \p realize_cb to act as a generator of new objects, without + * requiring creation of unnecessary future objects. + * + * It is an error to pass NULL for \p realize_cb. + * + * \details The \p discard_cb parameter is a function pointer that will be + * invoked by the HDF5 library to destroy a future object. This + * callback will always be invoked for _every_ future object, whether + * the \p realize_cb is invoked on it or not. It's possible that + * the \p discard_cb is invoked on a future object without the + * \p realize_cb being invoked, e.g. when a future ID is closed without + * requiring the future object to be realized into an actual one. + * + * Note that the \p discard_cb callback could receive a NULL value + * for a future object pointer, if one was used when H5Iregister_future() + * was initially called. + * + * It is an error to pass NULL for \p discard_cb. + * + * \note The H5Iregister_future() function is primarily targeted at VOL connector + * authors and is _not_ designed for general-purpose application use. + * + */ +H5_DLL hid_t H5Iregister_future(H5I_type_t type, const void *object, H5I_future_realize_func_t realize_cb, + H5I_future_discard_func_t discard_cb); +/** + * \ingroup H5I + * * \brief Returns the object referenced by an ID * * \param[in] id ID to be dereferenced @@ -25,6 +25,7 @@ #include "H5CXprivate.h" /* API Contexts */ #include "H5Dprivate.h" /* Datasets */ #include "H5Eprivate.h" /* Error handling */ +#include "H5ESprivate.h" /* Event Sets */ #include "H5Fprivate.h" /* File access */ #include "H5Gprivate.h" /* Groups */ #include "H5Iprivate.h" /* IDs */ @@ -82,7 +83,7 @@ typedef struct { char *sep; /* Pointer to next separator in the string */ /* Up */ - hbool_t exists; /* Whether the link exists or not */ + hbool_t *exists; /* Whether the link exists or not */ } H5L_trav_le_t; /* User data for path traversal routine for getting link value */ @@ -129,6 +130,22 @@ static herr_t H5L__get_info_by_idx_cb(H5G_loc_t *grp_loc /*in*/, const char *nam static herr_t H5L__get_name_by_idx_cb(H5G_loc_t *grp_loc /*in*/, const char *name, const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata /*in,out*/, H5G_own_loc_t *own_loc /*out*/); +static herr_t H5L__create_soft_api_common(const char *link_target, hid_t link_loc_id, const char *link_name, + hid_t lcpl_id, hid_t lapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static herr_t H5L__create_hard_api_common(hid_t cur_loc_id, const char *cur_name, hid_t new_loc_id, + const char *new_name, hid_t lcpl_id, hid_t lapl_id, + void **token_ptr, H5VL_object_t **_vol_obj_ptr); +static herr_t H5L__delete_api_common(hid_t loc_id, const char *name, hid_t lapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static herr_t H5L__delete_by_idx_api_common(hid_t loc_id, const char *group_name, H5_index_t idx_type, + H5_iter_order_t order, hsize_t n, hid_t lapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static herr_t H5L__exists_api_common(hid_t loc_id, const char *name, hbool_t *exists, hid_t lapl_id, + void **token_ptr, H5VL_object_t **_vol_obj_ptr); +static herr_t H5L__iterate_api_common(hid_t group_id, H5_index_t idx_type, H5_iter_order_t order, + hsize_t *idx_p, H5L_iterate2_t op, void *op_data, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); /*********************/ /* Package Variables */ @@ -422,33 +439,25 @@ done: } /* end H5Lcopy() */ /*------------------------------------------------------------------------- - * Function: H5Lcreate_soft + * Function: H5L__create_soft_api_common * - * Purpose: Creates a soft link from LINK_NAME to LINK_TARGET. - * - * LINK_TARGET can be anything and is interpreted at lookup - * time relative to the group which contains the final component - * of LINK_NAME. For instance, if LINK_TARGET is `./foo' and - * LINK_NAME is `./x/y/bar' and a request is made for `./x/y/bar' - * then the actual object looked up is `./x/y/./foo'. + * Purpose: This is the common function for creating a soft link * * Return: Non-negative on success/Negative on failure * - * Programmer: Robb Matzke - * Monday, April 6, 1998 - * *------------------------------------------------------------------------- */ -herr_t -H5Lcreate_soft(const char *link_target, hid_t link_loc_id, const char *link_name, hid_t lcpl_id, - hid_t lapl_id) +static herr_t +H5L__create_soft_api_common(const char *link_target, hid_t link_loc_id, const char *link_name, hid_t lcpl_id, + hid_t lapl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr) { - H5VL_object_t * vol_obj = NULL; /* object of loc_id */ - H5VL_loc_params_t loc_params; - herr_t ret_value = SUCCEED; /* Return value */ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API(FAIL) - H5TRACE5("e", "*si*sii", link_target, link_loc_id, link_name, lcpl_id, lapl_id); + FUNC_ENTER_STATIC /* Check arguments */ if (link_loc_id == H5L_SAME_LOC) @@ -457,10 +466,6 @@ H5Lcreate_soft(const char *link_target, hid_t link_loc_id, const char *link_name HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "link_target parameter cannot be NULL") if (!*link_target) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "link_target parameter cannot be an empty string") - if (!link_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "link_name parameter cannot be NULL") - if (!*link_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "link_name parameter cannot be an empty string") if (lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list") @@ -471,37 +476,31 @@ H5Lcreate_soft(const char *link_target, hid_t link_loc_id, const char *link_name /* Set the LCPL for the API context */ H5CX_set_lcpl(lcpl_id); - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, link_loc_id, TRUE) < 0) - HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info") - - /* Set location fields */ - loc_params.type = H5VL_OBJECT_BY_NAME; - loc_params.loc_data.loc_by_name.name = link_name; - loc_params.loc_data.loc_by_name.lapl_id = lapl_id; - loc_params.obj_type = H5I_get_type(link_loc_id); - - /* get the location object */ - if (NULL == (vol_obj = (H5VL_object_t *)H5VL_vol_object(link_loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") + /* link_name is verified in H5VL_setup_name_args() */ + /* Set up object access arguments */ + if (H5VL_setup_name_args(link_loc_id, link_name, H5P_CLS_LACC, TRUE, lapl_id, vol_obj_ptr, &loc_params) < + 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set object access arguments") /* Create the link */ - if (H5VL_link_create(H5VL_LINK_CREATE_SOFT, vol_obj, &loc_params, lcpl_id, lapl_id, - H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, link_target) < 0) + if (H5VL_link_create(H5VL_LINK_CREATE_SOFT, *vol_obj_ptr, &loc_params, lcpl_id, lapl_id, + H5P_DATASET_XFER_DEFAULT, token_ptr, link_target) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTCREATE, FAIL, "unable to create soft link") done: - FUNC_LEAVE_API(ret_value) -} /* end H5Lcreate_soft() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* H5L__create_soft_api_common() */ /*------------------------------------------------------------------------- - * Function: H5Lcreate_hard + * Function: H5Lcreate_soft * - * Purpose: Creates a hard link from NEW_NAME to CUR_NAME. + * Purpose: Creates a soft link from LINK_NAME to LINK_TARGET. * - * CUR_NAME must name an existing object. CUR_NAME and - * NEW_NAME are interpreted relative to CUR_LOC_ID and - * NEW_LOC_ID, which are either file IDs or group IDs. + * LINK_TARGET can be anything and is interpreted at lookup + * time relative to the group which contains the final component + * of LINK_NAME. For instance, if LINK_TARGET is `./foo' and + * LINK_NAME is `./x/y/bar' and a request is made for `./x/y/bar' + * then the actual object looked up is `./x/y/./foo'. * * Return: Non-negative on success/Negative on failure * @@ -511,18 +510,88 @@ done: *------------------------------------------------------------------------- */ herr_t -H5Lcreate_hard(hid_t cur_loc_id, const char *cur_name, hid_t new_loc_id, const char *new_name, hid_t lcpl_id, +H5Lcreate_soft(const char *link_target, hid_t link_loc_id, const char *link_name, hid_t lcpl_id, hid_t lapl_id) { - H5VL_object_t * vol_obj1 = NULL; /* Object of cur_loc_id */ - H5VL_object_t * vol_obj2 = NULL; /* Object of new_loc_id */ - H5VL_object_t tmp_vol_obj; /* Temporary object */ - H5VL_loc_params_t loc_params1; - H5VL_loc_params_t loc_params2; - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) - H5TRACE6("e", "i*si*sii", cur_loc_id, cur_name, new_loc_id, new_name, lcpl_id, lapl_id); + H5TRACE5("e", "*si*sii", link_target, link_loc_id, link_name, lcpl_id, lapl_id); + + /* Creates a soft link synchronously */ + if (H5L__create_soft_api_common(link_target, link_loc_id, link_name, lcpl_id, lapl_id, NULL, NULL) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTCREATE, FAIL, "unable to synchronously create soft link") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Lcreate_soft() */ + +/*------------------------------------------------------------------------- + * Function: H5Lcreate_soft_async + * + * Purpose: Asynchronous version of H5Lcreate_soft + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Lcreate_soft_async(const char *app_file, const char *app_func, unsigned app_line, const char *link_target, + hid_t link_loc_id, const char *link_name, hid_t lcpl_id, hid_t lapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE9("e", "*s*sIu*si*siii", app_file, app_func, app_line, link_target, link_loc_id, link_name, + lcpl_id, lapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Creates a soft link asynchronously */ + if (H5L__create_soft_api_common(link_target, link_loc_id, link_name, lcpl_id, lapl_id, token_ptr, + &vol_obj) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTCREATE, FAIL, "unable to asynchronously create soft link") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE9(FUNC, "*s*sIu*si*siii", app_file, app_func, app_line, link_target, + link_loc_id, link_name, lcpl_id, lapl_id, es_id)) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Lcreate_soft_async() */ + +/*------------------------------------------------------------------------- + * Function: H5L__create_hard_api_common + * + * Purpose: This is the common function for creating a hard link + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5L__create_hard_api_common(hid_t cur_loc_id, const char *cur_name, hid_t new_loc_id, const char *new_name, + hid_t lcpl_id, hid_t lapl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * vol_obj1 = NULL; /* Object of cur_loc_id */ + H5VL_object_t * vol_obj2 = NULL; /* Object of new_loc_id */ + H5VL_object_t tmp_vol_obj; /* Temporary object */ + H5VL_object_t * tmp_vol_obj_ptr = &tmp_vol_obj; /* Ptr to temporary object */ + H5VL_object_t **tmp_vol_obj_ptr_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj_ptr); /* Ptr to ptr to temporary object */ + H5VL_loc_params_t loc_params1; /* Location parameters for cur_loc_id object access */ + H5VL_loc_params_t loc_params2; /* Location parameters for new_loc_id object access */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC /* Check arguments */ if (cur_loc_id == H5L_SAME_LOC && new_loc_id == H5L_SAME_LOC) @@ -576,20 +645,97 @@ H5Lcreate_hard(hid_t cur_loc_id, const char *cur_name, hid_t new_loc_id, const c "Objects are accessed through different VOL connectors and can't be linked") /* Construct a temporary VOL object */ - tmp_vol_obj.data = (vol_obj2 ? (vol_obj2->data) : NULL); - tmp_vol_obj.connector = (vol_obj1 != NULL ? vol_obj1->connector : vol_obj2->connector); + (*tmp_vol_obj_ptr_ptr)->data = (vol_obj2 ? (vol_obj2->data) : NULL); + (*tmp_vol_obj_ptr_ptr)->connector = (vol_obj1 != NULL ? vol_obj1->connector : vol_obj2->connector); /* Create the link */ - if (H5VL_link_create(H5VL_LINK_CREATE_HARD, &tmp_vol_obj, &loc_params2, lcpl_id, lapl_id, - H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, (vol_obj1 ? vol_obj1->data : NULL), + if (H5VL_link_create(H5VL_LINK_CREATE_HARD, *tmp_vol_obj_ptr_ptr, &loc_params2, lcpl_id, lapl_id, + H5P_DATASET_XFER_DEFAULT, token_ptr, (vol_obj1 ? vol_obj1->data : NULL), &loc_params1) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTCREATE, FAIL, "unable to create hard link") done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5L__create_hard_api_common() */ + +/*------------------------------------------------------------------------- + * Function: H5Lcreate_hard + * + * Purpose: Creates a hard link from NEW_NAME to CUR_NAME. + * + * CUR_NAME must name an existing object. CUR_NAME and + * NEW_NAME are interpreted relative to CUR_LOC_ID and + * NEW_LOC_ID, which are either file IDs or group IDs. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Monday, April 6, 1998 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Lcreate_hard(hid_t cur_loc_id, const char *cur_name, hid_t new_loc_id, const char *new_name, hid_t lcpl_id, + hid_t lapl_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE6("e", "i*si*sii", cur_loc_id, cur_name, new_loc_id, new_name, lcpl_id, lapl_id); + + /* Creates a hard link synchronously */ + if (H5L__create_hard_api_common(cur_loc_id, cur_name, new_loc_id, new_name, lcpl_id, lapl_id, NULL, + NULL) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTCREATE, FAIL, "unable to synchronously create hard link") + +done: FUNC_LEAVE_API(ret_value) } /* end H5Lcreate_hard() */ /*------------------------------------------------------------------------- + * Function: H5Lcreate_hard_async + * + * Purpose: Asynchronous version of H5Lcreate_hard + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Lcreate_hard_async(const char *app_file, const char *app_func, unsigned app_line, hid_t cur_loc_id, + const char *cur_name, hid_t new_loc_id, const char *new_name, hid_t lcpl_id, + hid_t lapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE10("e", "*s*sIui*si*siii", app_file, app_func, app_line, cur_loc_id, cur_name, new_loc_id, + new_name, lcpl_id, lapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Creates a hard link asynchronously */ + if (H5L__create_hard_api_common(cur_loc_id, cur_name, new_loc_id, new_name, lcpl_id, lapl_id, token_ptr, + &vol_obj) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTCREATE, FAIL, "unable to asynchronously create hard link") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE10(FUNC, "*s*sIui*si*siii", app_file, app_func, app_line, cur_loc_id, + cur_name, new_loc_id, new_name, lcpl_id, lapl_id, es_id)) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Lcreate_hard_async() */ + +/*------------------------------------------------------------------------- * Function: H5Lcreate_external * * Purpose: Creates an external link from LINK_NAME to OBJ_NAME. @@ -759,6 +905,43 @@ done: } /* end H5Lcreate_ud() */ /*------------------------------------------------------------------------- + * Function: H5L__delete_api_common + * + * Purpose: This is the common function for deleting a link + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5L__delete_api_common(hid_t loc_id, const char *name, hid_t lapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check arguments */ + /* name is verified in H5VL_setup_name_args() */ + + /* Set up object access arguments */ + if (H5VL_setup_name_args(loc_id, name, H5P_CLS_LACC, TRUE, lapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set object access arguments") + + /* Unlink */ + if (H5VL_link_specific(*vol_obj_ptr, &loc_params, H5VL_LINK_DELETE, H5P_DATASET_XFER_DEFAULT, token_ptr) < + 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to delete link") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5L__delete_api_common() */ + +/*------------------------------------------------------------------------- * Function: H5Ldelete * * Purpose: Removes the specified NAME from the group graph and @@ -778,39 +961,103 @@ done: herr_t H5Ldelete(hid_t loc_id, const char *name, hid_t lapl_id) { - H5VL_object_t * vol_obj = NULL; /* Object of loc_id */ - H5VL_loc_params_t loc_params; - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE3("e", "i*si", loc_id, name, lapl_id); - /* Check arguments */ - if (!name || !*name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + /* Delete a link synchronously */ + if (H5L__delete_api_common(loc_id, name, lapl_id, NULL, NULL) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to synchronously delete link") - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, TRUE) < 0) - HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info") +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Ldelete() */ - /* Fill in the location struct fields */ - loc_params.type = H5VL_OBJECT_BY_NAME; - loc_params.obj_type = H5I_get_type(loc_id); - loc_params.loc_data.loc_by_name.name = name; - loc_params.loc_data.loc_by_name.lapl_id = lapl_id; +/*------------------------------------------------------------------------- + * Function: H5Ldelete_async + * + * Purpose: Asynchronous version of H5Ldelete + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Ldelete_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, const char *name, + hid_t lapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ - /* get the location object */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") + FUNC_ENTER_API(FAIL) + H5TRACE7("e", "*s*sIui*sii", app_file, app_func, app_line, loc_id, name, lapl_id, es_id); - /* Unlink */ - if (H5VL_link_specific(vol_obj, &loc_params, H5VL_LINK_DELETE, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL) < 0) - HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to delete link") + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Delete a link asynchronously */ + if (H5L__delete_api_common(loc_id, name, lapl_id, token_ptr, &vol_obj) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to asynchronously delete link") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE7(FUNC, "*s*sIui*sii", app_file, app_func, app_line, loc_id, name, lapl_id, + es_id)) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTINSERT, FAIL, "can't insert token into event set") done: FUNC_LEAVE_API(ret_value) -} /* end H5Ldelete() */ +} /* H5Ldelete_async() */ + +/*------------------------------------------------------------------------- + * Function: H5L__delete_by_idx_api_common + * + * Purpose: This is the common function for deleting a link + * according to the order within an index. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5L__delete_by_idx_api_common(hid_t loc_id, const char *group_name, H5_index_t idx_type, + H5_iter_order_t order, hsize_t n, hid_t lapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check arguments */ + if (!group_name || !*group_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified") + 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") + + /* Set up object access arguments */ + if (H5VL_setup_idx_args(loc_id, group_name, idx_type, order, n, H5P_CLS_LACC, TRUE, lapl_id, vol_obj_ptr, + &loc_params) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set object access arguments") + + /* Delete the link */ + if (H5VL_link_specific(*vol_obj_ptr, &loc_params, H5VL_LINK_DELETE, H5P_DATASET_XFER_DEFAULT, token_ptr) < + 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to delete link") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5L__delete_by_idx_api_common() */ /*------------------------------------------------------------------------- * Function: H5Ldelete_by_idx @@ -835,45 +1082,61 @@ herr_t H5Ldelete_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t lapl_id) { - H5VL_object_t * vol_obj = NULL; /* object of loc_id */ - H5VL_loc_params_t loc_params; - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE6("e", "i*sIiIohi", loc_id, group_name, idx_type, order, n, lapl_id); - /* Check arguments */ - if (!group_name || !*group_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified") - 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") + /* Delete a link synchronously */ + if (H5L__delete_by_idx_api_common(loc_id, group_name, idx_type, order, n, lapl_id, NULL, NULL) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to synchronously delete link") - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, TRUE) < 0) - HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info") +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Ldelete_by_idx() */ - loc_params.type = H5VL_OBJECT_BY_IDX; - loc_params.loc_data.loc_by_idx.name = group_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); +/*------------------------------------------------------------------------- + * Function: H5Ldelete_by_idx_async + * + * Purpose: Asynchronous version of H5Ldelete_by_idx + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Ldelete_by_idx_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *group_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, + hid_t lapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ - /* Get the location object */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") + FUNC_ENTER_API(FAIL) + H5TRACE10("e", "*s*sIui*sIiIohii", app_file, app_func, app_line, loc_id, group_name, idx_type, order, n, + lapl_id, es_id); - /* Delete the link */ - if (H5VL_link_specific(vol_obj, &loc_params, H5VL_LINK_DELETE, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL) < 0) - HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to delete link") + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Delete a link asynchronously */ + if (H5L__delete_by_idx_api_common(loc_id, group_name, idx_type, order, n, lapl_id, token_ptr, &vol_obj) < + 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to asynchronously delete link") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE10(FUNC, "*s*sIui*sIiIohii", app_file, app_func, app_line, loc_id, + group_name, idx_type, order, n, lapl_id, es_id)) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTINSERT, FAIL, "can't insert token into event set") done: FUNC_LEAVE_API(ret_value) -} /* end H5Ldelete_by_idx() */ +} /* H5Ldelete_by_idx_async() */ /*------------------------------------------------------------------------- * Function: H5Lget_val @@ -992,6 +1255,45 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Lget_val_by_idx() */ +/*-------------------------------------------------------------------------- + * NAME + * H5L__exists_api_common + * PURPOSE + * Common helper routine for sync/async check if an attribute exists + * RETURNS + * Non-negative on success/Negative on failure + * + *--------------------------------------------------------------------------*/ +static herr_t +H5L__exists_api_common(hid_t loc_id, const char *name, hbool_t *exists, hid_t lapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check arguments */ + /* name is verified in H5VL_setup_name_args() */ + if (NULL == exists) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid pointer for link existence") + + /* Set up object access arguments */ + if (H5VL_setup_name_args(loc_id, name, H5P_CLS_LACC, FALSE, lapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set object access arguments") + + /* Check for the existence of the link */ + if (H5VL_link_specific(*vol_obj_ptr, &loc_params, H5VL_LINK_EXISTS, H5P_DATASET_XFER_DEFAULT, token_ptr, + exists) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to get link info") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5L__exists_api_common() */ + /*------------------------------------------------------------------------- * Function: H5Lexists * @@ -1007,41 +1309,62 @@ done: htri_t H5Lexists(hid_t loc_id, const char *name, hid_t lapl_id) { - H5VL_object_t * vol_obj = NULL; /* object of loc_id */ - H5VL_loc_params_t loc_params; - htri_t ret_value = FAIL; /* Return value */ + hbool_t exists; /* Flag to indicate if link exists */ + htri_t ret_value = FAIL; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE3("t", "i*si", loc_id, name, lapl_id); - /* Check arguments */ - 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") + /* Synchronously check if a link exists */ + exists = FALSE; + if (H5L__exists_api_common(loc_id, name, &exists, lapl_id, NULL, NULL) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to synchronously check link existence") - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0) - HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info") + /* Set return value */ + ret_value = (htri_t)exists; - /* Set location struct fields */ - loc_params.type = H5VL_OBJECT_BY_NAME; - loc_params.obj_type = H5I_get_type(loc_id); - loc_params.loc_data.loc_by_name.name = name; - loc_params.loc_data.loc_by_name.lapl_id = lapl_id; +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Lexists() */ - /* Get the location object */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") +/*-------------------------------------------------------------------------- + * Function: H5Lexists_async + * + * Purpose: Asynchronous version of H5Lexists + * + * Return: Success: TRUE/FALSE/FAIL + * + *--------------------------------------------------------------------------*/ +herr_t +H5Lexists_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, const char *name, + hbool_t *exists, hid_t lapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ - /* Check for the existence of the link */ - if (H5VL_link_specific(vol_obj, &loc_params, H5VL_LINK_EXISTS, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, - &ret_value) < 0) - HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to get link info") + FUNC_ENTER_API(FAIL) + H5TRACE8("e", "*s*sIui*s*bii", app_file, app_func, app_line, loc_id, name, exists, lapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Asynchronously check if a link exists */ + if (H5L__exists_api_common(loc_id, name, exists, lapl_id, token_ptr, &vol_obj) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to asynchronously check link existence") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE8(FUNC, "*s*sIui*s*bii", app_file, app_func, app_line, loc_id, name, + exists, lapl_id, es_id)) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTINSERT, FAIL, "can't insert token into event set") done: FUNC_LEAVE_API(ret_value) -} /* end H5Lexists() */ +} /* H5Lexists_async() */ /*------------------------------------------------------------------------- * Function: H5Lget_info2 @@ -1349,6 +1672,53 @@ done: } /* end H5Lget_name_by_idx() */ /*------------------------------------------------------------------------- + * Function: H5L__iterate_api_common + * + * Purpose: This is the common function for iterating over links + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5L__iterate_api_common(hid_t group_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx_p, + H5L_iterate2_t op, void *op_data, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + H5I_type_t id_type; /* Type of ID */ + herr_t ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check arguments */ + id_type = H5I_get_type(group_id); + if (!(H5I_GROUP == id_type || H5I_FILE == id_type)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument") + 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") + if (!op) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no operator specified") + + /* Set up object access arguments */ + if (H5VL_setup_self_args(group_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set object access arguments") + + /* Iterate over the links */ + if ((ret_value = H5VL_link_specific(*vol_obj_ptr, &loc_params, H5VL_LINK_ITER, H5P_DATASET_XFER_DEFAULT, + token_ptr, (unsigned)FALSE, (int)idx_type, (int)order, idx_p, op, + op_data)) < 0) + HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "link iteration failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5L__iterate_api_common() */ + +/*------------------------------------------------------------------------- * Function: H5Literate2 * * Purpose: Iterates over links in a group, with user callback routine, @@ -1370,42 +1740,68 @@ herr_t H5Literate2(hid_t group_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx_p, H5L_iterate2_t op, void *op_data) { - H5VL_object_t * vol_obj = NULL; /* Object of loc_id */ - H5VL_loc_params_t loc_params; - H5I_type_t id_type; /* Type of ID */ - herr_t ret_value; /* Return value */ + herr_t ret_value; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE6("e", "iIiIo*hLI*x", group_id, idx_type, order, idx_p, op, op_data); - /* Check arguments */ - id_type = H5I_get_type(group_id); - if (!(H5I_GROUP == id_type || H5I_FILE == id_type)) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument") - 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") - if (!op) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no operator specified") + /* Iterate over links synchronously */ + if ((ret_value = H5L__iterate_api_common(group_id, idx_type, order, idx_p, op, op_data, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "asynchronous link iteration failed") - /* Get the location object */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(group_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Literate2() */ - /* Set location struct fields */ - loc_params.type = H5VL_OBJECT_BY_SELF; - loc_params.obj_type = H5I_get_type(group_id); +/*------------------------------------------------------------------------- + * Function: H5Literate_async + * + * Purpose: Asynchronous version of H5Literate2 + * + * Return: Success: The return value of the first operator that + * returns non-zero, or zero if all members were + * processed with no operator returning non-zero. + * + * Failure: Negative if something goes wrong within the + * library, or the negative value returned by one + * of the operators. + * + * + *------------------------------------------------------------------------- + */ +herr_t +H5Literate_async(const char *app_file, const char *app_func, unsigned app_line, hid_t group_id, + H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx_p, H5L_iterate2_t op, void *op_data, + hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value; /* Return value */ - /* Iterate over the links */ - if ((ret_value = H5VL_link_specific(vol_obj, &loc_params, H5VL_LINK_ITER, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL, (unsigned)FALSE, (int)idx_type, (int)order, idx_p, - op, op_data)) < 0) - HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "link iteration failed") + FUNC_ENTER_API(FAIL) + H5TRACE10("e", "*s*sIuiIiIo*hLI*xi", app_file, app_func, app_line, group_id, idx_type, order, idx_p, op, + op_data, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Iterate over links asynchronously */ + if ((ret_value = + H5L__iterate_api_common(group_id, idx_type, order, idx_p, op, op_data, token_ptr, &vol_obj)) < 0) + HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "asynchronous link iteration failed") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE10(FUNC, "*s*sIuiIiIo*hLI*xi", app_file, app_func, app_line, group_id, + idx_type, order, idx_p, op, op_data, es_id)) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTINSERT, FAIL, "can't insert token into event set") done: FUNC_LEAVE_API(ret_value) -} /* end H5Literate2() */ +} /* H5Literate_async() */ /*------------------------------------------------------------------------- * Function: H5Literate_by_name2 @@ -3094,7 +3490,7 @@ H5L__exists_final_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc /*in*/, const char H5_ATT FUNC_ENTER_STATIC_NOERR /* Check if the name in this group resolved to a valid link */ - udata->exists = (hbool_t)(lnk != NULL); + *udata->exists = (hbool_t)(lnk != NULL); /* Indicate that this callback didn't take ownership of the group * * location for the object */ @@ -3149,10 +3545,10 @@ H5L__exists_inter_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc /*in*/, const char H5_ATT HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't determine if link exists") } /* end if */ else - udata->exists = TRUE; + *udata->exists = TRUE; } /* end if */ else - udata->exists = FALSE; + *udata->exists = FALSE; /* Indicate that this callback didn't take ownership of the group * * location for the object */ @@ -3177,20 +3573,21 @@ done: * *------------------------------------------------------------------------- */ -htri_t -H5L_exists_tolerant(const H5G_loc_t *loc, const char *name) +herr_t +H5L_exists_tolerant(const H5G_loc_t *loc, const char *name, hbool_t *exists) { - H5L_trav_le_t udata; /* User data for traversal */ - H5G_traverse_t cb_func; /* Callback function for tranversal */ - char * name_copy = NULL; /* Duplicate of name */ - char * name_trav; /* Name to traverse */ - htri_t ret_value = FAIL; /* Return value */ + H5L_trav_le_t udata; /* User data for traversal */ + H5G_traverse_t cb_func; /* Callback function for tranversal */ + char * name_copy = NULL; /* Duplicate of name */ + char * name_trav; /* Name to traverse */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Sanity checks */ HDassert(loc); HDassert(name); + HDassert(exists); /* Copy the name and skip leading '/'s */ name_trav = name_copy = H5MM_strdup(name); @@ -3199,27 +3596,25 @@ H5L_exists_tolerant(const H5G_loc_t *loc, const char *name) /* A path of "/" will always exist in a file */ if ('\0' == *name_trav) - HGOTO_DONE(TRUE) - - /* Set up user data & correct callback */ - udata.exists = FALSE; - if (NULL == (udata.sep = HDstrchr(name_trav, '/'))) - cb_func = H5L__exists_final_cb; + *exists = TRUE; else { - /* Chew through adjacent separators, if present */ - do { - *udata.sep = '\0'; - udata.sep++; - } while ('/' == *udata.sep); - cb_func = H5L__exists_inter_cb; - } /* end else */ - - /* Traverse the group hierarchy to locate the link to check */ - if (H5G_traverse(loc, name_trav, H5G_TARGET_SLINK | H5G_TARGET_UDLINK, cb_func, &udata) < 0) - HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't determine if link exists") + /* Set up user data & correct callback */ + udata.exists = exists; + if (NULL == (udata.sep = HDstrchr(name_trav, '/'))) + cb_func = H5L__exists_final_cb; + else { + /* Chew through adjacent separators, if present */ + do { + *udata.sep = '\0'; + udata.sep++; + } while ('/' == *udata.sep); + cb_func = H5L__exists_inter_cb; + } /* end else */ - /* Set return value */ - ret_value = (htri_t)udata.exists; + /* Traverse the group hierarchy to locate the link to check */ + if (H5G_traverse(loc, name_trav, H5G_TARGET_SLINK | H5G_TARGET_UDLINK, cb_func, &udata) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't determine if link exists") + } done: /* Release duplicated string */ @@ -3236,36 +3631,35 @@ done: * Note: Same as H5L_exists_tolerant, except that missing links are reported * as failures * - * Return: Non-negative (TRUE/FALSE) on success/Negative on failure + * Return: Non-negative on success, with *exists set/Negative on failure * * Programmer: Quincey Koziol * Friday, March 16 2007 * *------------------------------------------------------------------------- */ -htri_t -H5L__exists(const H5G_loc_t *loc, const char *name) +herr_t +H5L__exists(const H5G_loc_t *loc, const char *name, hbool_t *exists) { - H5L_trav_le_t udata; /* User data for traversal */ - htri_t ret_value = FAIL; /* Return value */ + H5L_trav_le_t udata; /* User data for traversal */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity checks */ HDassert(loc); HDassert(name); + HDassert(exists); /* A path of "/" will always exist in a file */ if (0 == HDstrcmp(name, "/")) - HGOTO_DONE(TRUE) - - /* Traverse the group hierarchy to locate the object to get info about */ - udata.exists = FALSE; - if (H5G_traverse(loc, name, H5G_TARGET_SLINK | H5G_TARGET_UDLINK, H5L__exists_final_cb, &udata) < 0) - HGOTO_ERROR(H5E_LINK, H5E_EXISTS, FAIL, "path doesn't exist") - - /* Set return value */ - ret_value = (htri_t)udata.exists; + *exists = TRUE; + else { + /* Traverse the group hierarchy to locate the object to get info about */ + udata.exists = exists; + if (H5G_traverse(loc, name, H5G_TARGET_SLINK | H5G_TARGET_UDLINK, H5L__exists_final_cb, &udata) < 0) + HGOTO_ERROR(H5E_LINK, H5E_EXISTS, FAIL, "link doesn't exist") + } done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5Lexternal.c b/src/H5Lexternal.c index 1081c85..d60f996 100644 --- a/src/H5Lexternal.c +++ b/src/H5Lexternal.c @@ -251,8 +251,7 @@ done: if (ret_value < 0) { /* Close object if it's open and something failed */ if (ext_obj_id >= 0 && H5I_dec_ref(ext_obj_id) < 0) - HDONE_ERROR(H5E_ID, H5E_CANTRELEASE, H5I_INVALID_HID, - "unable to close ID for external object") + HDONE_ERROR(H5E_ID, H5E_CANTRELEASE, H5I_INVALID_HID, "unable to close ID for external object") } /* end if */ FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5Lpkg.h b/src/H5Lpkg.h index fe08ea4..6cbe087 100644 --- a/src/H5Lpkg.h +++ b/src/H5Lpkg.h @@ -59,7 +59,7 @@ H5_DLL herr_t H5L__create_soft(const char *target_path, const H5G_loc_t *cur_lo hid_t lcpl_id); H5_DLL herr_t H5L__create_ud(const H5G_loc_t *link_loc, const char *link_name, const void *ud_data, size_t ud_data_size, H5L_type_t type, hid_t lcpl_id); -H5_DLL htri_t H5L__exists(const H5G_loc_t *loc, const char *name); +H5_DLL herr_t H5L__exists(const H5G_loc_t *loc, const char *name, hbool_t *exists); H5_DLL herr_t H5L__get_info_by_idx(const H5G_loc_t *loc, const char *name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, H5L_info2_t *linfo /*out*/); H5_DLL ssize_t H5L__get_name_by_idx(const H5G_loc_t *loc, const char *group_name, H5_index_t idx_type, diff --git a/src/H5Lprivate.h b/src/H5Lprivate.h index 5bc8d35..ed7ef4b 100644 --- a/src/H5Lprivate.h +++ b/src/H5Lprivate.h @@ -114,7 +114,7 @@ H5_DLL herr_t H5L_init(void); H5_DLL herr_t H5L_link(const H5G_loc_t *new_loc, const char *new_name, H5G_loc_t *obj_loc, hid_t lcpl_id); H5_DLL herr_t H5L_link_object(const H5G_loc_t *new_loc, const char *new_name, H5O_obj_create_t *ocrt_info, hid_t lcpl_id); -H5_DLL htri_t H5L_exists_tolerant(const H5G_loc_t *loc, const char *name); +H5_DLL herr_t H5L_exists_tolerant(const H5G_loc_t *loc, const char *name, hbool_t *exists); H5_DLL herr_t H5L_get_info(const H5G_loc_t *loc, const char *name, H5L_info2_t *linkbuf /*out*/); H5_DLL herr_t H5L_register_external(void); H5_DLL herr_t H5L_iterate(H5G_loc_t *loc, const char *group_name, H5_index_t idx_type, H5_iter_order_t order, diff --git a/src/H5Lpublic.h b/src/H5Lpublic.h index e930a15..4154518 100644 --- a/src/H5Lpublic.h +++ b/src/H5Lpublic.h @@ -357,6 +357,9 @@ H5_DLL herr_t H5Lcopy(hid_t src_loc, const char *src_name, hid_t dst_loc, const */ H5_DLL herr_t H5Lcreate_hard(hid_t cur_loc, const char *cur_name, hid_t dst_loc, const char *dst_name, hid_t lcpl_id, hid_t lapl_id); +H5_DLL herr_t H5Lcreate_hard_async(const char *app_file, const char *app_func, unsigned app_line, + hid_t cur_loc_id, const char *cur_name, hid_t new_loc_id, + const char *new_name, hid_t lcpl_id, hid_t lapl_id, hid_t es_id); /** * \ingroup H5L * @@ -423,6 +426,9 @@ H5_DLL herr_t H5Lcreate_hard(hid_t cur_loc, const char *cur_name, hid_t dst_loc, */ H5_DLL herr_t H5Lcreate_soft(const char *link_target, hid_t link_loc_id, const char *link_name, hid_t lcpl_id, hid_t lapl_id); +H5_DLL herr_t H5Lcreate_soft_async(const char *app_file, const char *app_func, unsigned app_line, + const char *link_target, hid_t link_loc_id, const char *link_name, + hid_t lcpl_id, hid_t lapl_id, hid_t es_id); /** * \ingroup H5L * @@ -462,6 +468,8 @@ H5_DLL herr_t H5Lcreate_soft(const char *link_target, hid_t link_loc_id, const c * */ H5_DLL herr_t H5Ldelete(hid_t loc_id, const char *name, hid_t lapl_id); +H5_DLL herr_t H5Ldelete_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *name, hid_t lapl_id, hid_t es_id); /** * \ingroup H5L * @@ -492,6 +500,9 @@ H5_DLL herr_t H5Ldelete(hid_t loc_id, const char *name, hid_t lapl_id); */ H5_DLL herr_t H5Ldelete_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t lapl_id); +H5_DLL herr_t H5Ldelete_by_idx_async(const char *app_file, const char *app_func, unsigned app_line, + hid_t loc_id, const char *group_name, H5_index_t idx_type, + H5_iter_order_t order, hsize_t n, hid_t lapl_id, hid_t es_id); /** * \ingroup H5L * @@ -696,6 +707,8 @@ H5_DLL herr_t H5Lget_val_by_idx(hid_t loc_id, const char *group_name, H5_index_t * */ H5_DLL htri_t H5Lexists(hid_t loc_id, const char *name, hid_t lapl_id); +H5_DLL herr_t H5Lexists_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *name, hbool_t *exists, hid_t lapl_id, hid_t es_id); /** * \ingroup H5L * @@ -944,6 +957,9 @@ H5_DLL ssize_t H5Lget_name_by_idx(hid_t loc_id, const char *group_name, H5_index */ H5_DLL herr_t H5Literate2(hid_t grp_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx, H5L_iterate2_t op, void *op_data); +H5_DLL herr_t H5Literate_async(const char *app_file, const char *app_func, unsigned app_line, hid_t group_id, + H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx_p, H5L_iterate2_t op, + void *op_data, hid_t es_id); /** * \ingroup TRAV * @@ -1591,6 +1607,28 @@ H5_DLL herr_t H5Lunpack_elink_val(const void *ext_linkval /*in*/, size_t link_si H5_DLL herr_t H5Lcreate_external(const char *file_name, const char *obj_name, hid_t link_loc_id, const char *link_name, hid_t lcpl_id, hid_t lapl_id); +/* API Wrappers for async routines */ +/* (Must be defined _after_ the function prototype) */ +/* (And must only defined when included in application code, not the library) */ +#ifndef H5L_MODULE +#define H5Lcreate_hard_async(...) H5Lcreate_hard_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Lcreate_soft_async(...) H5Lcreate_soft_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Ldelete_async(...) H5Ldelete_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Ldelete_by_idx_async(...) H5Ldelete_by_idx_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Lexists_async(...) H5Lexists_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Literate_async(...) H5Literate_async(__FILE__, __func__, __LINE__, __VA_ARGS__) + +/* Define "wrapper" versions of function calls, to allow compile-time values to + * be passed in by language wrapper or library layer on top of HDF5. + */ +#define H5Lcreate_hard_async_wrap H5_NO_EXPAND(H5Lcreate_hard_async) +#define H5Lcreate_soft_async_wrap H5_NO_EXPAND(H5Lcreate_soft_async) +#define H5Ldelete_async_wrap H5_NO_EXPAND(H5Ldelete_async) +#define H5Ldelete_by_idx_async_wrap H5_NO_EXPAND(H5Ldelete_by_idx_async) +#define H5Lexists_async_wrap H5_NO_EXPAND(H5Lexists_async) +#define H5Literate_async_wrap H5_NO_EXPAND(H5Literate_async) +#endif /* H5L_MODULE */ + /* Symbols defined for compatibility with previous versions of the HDF5 API. * * Use of these symbols is deprecated. @@ -24,6 +24,7 @@ #include "H5CXprivate.h" /* API Contexts */ #include "H5Mpkg.h" /* Maps */ #include "H5Eprivate.h" /* Error handling */ +#include "H5ESprivate.h" /* Event Sets */ #include "H5Iprivate.h" /* IDs */ #include "H5VLprivate.h" /* Virtual Object Layer */ @@ -40,6 +41,19 @@ /********************/ static herr_t H5M__close_cb(H5VL_object_t *map_vol_obj, void **request); +#ifdef H5_HAVE_MAP_API +static hid_t H5M__create_api_common(hid_t loc_id, const char *name, hid_t key_type_id, hid_t val_type_id, + hid_t lcpl_id, hid_t mcpl_id, hid_t mapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static hid_t H5M__open_api_common(hid_t loc_id, const char *name, hid_t mapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static herr_t H5M__put_api_common(hid_t map_id, hid_t key_mem_type_id, const void *key, hid_t val_mem_type_id, + const void *value, hid_t dxpl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static herr_t H5M__get_api_common(hid_t map_id, hid_t key_mem_type_id, const void *key, hid_t val_mem_type_id, + void *value, hid_t dxpl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr); +#endif /* H5_HAVE_MAP_API */ + /*********************/ /* Package Variables */ /*********************/ @@ -219,15 +233,9 @@ done: #ifdef H5_HAVE_MAP_API /*------------------------------------------------------------------------- - * Function: H5Mcreate + * Function: H5M__create_api_common * - * Purpose: Creates a new map object for storing key-value pairs. The - * in-file datatype for keys is defined by KEY_TYPE_ID and - * the in-file datatype for values is defined by VAL_TYPE_ID. - * LOC_ID specifies the location to create the map object and - * NAME specifies the name of the link to the object - * (relative to LOC_ID). Other options can be specified - * through the property lists LCPL_ID, MCPL_ID, and MAPL_ID. + * Purpose: This is the common function for creating the HDF5 map. * * Return: Success: The object ID of the new map. * @@ -235,17 +243,18 @@ done: * *------------------------------------------------------------------------- */ -hid_t -H5Mcreate(hid_t loc_id, const char *name, hid_t key_type_id, hid_t val_type_id, hid_t lcpl_id, hid_t mcpl_id, - hid_t mapl_id) +static hid_t +H5M__create_api_common(hid_t loc_id, const char *name, hid_t key_type_id, hid_t val_type_id, hid_t lcpl_id, + hid_t mcpl_id, hid_t mapl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr) { - void * map = NULL; /* New map's info */ - H5VL_object_t * vol_obj = NULL; /* object of loc_id */ - H5VL_loc_params_t loc_params; - hid_t ret_value = H5I_INVALID_HID; /* Return value */ + void * map = NULL; /* New map's info */ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ - FUNC_ENTER_API(H5I_INVALID_HID) - H5TRACE7("i", "i*siiiii", loc_id, name, key_type_id, val_type_id, lcpl_id, mcpl_id, mapl_id); + FUNC_ENTER_STATIC /* Check arguments */ if (!name) @@ -265,37 +274,112 @@ H5Mcreate(hid_t loc_id, const char *name, hid_t key_type_id, hid_t val_type_id, else if (TRUE != H5P_isa_class(mcpl_id, H5P_MAP_CREATE)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "mcpl_id is not a map create property list ID") - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&mapl_id, H5P_CLS_MACC, loc_id, TRUE) < 0) - HGOTO_ERROR(H5E_MAP, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info") - - /* Get the location object */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier") - - /* Set location parameters */ - loc_params.type = H5VL_OBJECT_BY_SELF; - loc_params.obj_type = H5I_get_type(loc_id); + /* Set up object access arguments */ + if (H5VL_setup_acc_args(loc_id, H5P_CLS_MACC, TRUE, &mapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_MAP, H5E_CANTSET, H5I_INVALID_HID, "can't set object access arguments") /* Create the map */ - if (H5VL_optional(vol_obj, H5VL_MAP_CREATE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &loc_params, name, + if (H5VL_optional(*vol_obj_ptr, H5VL_MAP_CREATE, H5P_DATASET_XFER_DEFAULT, token_ptr, &loc_params, name, lcpl_id, key_type_id, val_type_id, mcpl_id, mapl_id, &map) < 0) HGOTO_ERROR(H5E_MAP, H5E_CANTINIT, H5I_INVALID_HID, "unable to create map") /* Get an ID for the map */ - if ((ret_value = H5VL_register(H5I_MAP, map, vol_obj->connector, TRUE)) < 0) + if ((ret_value = H5VL_register(H5I_MAP, map, (*vol_obj_ptr)->connector, TRUE)) < 0) HGOTO_ERROR(H5E_MAP, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register map handle") done: /* Cleanup on failure */ if (H5I_INVALID_HID == ret_value) - if (map && H5VL_optional(vol_obj, H5VL_MAP_CLOSE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) + if (map && H5VL_optional(*vol_obj_ptr, H5VL_MAP_CLOSE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release map") + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5M__create_api_common() */ + +/*------------------------------------------------------------------------- + * Function: H5Mcreate + * + * Purpose: Creates a new map object for storing key-value pairs. The + * in-file datatype for keys is defined by KEY_TYPE_ID and + * the in-file datatype for values is defined by VAL_TYPE_ID. + * LOC_ID specifies the location to create the map object and + * NAME specifies the name of the link to the object + * (relative to LOC_ID). Other options can be specified + * through the property lists LCPL_ID, MCPL_ID, and MAPL_ID. + * + * Return: Success: The object ID of the new map. + * + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Mcreate(hid_t loc_id, const char *name, hid_t key_type_id, hid_t val_type_id, hid_t lcpl_id, hid_t mcpl_id, + hid_t mapl_id) +{ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE7("i", "i*siiiii", loc_id, name, key_type_id, val_type_id, lcpl_id, mcpl_id, mapl_id); + + /* Create the map synchronously */ + if ((ret_value = H5M__create_api_common(loc_id, name, key_type_id, val_type_id, lcpl_id, mcpl_id, mapl_id, + NULL, NULL)) < 0) + HGOTO_ERROR(H5E_MAP, H5E_CANTCREATE, H5I_INVALID_HID, "unable to create map synchronously") + +done: FUNC_LEAVE_API(ret_value) } /* end H5Mcreate() */ /*------------------------------------------------------------------------- + * Function: H5Mcreate_async + * + * Purpose: Asynchronous version of H5Mcreate + * + * Return: Success: The object ID of the new map. + * + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Mcreate_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, const char *name, + hid_t key_type_id, hid_t val_type_id, hid_t lcpl_id, hid_t mcpl_id, hid_t mapl_id, + hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE11("i", "*s*sIui*siiiiii", app_file, app_func, app_line, loc_id, name, key_type_id, val_type_id, + lcpl_id, mcpl_id, mapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; + + /* Create the map asynchronously */ + if ((ret_value = H5M__create_api_common(loc_id, name, key_type_id, val_type_id, lcpl_id, mcpl_id, mapl_id, + token_ptr, &vol_obj)) < 0) + HGOTO_ERROR(H5E_MAP, H5E_CANTCREATE, H5I_INVALID_HID, "unable to create map asynchronously") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE11(FUNC, "*s*sIui*siiiiii", app_file, app_func, app_line, loc_id, name, + key_type_id, val_type_id, lcpl_id, mcpl_id, mapl_id, es_id)) < 0) { + if (H5I_dec_app_ref_always_close(ret_value) < 0) + HDONE_ERROR(H5E_MAP, H5E_CANTDEC, H5I_INVALID_HID, "can't decrement count on map ID") + HGOTO_ERROR(H5E_MAP, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Mcreate_async() */ + +/*------------------------------------------------------------------------- * Function: H5Mcreate_anon * * Purpose: Creates a new map object for storing key-value pairs. The @@ -367,13 +451,9 @@ done: } /* end H5Mcreate_anon() */ /*------------------------------------------------------------------------ - * Function: H5Mopen - * - * Purpose: Finds a map named NAME at LOC_ID, opens it, and returns - * its ID. The map should be close when the caller is no - * longer interested in it. + * Function: H5M__open_api_common * - * Takes a map access property list + * Purpose: This is the common function for opening the HDF5 map. * * Return: Success: Object ID of the map * @@ -381,16 +461,18 @@ done: * *------------------------------------------------------------------------- */ -hid_t -H5Mopen(hid_t loc_id, const char *name, hid_t mapl_id) +static hid_t +H5M__open_api_common(hid_t loc_id, const char *name, hid_t mapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) { - void * map = NULL; /* map object from VOL connector */ - H5VL_object_t * vol_obj = NULL; /* object of loc_id */ - H5VL_loc_params_t loc_params; - hid_t ret_value = H5I_INVALID_HID; /* Return value */ + void * map = NULL; /* map object from VOL connector */ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ - FUNC_ENTER_API(H5I_INVALID_HID) - H5TRACE3("i", "i*si", loc_id, name, mapl_id); + FUNC_ENTER_STATIC /* Check args */ if (!name) @@ -398,36 +480,111 @@ H5Mopen(hid_t loc_id, const char *name, hid_t mapl_id) if (!*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be an empty string") - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&mapl_id, H5P_CLS_MACC, loc_id, FALSE) < 0) - HGOTO_ERROR(H5E_MAP, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info") - - /* get the location object */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier") - - /* Set the location parameters */ - loc_params.type = H5VL_OBJECT_BY_SELF; - loc_params.obj_type = H5I_get_type(loc_id); + /* Set up object access arguments */ + if (H5VL_setup_acc_args(loc_id, H5P_CLS_MACC, FALSE, &mapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_MAP, H5E_CANTSET, H5I_INVALID_HID, "can't set object access arguments") /* Open the map */ - if (H5VL_optional(vol_obj, H5VL_MAP_OPEN, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &loc_params, name, + if (H5VL_optional(*vol_obj_ptr, H5VL_MAP_OPEN, H5P_DATASET_XFER_DEFAULT, token_ptr, &loc_params, name, mapl_id, &map) < 0) HGOTO_ERROR(H5E_MAP, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open map") /* Register an ID for the map */ - if ((ret_value = H5VL_register(H5I_MAP, map, vol_obj->connector, TRUE)) < 0) + if ((ret_value = H5VL_register(H5I_MAP, map, (*vol_obj_ptr)->connector, TRUE)) < 0) HGOTO_ERROR(H5E_MAP, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register map ID") done: /* Cleanup on failure */ if (H5I_INVALID_HID == ret_value) + if (map && H5VL_optional(*vol_obj_ptr, H5VL_MAP_CLOSE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release map") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5M__open_api_common() */ + +/*------------------------------------------------------------------------ + * Function: H5Mopen + * + * Purpose: Finds a map named NAME at LOC_ID, opens it, and returns + * its ID. The map should be close when the caller is no + * longer interested in it. + * + * Takes a map access property list + * + * Return: Success: Object ID of the map + * + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Mopen(hid_t loc_id, const char *name, hid_t mapl_id) +{ + void * map = NULL; /* map object from VOL connector */ + H5VL_object_t *vol_obj = NULL; /* object of loc_id */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE3("i", "i*si", loc_id, name, mapl_id); + + /* Open the map synchronously */ + if ((ret_value = H5M__open_api_common(loc_id, name, mapl_id, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_MAP, H5E_CANTCREATE, H5I_INVALID_HID, "unable to open map synchronously") + +done: + /* Cleanup on failure */ + if (H5I_INVALID_HID == ret_value) if (map && H5VL_optional(vol_obj, H5VL_MAP_CLOSE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release map") FUNC_LEAVE_API(ret_value) } /* end H5Mopen() */ +/*------------------------------------------------------------------------ + * Function: H5Mopen_async + * + * Purpose: Asynchronous version of H5Mopen + * + * Return: Success: Object ID of the map + * + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Mopen_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, const char *name, + hid_t mapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE7("i", "*s*sIui*sii", app_file, app_func, app_line, loc_id, name, mapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; + + /* Open the map asynchronously */ + if ((ret_value = H5M__open_api_common(loc_id, name, mapl_id, token_ptr, &vol_obj)) < 0) + HGOTO_ERROR(H5E_MAP, H5E_CANTCREATE, H5I_INVALID_HID, "unable to open map asynchronously") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE7(FUNC, "*s*sIui*sii", app_file, app_func, app_line, loc_id, name, mapl_id, + es_id)) < 0) { + if (H5I_dec_app_ref_always_close(ret_value) < 0) + HDONE_ERROR(H5E_MAP, H5E_CANTDEC, H5I_INVALID_HID, "can't decrement count on map ID") + HGOTO_ERROR(H5E_MAP, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Mopen_async() */ + /*------------------------------------------------------------------------- * Function: H5Mclose * @@ -462,6 +619,65 @@ done: } /* end H5Mclose() */ /*------------------------------------------------------------------------- + * Function: H5Mclose_async + * + * Purpose: Asynchronous version of H5Mclose + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5Mclose_async(const char *app_file, const char *app_func, unsigned app_line, hid_t map_id, hid_t es_id) +{ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + H5VL_object_t *vol_obj = NULL; /* VOL object of dset_id */ + H5VL_t * connector = NULL; /* VOL connector */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "*s*sIuii", app_file, app_func, app_line, map_id, es_id); + + /* Check args */ + if (H5I_MAP != H5I_get_type(map_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a map ID") + + /* Get dataset object's connector */ + if (NULL == (vol_obj = H5VL_vol_object(map_id))) + HGOTO_ERROR(H5E_MAP, H5E_CANTGET, FAIL, "can't get VOL object for dataset") + + /* Prepare for possible asynchronous operation */ + if (H5ES_NONE != es_id) { + /* Increase connector's refcount, so it doesn't get closed if closing + * the dataset closes the file */ + connector = vol_obj->connector; + H5VL_conn_inc_rc(connector); + + /* Point at token for operation to set up */ + token_ptr = &token; + } /* end if */ + + /* Decrement the counter on the map. It will be freed if the count + * reaches zero. + */ + if (H5I_dec_app_ref_always_close_async(map_id, token_ptr) < 0) + HGOTO_ERROR(H5E_MAP, H5E_CANTDEC, FAIL, "can't decrement count on dataset ID") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE5(FUNC, "*s*sIuii", app_file, app_func, app_line, map_id, es_id)) < 0) + HGOTO_ERROR(H5E_MAP, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + if (connector && H5VL_conn_dec_rc(connector) < 0) + HDONE_ERROR(H5E_MAP, H5E_CANTDEC, FAIL, "can't decrement ref count on connector") + + FUNC_LEAVE_API(ret_value) +} /* end H5Mclose_async() */ + +/*------------------------------------------------------------------------- * Function: H5Mget_key_type * * Purpose: Returns a copy of the key datatype for a map. @@ -647,6 +863,54 @@ done: } /* end H5Mget_count() */ /*------------------------------------------------------------------------- + * Function: H5M__put_api_common + * + * Purpose: This is the common function for putting value to map. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5M__put_api_common(hid_t map_id, hid_t key_mem_type_id, const void *key, hid_t val_mem_type_id, + const void *value, hid_t dxpl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check arguments */ + if (key_mem_type_id < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid key memory datatype ID") + if (val_mem_type_id < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid value memory datatype ID") + + /* Get map pointer */ + if (NULL == (*vol_obj_ptr = (H5VL_object_t *)H5I_object_verify(map_id, H5I_MAP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "map_id is not a map ID") + + /* Get the default dataset transfer property list if the user didn't provide one */ + if (H5P_DEFAULT == dxpl_id) + dxpl_id = H5P_DATASET_XFER_DEFAULT; + else if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms") + + /* Set DXPL for operation */ + H5CX_set_dxpl(dxpl_id); + + /* Set the key/value pair */ + if (H5VL_optional(*vol_obj_ptr, H5VL_MAP_PUT, dxpl_id, token_ptr, key_mem_type_id, key, val_mem_type_id, + value) < 0) + HGOTO_ERROR(H5E_MAP, H5E_CANTSET, FAIL, "unable to put key/value pair") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5M__put_api_common() */ + +/*------------------------------------------------------------------------- * Function: H5Mput * * Purpose: H5Mput adds a key-value pair to the Map specified by @@ -666,12 +930,83 @@ herr_t H5Mput(hid_t map_id, hid_t key_mem_type_id, const void *key, hid_t val_mem_type_id, const void *value, hid_t dxpl_id) { - H5VL_object_t *vol_obj = NULL; - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE6("e", "ii*xi*xi", map_id, key_mem_type_id, key, val_mem_type_id, value, dxpl_id); + /* Add key-value pair to the map synchronously */ + if ((ret_value = H5M__put_api_common(map_id, key_mem_type_id, key, val_mem_type_id, value, dxpl_id, NULL, + NULL)) < 0) + HGOTO_ERROR(H5E_MAP, H5E_CANTPUT, FAIL, "unable to put value to map synchronously") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Mput() */ + +/*------------------------------------------------------------------------- + * Function: H5Mput_async + * + * Purpose: Asynchronous version of H5Mput + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5Mput_async(const char *app_file, const char *app_func, unsigned app_line, hid_t map_id, + hid_t key_mem_type_id, const void *key, hid_t val_mem_type_id, const void *value, hid_t dxpl_id, + hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE10("e", "*s*sIuii*xi*xii", app_file, app_func, app_line, map_id, key_mem_type_id, key, + val_mem_type_id, value, dxpl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; + + /* Add key-value pair to the map asynchronously */ + if ((ret_value = H5M__put_api_common(map_id, key_mem_type_id, key, val_mem_type_id, value, dxpl_id, + token_ptr, &vol_obj)) < 0) + HGOTO_ERROR(H5E_MAP, H5E_CANTPUT, FAIL, "unable to put value to map asynchronously") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE10(FUNC, "*s*sIuii*xi*xii", app_file, app_func, app_line, map_id, + key_mem_type_id, key, val_mem_type_id, value, dxpl_id, es_id)) < 0) + HGOTO_ERROR(H5E_MAP, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Mput_async() */ + +/*------------------------------------------------------------------------- + * Function: H5M__get_api_common + * + * Purpose: This is common function for getting value from the map. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5M__get_api_common(hid_t map_id, hid_t key_mem_type_id, const void *key, hid_t val_mem_type_id, void *value, + hid_t dxpl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + /* Check arguments */ if (key_mem_type_id < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid key memory datatype ID") @@ -679,7 +1014,7 @@ H5Mput(hid_t map_id, hid_t key_mem_type_id, const void *key, hid_t val_mem_type_ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid value memory datatype ID") /* Get map pointer */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(map_id, H5I_MAP))) + if (NULL == (*vol_obj_ptr = (H5VL_object_t *)H5I_object_verify(map_id, H5I_MAP))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "map_id is not a map ID") /* Get the default dataset transfer property list if the user didn't provide one */ @@ -691,14 +1026,14 @@ H5Mput(hid_t map_id, hid_t key_mem_type_id, const void *key, hid_t val_mem_type_ /* Set DXPL for operation */ H5CX_set_dxpl(dxpl_id); - /* Set the key/value pair */ - if (H5VL_optional(vol_obj, H5VL_MAP_PUT, dxpl_id, H5_REQUEST_NULL, key_mem_type_id, key, val_mem_type_id, - value) < 0) - HGOTO_ERROR(H5E_MAP, H5E_CANTSET, FAIL, "unable to put key/value pair") + /* Get the value for the key */ + if (H5VL_optional(*vol_obj_ptr, H5VL_MAP_GET_VAL, dxpl_id, token_ptr, key_mem_type_id, key, + val_mem_type_id, value) < 0) + HGOTO_ERROR(H5E_MAP, H5E_CANTGET, FAIL, "unable to get value from map") done: - FUNC_LEAVE_API(ret_value) -} /* end H5Mput() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5M__get_api_common() */ /*------------------------------------------------------------------------- * Function: H5Mget @@ -723,39 +1058,62 @@ herr_t H5Mget(hid_t map_id, hid_t key_mem_type_id, const void *key, hid_t val_mem_type_id, void *value, hid_t dxpl_id) { - H5VL_object_t *vol_obj = NULL; - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE6("e", "ii*xi*xi", map_id, key_mem_type_id, key, val_mem_type_id, value, dxpl_id); - /* Check arguments */ - if (key_mem_type_id < 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid key memory datatype ID") - if (val_mem_type_id < 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid value memory datatype ID") + /* Get key-value pair from the map synchronously */ + if ((ret_value = H5M__get_api_common(map_id, key_mem_type_id, key, val_mem_type_id, value, dxpl_id, NULL, + NULL)) < 0) + HGOTO_ERROR(H5E_MAP, H5E_CANTGET, FAIL, "unable to get value from map synchronously") - /* Get map pointer */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(map_id, H5I_MAP))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "map_id is not a map ID") +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Mget() */ - /* Get the default dataset transfer property list if the user didn't provide one */ - if (H5P_DEFAULT == dxpl_id) - dxpl_id = H5P_DATASET_XFER_DEFAULT; - else if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms") +/*------------------------------------------------------------------------- + * Function: H5Mget_async + * + * Purpose: Asynchronous version of H5Mget + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5Mget_async(const char *app_file, const char *app_func, unsigned app_line, hid_t map_id, + hid_t key_mem_type_id, const void *key, hid_t val_mem_type_id, void *value, hid_t dxpl_id, + hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ - /* Set DXPL for operation */ - H5CX_set_dxpl(dxpl_id); + FUNC_ENTER_API(FAIL) + H5TRACE10("e", "*s*sIuii*xi*xii", app_file, app_func, app_line, map_id, key_mem_type_id, key, + val_mem_type_id, value, dxpl_id, es_id); - /* Get the value for the key */ - if (H5VL_optional(vol_obj, H5VL_MAP_GET_VAL, dxpl_id, H5_REQUEST_NULL, key_mem_type_id, key, - val_mem_type_id, value) < 0) - HGOTO_ERROR(H5E_MAP, H5E_CANTGET, FAIL, "unable to get value from map") + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; + + /* Get key-value pair from the map asynchronously */ + if ((ret_value = H5M__get_api_common(map_id, key_mem_type_id, key, val_mem_type_id, value, dxpl_id, + token_ptr, &vol_obj)) < 0) + HGOTO_ERROR(H5E_MAP, H5E_CANTGET, FAIL, "unable to get value from map asynchronously") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE10(FUNC, "*s*sIuii*xi*xii", app_file, app_func, app_line, map_id, + key_mem_type_id, key, val_mem_type_id, value, dxpl_id, es_id)) < 0) + HGOTO_ERROR(H5E_MAP, H5E_CANTINSERT, FAIL, "can't insert token into event set") done: FUNC_LEAVE_API(ret_value) -} /* end H5Mget() */ +} /* end H5Mget_async() */ /*------------------------------------------------------------------------- * Function: H5Mexists @@ -52,7 +52,8 @@ /* Memory allocation "block", wrapped around each allocation */ struct H5MM_block_t; /* Forward declaration for typedef */ typedef struct H5MM_block_t { - unsigned char sig[H5MM_SIG_SIZE]; /* Signature for the block, to indicate it was allocated with H5MM* interface */ + unsigned char + sig[H5MM_SIG_SIZE]; /* Signature for the block, to indicate it was allocated with H5MM* interface */ struct H5MM_block_t *next; /* Pointer to next block in the list of allocated blocks */ struct H5MM_block_t *prev; /* Pointer to previous block in the list of allocated blocks */ union { diff --git a/src/H5MMprivate.h b/src/H5MMprivate.h index 7c34a98..b4a59ba 100644 --- a/src/H5MMprivate.h +++ b/src/H5MMprivate.h @@ -48,9 +48,9 @@ H5_DLL void * H5MM_xfree(void *mem); H5_DLL void * H5MM_xfree_const(const void *mem); H5_DLL void * H5MM_memcpy(void *dest, const void *src, size_t n); H5_DLL herr_t H5MM_get_alloc_stats(H5_alloc_stats_t *stats); -#if defined H5_MEMORY_ALLOC_SANITY_CHECK -H5_DLL void H5MM_sanity_check_all(void); -H5_DLL void H5MM_final_sanity_check(void); +#if defined H5_MEMORY_ALLOC_SANITY_CHECK +H5_DLL void H5MM_sanity_check_all(void); +H5_DLL void H5MM_final_sanity_check(void); #endif /* H5_MEMORY_ALLOC_SANITY_CHECK */ #endif /* _H5MMprivate_H */ diff --git a/src/H5Mpublic.h b/src/H5Mpublic.h index 643a1e6..5c8ba23 100644 --- a/src/H5Mpublic.h +++ b/src/H5Mpublic.h @@ -83,9 +83,16 @@ extern "C" { H5_DLL hid_t H5Mcreate(hid_t loc_id, const char *name, hid_t key_type_id, hid_t val_type_id, hid_t lcpl_id, hid_t mcpl_id, hid_t mapl_id); +H5_DLL hid_t H5Mcreate_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *name, hid_t key_type_id, hid_t val_type_id, hid_t lcpl_id, + hid_t mcpl_id, hid_t mapl_id, hid_t es_id); H5_DLL hid_t H5Mcreate_anon(hid_t loc_id, hid_t key_type_id, hid_t val_type_id, hid_t mcpl_id, hid_t mapl_id); H5_DLL hid_t H5Mopen(hid_t loc_id, const char *name, hid_t mapl_id); +H5_DLL hid_t H5Mopen_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *name, hid_t mapl_id, hid_t es_id); H5_DLL herr_t H5Mclose(hid_t map_id); +H5_DLL herr_t H5Mclose_async(const char *app_file, const char *app_func, unsigned app_line, hid_t map_id, + hid_t es_id); H5_DLL hid_t H5Mget_key_type(hid_t map_id); H5_DLL hid_t H5Mget_val_type(hid_t map_id); H5_DLL hid_t H5Mget_create_plist(hid_t map_id); @@ -93,8 +100,14 @@ H5_DLL hid_t H5Mget_access_plist(hid_t map_id); H5_DLL herr_t H5Mget_count(hid_t map_id, hsize_t *count, hid_t dxpl_id); H5_DLL herr_t H5Mput(hid_t map_id, hid_t key_mem_type_id, const void *key, hid_t val_mem_type_id, const void *value, hid_t dxpl_id); +H5_DLL herr_t H5Mput_async(const char *app_file, const char *app_func, unsigned app_line, hid_t map_id, + hid_t key_mem_type_id, const void *key, hid_t val_mem_type_id, const void *value, + hid_t dxpl_id, hid_t es_id); H5_DLL herr_t H5Mget(hid_t map_id, hid_t key_mem_type_id, const void *key, hid_t val_mem_type_id, void *value, hid_t dxpl_id); +H5_DLL herr_t H5Mget_async(const char *app_file, const char *app_func, unsigned app_line, hid_t map_id, + hid_t key_mem_type_id, const void *key, hid_t val_mem_type_id, void *value, + hid_t dxpl_id, hid_t es_id); H5_DLL herr_t H5Mexists(hid_t map_id, hid_t key_mem_type_id, const void *key, hbool_t *exists, hid_t dxpl_id); H5_DLL herr_t H5Miterate(hid_t map_id, hsize_t *idx, hid_t key_mem_type_id, H5M_iterate_t op, void *op_data, hid_t dxpl_id); @@ -102,6 +115,25 @@ H5_DLL herr_t H5Miterate_by_name(hid_t loc_id, const char *map_name, hsize_t *id H5M_iterate_t op, void *op_data, hid_t dxpl_id, hid_t lapl_id); H5_DLL herr_t H5Mdelete(hid_t map_id, hid_t key_mem_type_id, const void *key, hid_t dxpl_id); +/* API Wrappers for async routines */ +/* (Must be defined _after_ the function prototype) */ +/* (And must only defined when included in application code, not the library) */ +#ifndef H5M_MODULE +#define H5Mcreate_async(...) H5Mcreate_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Mopen_async(...) H5Mopen_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Mclose_async(...) H5Mclose_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Mput_async(...) H5Mput_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Mget_async(...) H5Mget_async(__FILE__, __func__, __LINE__, __VA_ARGS__) + +/* Define "wrapper" versions of function calls, to allow compile-time values to + * be passed in by language wrapper or library layer on top of HDF5. */ +#define H5Mcreate_async_wrap H5_NO_EXPAND(H5Mcreate_async) +#define H5Mopen_async_wrap H5_NO_EXPAND(H5Mopen_async) +#define H5Mclose_async_wrap H5_NO_EXPAND(H5Mclose_async) +#define H5Mput_async_wrap H5_NO_EXPAND(H5Mput_async) +#define H5Mget_async_wrap H5_NO_EXPAND(H5Mget_async) +#endif /* H5M_MODULE */ + /* Symbols defined for compatibility with previous versions of the HDF5 API. * * Use of these symbols is deprecated. @@ -32,6 +32,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5CXprivate.h" /* API Contexts */ #include "H5Eprivate.h" /* Error handling */ +#include "H5ESprivate.h" /* Event Sets */ #include "H5Fprivate.h" /* File access */ #include "H5Iprivate.h" /* IDs */ #include "H5Lprivate.h" /* Links */ @@ -55,6 +56,22 @@ /* Local Prototypes */ /********************/ +/* Helper routines for sync/async API calls */ +static hid_t H5O__open_api_common(hid_t loc_id, const char *name, hid_t lapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static hid_t H5O__open_by_idx_api_common(hid_t loc_id, const char *group_name, H5_index_t idx_type, + H5_iter_order_t order, hsize_t n, hid_t lapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static herr_t H5O__get_info_by_name_api_common(hid_t loc_id, const char *name, H5O_info2_t *oinfo /*out*/, + unsigned fields, hid_t lapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static herr_t H5O__copy_api_common(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, + const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static herr_t H5O__flush_api_common(hid_t obj_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr); +static herr_t H5O__refresh_api_common(hid_t oid, void **token_ptr, H5VL_object_t **_vol_obj_ptr); +static htri_t H5O__close_check_common(hid_t object_id); + /*********************/ /* Package Variables */ /*********************/ @@ -68,6 +85,50 @@ /*******************/ /*------------------------------------------------------------------------- + * Function: H5O__open_api_common + * + * Purpose: This is the common function for opening an object + * + * Return: Success: An open object identifier + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +static hid_t +H5O__open_api_common(hid_t loc_id, const char *name, hid_t lapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5I_type_t opened_type; + void * opened_obj = NULL; + H5VL_loc_params_t loc_params; + hid_t ret_value = H5I_INVALID_HID; + + FUNC_ENTER_STATIC + + /* Check args */ + + /* name is checked in this H5VL_setup_name_args() */ + /* Set up object access arguments */ + if (H5VL_setup_name_args(loc_id, name, H5P_CLS_LACC, FALSE, lapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, H5I_INVALID_HID, "can't set object access arguments") + + /* Open the object */ + if (NULL == (opened_obj = H5VL_object_open(*vol_obj_ptr, &loc_params, &opened_type, + H5P_DATASET_XFER_DEFAULT, token_ptr))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object") + + /* Get an atom for the object */ + if ((ret_value = H5VL_register(opened_type, opened_obj, (*vol_obj_ptr)->connector, TRUE)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize object handle") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O__open_api_common() */ + +/*------------------------------------------------------------------------- * Function: H5Oopen * * Purpose: Opens an object within an HDF5 file. @@ -93,47 +154,106 @@ hid_t H5Oopen(hid_t loc_id, const char *name, hid_t lapl_id) { - H5VL_object_t * vol_obj; /* Object of loc_id */ - H5I_type_t opened_type; - void * opened_obj = NULL; - H5VL_loc_params_t loc_params; - hid_t ret_value = H5I_INVALID_HID; + hid_t ret_value = H5I_INVALID_HID; FUNC_ENTER_API(H5I_INVALID_HID) H5TRACE3("i", "i*si", loc_id, name, lapl_id); - /* Check args */ - if (!name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be NULL") - if (!*name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be an empty string") + /* Open the object synchronously */ + if ((ret_value = H5O__open_api_common(loc_id, name, lapl_id, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to synchronously open object") - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info") +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Oopen() */ - /* Get the location object */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier") +/*------------------------------------------------------------------------- + * Function: H5Oopen_async + * + * Purpose: Asynchronous version of H5Oopen + * + * Return: Success: An open object identifier + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Oopen_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, const char *name, + hid_t lapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ - /* Set location struct fields */ - 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); + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE7("i", "*s*sIui*sii", app_file, app_func, app_line, loc_id, name, lapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Open the object asynchronously */ + if ((ret_value = H5O__open_api_common(loc_id, name, lapl_id, token_ptr, &vol_obj)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to asynchronously open object") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE7(FUNC, "*s*sIui*sii", app_file, app_func, app_line, loc_id, name, lapl_id, + es_id)) < 0) { + if (H5I_dec_app_ref_always_close(ret_value) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTDEC, H5I_INVALID_HID, "can't decrement count on object ID") + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Oopen_async() */ + +/*------------------------------------------------------------------------- + * Function: H5O__open_by_idx_api_common + * + * Purpose: This is the common function for opening an object within an index + * + * Return: Success: An open object identifier + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +static hid_t +H5O__open_by_idx_api_common(hid_t loc_id, const char *group_name, H5_index_t idx_type, H5_iter_order_t order, + hsize_t n, hid_t lapl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5I_type_t opened_type; + void * opened_obj = NULL; + H5VL_loc_params_t loc_params; + hid_t ret_value = H5I_INVALID_HID; + + FUNC_ENTER_STATIC + + /* Check args */ + /* group_name, idx_type, order are checked in H5VL_setup_idx-args() */ + /* Set up object access arguments */ + if (H5VL_setup_idx_args(loc_id, group_name, idx_type, order, n, H5P_CLS_LACC, FALSE, lapl_id, vol_obj_ptr, + &loc_params) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTSET, H5I_INVALID_HID, "can't set object access arguments") /* Open the object */ - if (NULL == (opened_obj = H5VL_object_open(vol_obj, &loc_params, &opened_type, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL))) + if (NULL == (opened_obj = H5VL_object_open(*vol_obj_ptr, &loc_params, &opened_type, + H5P_DATASET_XFER_DEFAULT, token_ptr))) HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object") /* Get an ID for the object */ - if ((ret_value = H5VL_register(opened_type, opened_obj, vol_obj->connector, TRUE)) < 0) + if ((ret_value = H5VL_register(opened_type, opened_obj, (*vol_obj_ptr)->connector, TRUE)) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object handle") done: - FUNC_LEAVE_API(ret_value) -} /* end H5Oopen() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O__open_by_idx_api_common() */ /*------------------------------------------------------------------------- * Function: H5Oopen_by_idx @@ -162,50 +282,66 @@ hid_t H5Oopen_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t lapl_id) { - H5VL_object_t * vol_obj; /* Object of loc_id */ - H5I_type_t opened_type; - void * opened_obj = NULL; - H5VL_loc_params_t loc_params; - hid_t ret_value = H5I_INVALID_HID; + hid_t ret_value = H5I_INVALID_HID; FUNC_ENTER_API(H5I_INVALID_HID) H5TRACE6("i", "i*sIiIohi", loc_id, group_name, idx_type, order, n, lapl_id); - /* Check args */ - if (!group_name || !*group_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "no name specified") - if (idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid index type specified") - if (order <= H5_ITER_UNKNOWN || order >= H5_ITER_N) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "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, FALSE) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info") + /* Open the object synchronously */ + if ((ret_value = + H5O__open_by_idx_api_common(loc_id, group_name, idx_type, order, n, lapl_id, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to synchronously open object") - loc_params.type = H5VL_OBJECT_BY_IDX; - loc_params.loc_data.loc_by_idx.name = group_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); - - /* get the location object */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier") +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Oopen_by_idx() */ - /* Open the object */ - if (NULL == (opened_obj = H5VL_object_open(vol_obj, &loc_params, &opened_type, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL))) - HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object") +/*------------------------------------------------------------------------- + * Function: H5Oopen_by_idx_async + * + * Purpose: Asynchronous version of H5Oopen_by_idx + * + * Return: Success: An open object identifier + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Oopen_by_idx_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *group_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, + hid_t lapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ - if ((ret_value = H5VL_register(opened_type, opened_obj, vol_obj->connector, TRUE)) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object handle") + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE10("i", "*s*sIui*sIiIohii", app_file, app_func, app_line, loc_id, group_name, idx_type, order, n, + lapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Open the object asynchronously */ + if ((ret_value = H5O__open_by_idx_api_common(loc_id, group_name, idx_type, order, n, lapl_id, token_ptr, + &vol_obj)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to asynchronously open object") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE10(FUNC, "*s*sIui*sIiIohii", app_file, app_func, app_line, loc_id, + group_name, idx_type, order, n, lapl_id, es_id)) < 0) { + if (H5I_dec_app_ref_always_close(ret_value) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTDEC, H5I_INVALID_HID, "can't decrement count on object ID") + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } done: FUNC_LEAVE_API(ret_value) -} /* end H5Oopen_by_idx() */ +} /* end H5Oopen_by_idx_async() */ /*------------------------------------------------------------------------- * Function: H5Oopen_by_token @@ -263,6 +399,72 @@ done: } /* end H5Oopen_by_token() */ /*------------------------------------------------------------------------- + * Function: H5O__copy_api_common + * + * Purpose: This is the common function for copying an object. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O__copy_api_common(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, const char *dst_name, + hid_t ocpypl_id, hid_t lcpl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + /* dst_id */ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params2; + + /* src_id */ + H5VL_object_t * vol_obj1 = NULL; /* object of src_id */ + H5VL_loc_params_t loc_params1; + + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check arguments */ + if (!src_name || !*src_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no source name specified") + if (!dst_name || !*dst_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no destination name specified") + + /* Get correct property lists */ + if (H5P_DEFAULT == lcpl_id) + lcpl_id = H5P_LINK_CREATE_DEFAULT; + else if (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link creation property list") + + /* Get object copy property list */ + if (H5P_DEFAULT == ocpypl_id) + ocpypl_id = H5P_OBJECT_COPY_DEFAULT; + else if (TRUE != H5P_isa_class(ocpypl_id, H5P_OBJECT_COPY)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not object copy property list") + + /* Set the LCPL for the API context */ + H5CX_set_lcpl(lcpl_id); + + if (H5VL_setup_loc_args(src_loc_id, &vol_obj1, &loc_params1) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set object access arguments") + + /* get the object */ + if (NULL == (*vol_obj_ptr = (H5VL_object_t *)H5I_object(dst_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") + loc_params2.type = H5VL_OBJECT_BY_SELF; + loc_params2.obj_type = H5I_get_type(dst_loc_id); + + /* Copy the object */ + if (H5VL_object_copy(vol_obj1, &loc_params1, src_name, *vol_obj_ptr, &loc_params2, dst_name, ocpypl_id, + lcpl_id, H5P_DATASET_XFER_DEFAULT, token_ptr) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O__copy_api_common() */ + +/*------------------------------------------------------------------------- * Function: H5Ocopy * * Purpose: Copy an object (group or dataset) to destination location @@ -340,60 +542,95 @@ herr_t H5Ocopy(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id) { - H5VL_object_t * vol_obj1 = NULL; /* object of src_id */ - H5VL_loc_params_t loc_params1; - H5VL_object_t * vol_obj2 = NULL; /* object of dst_id */ - H5VL_loc_params_t loc_params2; - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE6("e", "i*si*sii", src_loc_id, src_name, dst_loc_id, dst_name, ocpypl_id, lcpl_id); - /* Check arguments */ - if (!src_name || !*src_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no source name specified") - if (!dst_name || !*dst_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no destination name specified") - - /* Get correct property lists */ - if (H5P_DEFAULT == lcpl_id) - lcpl_id = H5P_LINK_CREATE_DEFAULT; - else if (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link creation property list") + /* To copy an object synchronously */ + if (H5O__copy_api_common(src_loc_id, src_name, dst_loc_id, dst_name, ocpypl_id, lcpl_id, NULL, NULL) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to synchronously copy object") - /* Get object copy property list */ - if (H5P_DEFAULT == ocpypl_id) - ocpypl_id = H5P_OBJECT_COPY_DEFAULT; - else if (TRUE != H5P_isa_class(ocpypl_id, H5P_OBJECT_COPY)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not object copy property list") +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Ocopy() */ - /* Set the LCPL for the API context */ - H5CX_set_lcpl(lcpl_id); +/*------------------------------------------------------------------------- + * Function: H5Ocopy_async + * + * Purpose: Asynchronous version of H5Ocopy + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5Ocopy_async(const char *app_file, const char *app_func, unsigned app_line, hid_t src_loc_id, + const char *src_name, hid_t dst_loc_id, const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id, + hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ - /* Set up collective metadata if appropriate */ - if (H5CX_set_loc(src_loc_id) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set collective metadata read info") + FUNC_ENTER_API(FAIL) + H5TRACE10("e", "*s*sIui*si*siii", app_file, app_func, app_line, src_loc_id, src_name, dst_loc_id, + dst_name, ocpypl_id, lcpl_id, es_id); - /* get the object */ - if (NULL == (vol_obj1 = (H5VL_object_t *)H5I_object(src_loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") - loc_params1.type = H5VL_OBJECT_BY_SELF; - loc_params1.obj_type = H5I_get_type(src_loc_id); + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ - /* get the object */ - if (NULL == (vol_obj2 = (H5VL_object_t *)H5I_object(dst_loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") - loc_params2.type = H5VL_OBJECT_BY_SELF; - loc_params2.obj_type = H5I_get_type(dst_loc_id); + /* To copy an object asynchronously */ + if (H5O__copy_api_common(src_loc_id, src_name, dst_loc_id, dst_name, ocpypl_id, lcpl_id, token_ptr, + &vol_obj) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to asynchronously copy object") - /* Copy the object */ - if (H5VL_object_copy(vol_obj1, &loc_params1, src_name, vol_obj2, &loc_params2, dst_name, ocpypl_id, - lcpl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE10(FUNC, "*s*sIui*si*siii", app_file, app_func, app_line, src_loc_id, + src_name, dst_loc_id, dst_name, ocpypl_id, lcpl_id, es_id)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert token into event set") done: FUNC_LEAVE_API(ret_value) -} /* end H5Ocopy() */ +} /* H5Ocopy_async() */ + +/*------------------------------------------------------------------------- + * Function: H5O__flush_api_common + * + * Purpose: This is the common function for flushing an object. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O__flush_api_common(hid_t obj_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check args */ + + if (H5VL_setup_loc_args(obj_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set object access arguments") + + /* Flush the object */ + if (H5VL_object_specific(*vol_obj_ptr, &loc_params, H5VL_OBJECT_FLUSH, H5P_DATASET_XFER_DEFAULT, + token_ptr, obj_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O__flush_api_common() */ /*------------------------------------------------------------------------- * Function: H5Oflush @@ -410,33 +647,90 @@ done: herr_t H5Oflush(hid_t obj_id) { - H5VL_object_t * vol_obj = NULL; /* Object of obj_id */ - H5VL_loc_params_t loc_params; - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE1("e", "i", obj_id); - /* Check args */ - if (NULL == (vol_obj = H5VL_vol_object(obj_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier") + /* To flush an object synchronously */ + if (H5O__flush_api_common(obj_id, NULL, NULL) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to synchronously flush object") - /* Set up collective metadata if appropriate */ - if (H5CX_set_loc(obj_id) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access property list info") +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Oflush() */ - /* Set location parameters */ - loc_params.type = H5VL_OBJECT_BY_SELF; - loc_params.obj_type = H5I_get_type(obj_id); +/*------------------------------------------------------------------------- + * Function: H5Oflush_async + * + * Purpose: Asynchronous version of H5Oflush + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5Oflush_async(const char *app_file, const char *app_func, unsigned app_line, hid_t obj_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ - /* Flush the object */ - if (H5VL_object_specific(vol_obj, &loc_params, H5VL_OBJECT_FLUSH, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL, obj_id) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object") + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "*s*sIuii", app_file, app_func, app_line, obj_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Flush an object asynchronously */ + if (H5O__flush_api_common(obj_id, token_ptr, &vol_obj) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to asynchronously flush object") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE5(FUNC, "*s*sIuii", app_file, app_func, app_line, obj_id, es_id)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert token into event set") done: FUNC_LEAVE_API(ret_value) -} /* end H5Oflush() */ +} /* H5Oflush_async() */ + +/*------------------------------------------------------------------------- + * Function: H5O__refresh_api_common + * + * Purpose: This is the common function for refreshing an object. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O__refresh_api_common(hid_t oid, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check args */ + + if (H5VL_setup_loc_args(oid, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set object access arguments") + + /* Refresh the object */ + if (H5VL_object_specific(*vol_obj_ptr, &loc_params, H5VL_OBJECT_REFRESH, H5P_DATASET_XFER_DEFAULT, + token_ptr, oid) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to refresh object") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O__refresh_api_common() */ /*------------------------------------------------------------------------- * Function: H5Orefresh @@ -453,33 +747,56 @@ done: herr_t H5Orefresh(hid_t oid) { - H5VL_object_t * vol_obj = NULL; /* Object of oid */ - H5VL_loc_params_t loc_params; - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE1("e", "i", oid); - /* Check args */ - if (NULL == (vol_obj = H5VL_vol_object(oid))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier") + /* To refresh an object synchronously */ + if (H5O__refresh_api_common(oid, NULL, NULL) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to synchronously refresh object") - /* Set up collective metadata if appropriate */ - if (H5CX_set_loc(oid) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access property list info") +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Orefresh() */ - /* Set location parameters */ - loc_params.type = H5VL_OBJECT_BY_SELF; - loc_params.obj_type = H5I_get_type(oid); +/*------------------------------------------------------------------------- + * Function: H5Orefresh_async + * + * Purpose: Asynchronous version of H5Orefresh + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5Orefresh_async(const char *app_file, const char *app_func, unsigned app_line, hid_t oid, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ - /* Refresh the object */ - if (H5VL_object_specific(vol_obj, &loc_params, H5VL_OBJECT_REFRESH, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL, oid) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to refresh object") + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "*s*sIuii", app_file, app_func, app_line, oid, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Refresh an object asynchronously */ + if (H5O__refresh_api_common(oid, token_ptr, &vol_obj) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to asynchronously refresh object") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE5(FUNC, "*s*sIuii", app_file, app_func, app_line, oid, es_id)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert token into event set") done: FUNC_LEAVE_API(ret_value) -} /* end H5Orefresh() */ +} /* H5Orefresh_async() */ /*------------------------------------------------------------------------- * Function: H5Olink @@ -774,6 +1091,48 @@ done: } /* end H5Oget_info3() */ /*------------------------------------------------------------------------- + * Function: H5O__get_info_by_name_api_common + * + * Purpose: This is the common function for retrieving information + * about an object. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O__get_info_by_name_api_common(hid_t loc_id, const char *name, H5O_info2_t *oinfo /*out*/, unsigned fields, + hid_t lapl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr) +{ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters for object access */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check args */ + if (!oinfo) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "oinfo parameter cannot be NULL") + if (fields & ~H5O_INFO_ALL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid fields") + + /* "name" is checked in H5VL_setup_name_args() */ + /* Set up object access arguments */ + if (H5VL_setup_name_args(loc_id, name, H5P_CLS_LACC, FALSE, lapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set object access arguments") + + /* Retrieve the object's information */ + if (H5VL_object_get(*vol_obj_ptr, &loc_params, H5VL_OBJECT_GET_INFO, H5P_DATASET_XFER_DEFAULT, token_ptr, + oinfo, fields) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get data model info for object") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O__get_info_by_name_api_common() */ + +/*------------------------------------------------------------------------- * Function: H5Oget_info_by_name3 * * Purpose: Retrieve information about an object @@ -789,45 +1148,60 @@ herr_t H5Oget_info_by_name3(hid_t loc_id, const char *name, H5O_info2_t *oinfo /*out*/, unsigned fields, hid_t lapl_id) { - H5VL_object_t * vol_obj; /* Object of loc_id */ - H5VL_loc_params_t loc_params; - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE5("e", "i*sxIui", loc_id, name, oinfo, fields, lapl_id); - /* 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 (!oinfo) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "oinfo parameter cannot be NULL") - if (fields & ~H5O_INFO_ALL) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid fields") + /* Retrieve object information synchronously */ + if (H5O__get_info_by_name_api_common(loc_id, name, oinfo, fields, lapl_id, NULL, NULL) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't synchronously retrieve object info") - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access property list info") +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Oget_info_by_name3() */ - /* Fill out location struct */ - 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); +/*------------------------------------------------------------------------- + * Function: H5Oget_info_by_name_async + * + * Purpose: Asynchronous version of H5Oget_info_by_name3 + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5Oget_info_by_name_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *name, H5O_info2_t *oinfo /*out*/, unsigned fields, hid_t lapl_id, + hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ - /* Get the location object */ - if (NULL == (vol_obj = H5VL_vol_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") + FUNC_ENTER_API(FAIL) + H5TRACE9("e", "*s*sIui*sxIuii", app_file, app_func, app_line, loc_id, name, oinfo, fields, lapl_id, + es_id); - /* Retrieve the object's information */ - if (H5VL_object_get(vol_obj, &loc_params, H5VL_OBJECT_GET_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, - oinfo, fields) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get data model info for object") + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Retrieve group information asynchronously */ + if (H5O__get_info_by_name_api_common(loc_id, name, oinfo, fields, lapl_id, token_ptr, &vol_obj) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't asynchronously retrieve object info") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE9(FUNC, "*s*sIui*sxIuii", app_file, app_func, app_line, loc_id, name, + oinfo, fields, lapl_id, es_id)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert token into event set") done: FUNC_LEAVE_API(ret_value) -} /* end H5Oget_info_by_name3() */ +} /* H5Oget_info_by_name_async() */ /*------------------------------------------------------------------------- * Function: H5Oget_info_by_idx3 @@ -1411,29 +1785,21 @@ done: } /* end H5Ovisit_by_name3() */ /*------------------------------------------------------------------------- - * Function: H5Oclose - * - * Purpose: Close an open file object. - * - * This is the companion to H5Oopen. It is used to close any - * open object in an HDF5 file (but not IDs are that not file - * objects, such as property lists and dataspaces). It has - * the same effect as calling H5Gclose, H5Dclose, or H5Tclose. + * Function: H5O__close_check_common * - * Return: SUCCEED/FAIL + * Purpose: This is the common function to validate an object + * when closing it. * - * Programmer: James Laird - * July 14 2006 + * Return: TRUE/FALSE/FAIL * *------------------------------------------------------------------------- */ -herr_t -H5Oclose(hid_t object_id) +static htri_t +H5O__close_check_common(hid_t object_id) { - herr_t ret_value = SUCCEED; + htri_t ret_value = TRUE; /* Return value */ - FUNC_ENTER_API(FAIL) - H5TRACE1("e", "i", object_id); + FUNC_ENTER_STATIC /* Get the type of the object and close it in the correct way */ switch (H5I_get_type(object_id)) { @@ -1443,8 +1809,6 @@ H5Oclose(hid_t object_id) case H5I_MAP: if (H5I_object(object_id) == NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid object") - if (H5I_dec_app_ref(object_id) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to close object") break; case H5I_UNINIT: @@ -1460,18 +1824,114 @@ H5Oclose(hid_t object_id) 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_CANTRELEASE, FAIL, + HGOTO_ERROR(H5E_ARGS, H5E_CANTRELEASE, FALSE, "not a valid file object ID (dataset, group, or datatype)") break; } /* end switch */ done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O__close_api_common() */ + +/*------------------------------------------------------------------------- + * Function: H5Oclose + * + * Purpose: Close an open file object. + * + * This is the companion to H5Oopen. It is used to close any + * open object in an HDF5 file (but not IDs are that not file + * objects, such as property lists and dataspaces). It has + * the same effect as calling H5Gclose, H5Dclose, or H5Tclose. + * + * Return: SUCCEED/FAIL + * + * Programmer: James Laird + * July 14 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Oclose(hid_t object_id) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE1("e", "i", object_id); + + /* Validate the object type before closing */ + if (H5O__close_check_common(object_id) <= 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "not a valid object") + + if (H5I_dec_app_ref(object_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to close object") + +done: FUNC_LEAVE_API(ret_value) } /* end H5Oclose() */ /*------------------------------------------------------------------------- + * Function: H5Oclose_async + * + * Purpose: Asynchronous version of H5Oclose + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5Oclose_async(const char *app_file, const char *app_func, unsigned app_line, hid_t object_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + H5VL_t * connector = NULL; /* VOL connector */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "*s*sIuii", app_file, app_func, app_line, object_id, es_id); + + /* Validate the object type before closing */ + if (H5O__close_check_common(object_id) <= 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "not a valid object") + + /* Prepare for possible asynchronous operation */ + if (H5ES_NONE != es_id) { + /* Get file object's connector */ + if (NULL == (vol_obj = H5VL_vol_object(object_id))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get VOL object for object") + + /* Increase connector's refcount, so it doesn't get closed if closing + * this object ID closes the file */ + connector = vol_obj->connector; + H5VL_conn_inc_rc(connector); + + /* Point at token for operation to set up */ + token_ptr = &token; + } /* end if */ + + /* Asynchronously decrement reference count on ID. + * When it reaches zero the object will be closed. + */ + if (H5I_dec_app_ref_async(object_id, token_ptr) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCLOSEFILE, FAIL, "decrementing object ID failed") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE5(FUNC, "*s*sIuii", app_file, app_func, app_line, object_id, es_id)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + if (connector && H5VL_conn_dec_rc(connector) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "can't decrement ref count on connector") + + FUNC_LEAVE_API(ret_value) +} /* end H5Oclose_async() */ + +/*------------------------------------------------------------------------- * Function: H5O_disable_mdc_flushes * * Purpose: Private version of the metadata cache cork function. diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c index bf75634..6749459 100644 --- a/src/H5Oattribute.c +++ b/src/H5Oattribute.c @@ -93,6 +93,15 @@ typedef struct { hbool_t found; /* Found attribute to delete */ } H5O_iter_rm_t; +/* User data for iteration when checking if an attribute exists */ +typedef struct { + /* down */ + const char *name; /* Name of attribute to open */ + + /* up */ + hbool_t *exists; /* Pointer to flag to indicate attribute exists */ +} H5O_iter_xst_t; + /********************/ /* Package Typedefs */ /********************/ @@ -1723,19 +1732,19 @@ static herr_t H5O__attr_exists_cb(H5O_t H5_ATTR_UNUSED *oh, H5O_mesg_t *mesg /*in,out*/, unsigned H5_ATTR_UNUSED sequence, unsigned H5_ATTR_UNUSED *oh_modified, void *_udata /*in,out*/) { - H5O_iter_rm_t *udata = (H5O_iter_rm_t *)_udata; /* Operator user data */ - herr_t ret_value = H5_ITER_CONT; /* Return value */ + H5O_iter_xst_t *udata = (H5O_iter_xst_t *)_udata; /* Operator user data */ + herr_t ret_value = H5_ITER_CONT; /* Return value */ FUNC_ENTER_STATIC_NOERR /* check args */ HDassert(mesg); - HDassert(!udata->found); + HDassert(udata->exists && !*udata->exists); /* Check for correct attribute message */ if (HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->name) == 0) { /* Indicate that this message is the attribute sought */ - udata->found = TRUE; + *udata->exists = TRUE; /* Stop iterating */ ret_value = H5_ITER_STOP; @@ -1756,18 +1765,19 @@ H5O__attr_exists_cb(H5O_t H5_ATTR_UNUSED *oh, H5O_mesg_t *mesg /*in,out*/, unsig * *------------------------------------------------------------------------- */ -htri_t -H5O__attr_exists(const H5O_loc_t *loc, const char *name) +herr_t +H5O__attr_exists(const H5O_loc_t *loc, const char *name, hbool_t *attr_exists) { - H5O_t * oh = NULL; /* Pointer to actual object header */ - H5O_ainfo_t ainfo; /* Attribute information for object */ - htri_t ret_value = FAIL; /* Return value */ + H5O_t * oh = NULL; /* Pointer to actual object header */ + H5O_ainfo_t ainfo; /* Attribute information for object */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE_TAG(loc->addr) /* Check arguments */ HDassert(loc); HDassert(name); + HDassert(attr_exists); /* Protect the object header to iterate over */ if (NULL == (oh = H5O_protect(loc, H5AC__READ_ONLY_FLAG, FALSE))) @@ -1784,26 +1794,22 @@ H5O__attr_exists(const H5O_loc_t *loc, const char *name) /* Check for attributes stored densely */ if (H5F_addr_defined(ainfo.fheap_addr)) { /* Check if attribute exists in dense storage */ - if ((ret_value = H5A__dense_exists(loc->file, &ainfo, name)) < 0) + if (H5A__dense_exists(loc->file, &ainfo, name, attr_exists) < 0) HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error checking for existence of attribute") } /* end if */ else { - H5O_iter_rm_t udata; /* User data for callback */ + H5O_iter_xst_t udata; /* User data for callback */ H5O_mesg_operator_t op; /* Wrapper for operator */ /* Set up user data for callback */ - udata.f = loc->file; - udata.name = name; - udata.found = FALSE; + udata.name = name; + udata.exists = attr_exists; /* Iterate over existing attributes, checking for attribute with same name */ op.op_type = H5O_MESG_OP_LIB; op.u.lib_op = H5O__attr_exists_cb; if (H5O__msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, &op, &udata) < 0) HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error checking for existence of attribute") - - /* Check that we found the attribute */ - ret_value = (htri_t)udata.found; } /* end else */ done: diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c index c6f54d7..e0e47e3 100644 --- a/src/H5Ocopy.c +++ b/src/H5Ocopy.c @@ -33,6 +33,7 @@ #include "H5Aprivate.h" /* Attributes */ #include "H5CXprivate.h" /* API Contexts */ #include "H5Eprivate.h" /* Error handling */ +#include "H5ESprivate.h" /* Event Sets */ #include "H5FLprivate.h" /* Free lists */ #include "H5Iprivate.h" /* IDs */ #include "H5HGprivate.h" /* Global Heaps */ @@ -129,7 +130,7 @@ H5O__copy(const H5G_loc_t *loc, const char *src_name, H5G_loc_t *dst_loc, const H5G_loc_t src_loc; /* Source object group location */ H5G_name_t src_path; /* Opened source object hier. path */ H5O_loc_t src_oloc; /* Opened source object object location */ - htri_t dst_exists; /* Does destination name exist already? */ + hbool_t dst_exists; /* Does destination name exist already? */ hbool_t loc_found = FALSE; /* Location at 'name' found */ hbool_t obj_open = FALSE; /* Entry at 'name' found */ herr_t ret_value = SUCCEED; /* Return value */ @@ -143,9 +144,10 @@ H5O__copy(const H5G_loc_t *loc, const char *src_name, H5G_loc_t *dst_loc, const HDassert(dst_name && *dst_name); /* Check if destination name already exists */ - if ((dst_exists = H5L_exists_tolerant(dst_loc, dst_name)) < 0) + dst_exists = FALSE; + if (H5L_exists_tolerant(dst_loc, dst_name, &dst_exists) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to check if destination name exists") - if (TRUE == dst_exists) + if (dst_exists) HGOTO_ERROR(H5E_OHDR, H5E_EXISTS, FAIL, "destination object already exists") /* Set up opened group location to fill in */ diff --git a/src/H5Oflush.c b/src/H5Oflush.c index adbe4fa..c4a33d6 100644 --- a/src/H5Oflush.c +++ b/src/H5Oflush.c @@ -37,6 +37,7 @@ #include "H5CXprivate.h" /* API Contexts */ #include "H5Dprivate.h" /* Datasets */ #include "H5Eprivate.h" /* Errors */ +#include "H5ESprivate.h" /* Event Sets */ #include "H5Fprivate.h" /* Files */ #include "H5Gprivate.h" /* Groups */ #include "H5Iprivate.h" /* IDs */ @@ -400,6 +401,7 @@ H5O_refresh_metadata_reopen(hid_t oid, H5G_loc_t *obj_loc, H5VL_t *vol_connector case H5I_ERROR_MSG: case H5I_ERROR_STACK: case H5I_SPACE_SEL_ITER: + case H5I_EVENTSET: case H5I_NTYPES: default: HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, FAIL, diff --git a/src/H5Oint.c b/src/H5Oint.c index b966b45..3b8193c 100644 --- a/src/H5Oint.c +++ b/src/H5Oint.c @@ -1827,6 +1827,7 @@ H5O_get_loc(hid_t object_id) case H5I_ERROR_MSG: case H5I_ERROR_STACK: case H5I_SPACE_SEL_ITER: + case H5I_EVENTSET: case H5I_NTYPES: default: HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, NULL, "invalid object type") diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 8e338cc..d2aed18 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -29,22 +29,22 @@ typedef struct H5O_t H5O_t; typedef struct H5O_fill_t H5O_fill_t; /* Include the public header file for this API */ -#include "H5Opublic.h" /* Object header functions */ +#include "H5Opublic.h" /* Object header functions */ /* Public headers needed by this file */ -#include "H5Dpublic.h" /* Dataset functions */ -#include "H5Lpublic.h" /* Link functions */ -#include "H5Spublic.h" /* Dataspace functions */ +#include "H5Dpublic.h" /* Dataset functions */ +#include "H5Lpublic.h" /* Link functions */ +#include "H5Spublic.h" /* Dataspace functions */ /* Private headers needed by this file */ -#include "H5private.h" /* Generic Functions */ +#include "H5private.h" /* Generic Functions */ #include "H5ACprivate.h" /* Metadata cache */ -#include "H5Fprivate.h" /* File access */ +#include "H5Fprivate.h" /* File access */ #include "H5HGprivate.h" /* Global Heaps */ #include "H5SLprivate.h" /* Skip lists */ -#include "H5Tprivate.h" /* Datatype functions */ +#include "H5Tprivate.h" /* Datatype functions */ #include "H5VLprivate.h" /* Virtual Object Layer */ -#include "H5Zprivate.h" /* I/O pipeline filters */ +#include "H5Zprivate.h" /* I/O pipeline filters */ /* Forward references of package typedefs */ typedef struct H5O_msg_class_t H5O_msg_class_t; @@ -67,8 +67,8 @@ typedef struct H5O_mesg_t H5O_mesg_t; /* Object header macros */ #define H5O_MESG_MAX_SIZE 65536 /*max obj header message size */ -#define H5O_ALL (-1) /* Operate on all messages of type */ -#define H5O_FIRST (-2) /* Operate on first message of type */ +#define H5O_ALL (-1) /* Operate on all messages of type */ +#define H5O_FIRST (-2) /* Operate on first message of type */ /* Flags needed when encoding messages */ #define H5O_MSG_NO_FLAGS_SET 0x00u @@ -96,10 +96,10 @@ typedef struct H5O_mesg_t H5O_mesg_t; /* #define H5O_ENABLE_BOGUS */ /* ========= Object Creation properties ============ */ -#define H5O_CRT_ATTR_MAX_COMPACT_NAME "max compact attr" /* Max. # of attributes to store compactly */ -#define H5O_CRT_ATTR_MIN_DENSE_NAME "min dense attr" /* Min. # of attributes to store densely */ +#define H5O_CRT_ATTR_MAX_COMPACT_NAME "max compact attr" /* Max. # of attributes to store compactly */ +#define H5O_CRT_ATTR_MIN_DENSE_NAME "min dense attr" /* Min. # of attributes to store densely */ #define H5O_CRT_OHDR_FLAGS_NAME "object header flags" /* Object header flags */ -#define H5O_CRT_PIPELINE_NAME "pline" /* Filter pipeline */ +#define H5O_CRT_PIPELINE_NAME "pline" /* Filter pipeline */ #define H5O_CRT_PIPELINE_DEF \ { \ {0, NULL, H5O_NULL_ID, {{0, HADDR_UNDEF}}}, H5O_PLINE_VERSION_1, 0, 0, NULL \ @@ -232,7 +232,7 @@ typedef struct H5O_copy_t { #define H5O_FSINFO_ID 0x0017 /* File space info message. */ #define H5O_MDCI_MSG_ID 0x0018 /* Metadata Cache Image Message */ #define H5O_UNKNOWN_ID 0x0019 /* Placeholder message ID for unknown message. */ - /* (this should never exist in a file) */ +/* (this should never exist in a file) */ /* * Note: Must increment H5O_MSG_TYPES in H5Opkg.h and update H5O_msg_class_g * in H5O.c when creating a new message type. Also bump the value of @@ -376,7 +376,7 @@ typedef struct H5O_link_t { * External File List Message * (Data structure in memory) */ -#define H5O_EFL_ALLOC 16 /*number of slots to alloc at once */ +#define H5O_EFL_ALLOC 16 /*number of slots to alloc at once */ #define H5O_EFL_UNLIMITED H5F_UNLIMITED /*max possible file size */ typedef struct H5O_efl_entry_t { diff --git a/src/H5Opublic.h b/src/H5Opublic.h index 64408a0..2d2abdf 100644 --- a/src/H5Opublic.h +++ b/src/H5Opublic.h @@ -182,30 +182,41 @@ typedef H5O_mcdt_search_ret_t (*H5O_mcdt_search_cb_t)(void *op_data); extern "C" { #endif -H5_DLL hid_t H5Oopen(hid_t loc_id, const char *name, hid_t lapl_id); -H5_DLL hid_t H5Oopen_by_token(hid_t loc_id, H5O_token_t token); -H5_DLL hid_t H5Oopen_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type, H5_iter_order_t order, - hsize_t n, hid_t lapl_id); -H5_DLL htri_t H5Oexists_by_name(hid_t loc_id, const char *name, hid_t lapl_id); -H5_DLL herr_t H5Oget_info3(hid_t loc_id, H5O_info2_t *oinfo, unsigned fields); -H5_DLL herr_t H5Oget_info_by_name3(hid_t loc_id, const char *name, H5O_info2_t *oinfo, unsigned fields, +H5_DLL hid_t H5Oopen(hid_t loc_id, const char *name, hid_t lapl_id); +H5_DLL hid_t H5Oopen_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *name, hid_t lapl_id, hid_t es_id); +H5_DLL hid_t H5Oopen_by_token(hid_t loc_id, H5O_token_t token); +H5_DLL hid_t H5Oopen_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type, H5_iter_order_t order, + hsize_t n, hid_t lapl_id); +H5_DLL hid_t H5Oopen_by_idx_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *group_name, H5_index_t idx_type, H5_iter_order_t order, + hsize_t n, hid_t lapl_id, hid_t es_id); +H5_DLL htri_t H5Oexists_by_name(hid_t loc_id, const char *name, hid_t lapl_id); +H5_DLL herr_t H5Oget_info3(hid_t loc_id, H5O_info2_t *oinfo, unsigned fields); +H5_DLL herr_t H5Oget_info_by_name3(hid_t loc_id, const char *name, H5O_info2_t *oinfo, unsigned fields, + hid_t lapl_id); +H5_DLL herr_t H5Oget_info_by_name_async(const char *app_file, const char *app_func, unsigned app_line, + hid_t loc_id, const char *name, H5O_info2_t *oinfo /*out*/, + unsigned fields, hid_t lapl_id, hid_t es_id); +H5_DLL herr_t H5Oget_info_by_idx3(hid_t loc_id, const char *group_name, H5_index_t idx_type, + H5_iter_order_t order, hsize_t n, H5O_info2_t *oinfo, unsigned fields, hid_t lapl_id); -H5_DLL herr_t H5Oget_info_by_idx3(hid_t loc_id, const char *group_name, H5_index_t idx_type, - H5_iter_order_t order, hsize_t n, H5O_info2_t *oinfo, unsigned fields, - hid_t lapl_id); -H5_DLL herr_t H5Oget_native_info(hid_t loc_id, H5O_native_info_t *oinfo, unsigned fields); -H5_DLL herr_t H5Oget_native_info_by_name(hid_t loc_id, const char *name, H5O_native_info_t *oinfo, +H5_DLL herr_t H5Oget_native_info(hid_t loc_id, H5O_native_info_t *oinfo, unsigned fields); +H5_DLL herr_t H5Oget_native_info_by_name(hid_t loc_id, const char *name, H5O_native_info_t *oinfo, + unsigned fields, hid_t lapl_id); +H5_DLL herr_t H5Oget_native_info_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type, + H5_iter_order_t order, hsize_t n, H5O_native_info_t *oinfo, unsigned fields, hid_t lapl_id); -H5_DLL herr_t H5Oget_native_info_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type, - H5_iter_order_t order, hsize_t n, H5O_native_info_t *oinfo, - unsigned fields, hid_t lapl_id); -H5_DLL herr_t H5Olink(hid_t obj_id, hid_t new_loc_id, const char *new_name, hid_t lcpl_id, hid_t lapl_id); -H5_DLL herr_t H5Oincr_refcount(hid_t object_id); -H5_DLL herr_t H5Odecr_refcount(hid_t object_id); -H5_DLL herr_t H5Ocopy(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, const char *dst_name, - hid_t ocpypl_id, hid_t lcpl_id); -H5_DLL herr_t H5Oset_comment(hid_t obj_id, const char *comment); -H5_DLL herr_t H5Oset_comment_by_name(hid_t loc_id, const char *name, const char *comment, hid_t lapl_id); +H5_DLL herr_t H5Olink(hid_t obj_id, hid_t new_loc_id, const char *new_name, hid_t lcpl_id, hid_t lapl_id); +H5_DLL herr_t H5Oincr_refcount(hid_t object_id); +H5_DLL herr_t H5Odecr_refcount(hid_t object_id); +H5_DLL herr_t H5Ocopy(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, const char *dst_name, + hid_t ocpypl_id, hid_t lcpl_id); +H5_DLL herr_t H5Ocopy_async(const char *app_file, const char *app_func, unsigned app_line, hid_t src_loc_id, + const char *src_name, hid_t dst_loc_id, const char *dst_name, hid_t ocpypl_id, + hid_t lcpl_id, hid_t es_id); +H5_DLL herr_t H5Oset_comment(hid_t obj_id, const char *comment); +H5_DLL herr_t H5Oset_comment_by_name(hid_t loc_id, const char *name, const char *comment, hid_t lapl_id); H5_DLL ssize_t H5Oget_comment(hid_t obj_id, char *comment, size_t bufsize); H5_DLL ssize_t H5Oget_comment_by_name(hid_t loc_id, const char *name, char *comment, size_t bufsize, hid_t lapl_id); @@ -215,8 +226,14 @@ H5_DLL herr_t H5Ovisit_by_name3(hid_t loc_id, const char *obj_name, H5_index_t H5_iter_order_t order, H5O_iterate2_t op, void *op_data, unsigned fields, hid_t lapl_id); H5_DLL herr_t H5Oclose(hid_t object_id); +H5_DLL herr_t H5Oclose_async(const char *app_file, const char *app_func, unsigned app_line, hid_t object_id, + hid_t es_id); H5_DLL herr_t H5Oflush(hid_t obj_id); +H5_DLL herr_t H5Oflush_async(const char *app_file, const char *app_func, unsigned app_line, hid_t obj_id, + hid_t es_id); H5_DLL herr_t H5Orefresh(hid_t oid); +H5_DLL herr_t H5Orefresh_async(const char *app_file, const char *app_func, unsigned app_line, hid_t oid, + hid_t es_id); H5_DLL herr_t H5Odisable_mdc_flushes(hid_t object_id); H5_DLL herr_t H5Oenable_mdc_flushes(hid_t object_id); H5_DLL herr_t H5Oare_mdc_flushes_disabled(hid_t object_id, hbool_t *are_disabled); @@ -225,6 +242,30 @@ H5_DLL herr_t H5Otoken_cmp(hid_t loc_id, const H5O_token_t *token1, const H5O_t H5_DLL herr_t H5Otoken_to_str(hid_t loc_id, const H5O_token_t *token, char **token_str); H5_DLL herr_t H5Otoken_from_str(hid_t loc_id, const char *token_str, H5O_token_t *token); +/* API Wrappers for async routines */ +/* (Must be defined _after_ the function prototype) */ +/* (And must only defined when included in application code, not the library) */ +#ifndef H5O_MODULE +#define H5Oopen_async(...) H5Oopen_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Oopen_by_idx_async(...) H5Oopen_by_idx_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Oget_info_by_name_async(...) H5Oget_info_by_name_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Oclose_async(...) H5Oclose_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Oflush_async(...) H5Oflush_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Orefresh_async(...) H5Orefresh_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Ocopy_async(...) H5Ocopy_async(__FILE__, __func__, __LINE__, __VA_ARGS__) + +/* Define "wrapper" versions of function calls, to allow compile-time values to + * be passed in by language wrapper or library layer on top of HDF5. + */ +#define H5Oopen_async_wrap H5_NO_EXPAND(H5Oopen_async) +#define H5Oopen_by_idx_async_wrap H5_NO_EXPAND(H5Oopen_by_idx_async) +#define H5Oget_info_by_name_async_wrap H5_NO_EXPAND(H5Oget_info_by_name_async) +#define H5Oclose_async_wrap H5_NO_EXPAND(H5Oclose_async) +#define H5Oflush_async_wrap H5_NO_EXPAND(H5Oflush_async) +#define H5Orefresh_async_wrap H5_NO_EXPAND(H5Orefresh_async) +#define H5Ocopy_async_wrap H5_NO_EXPAND(H5Ocopy_async) +#endif + /* The canonical 'undefined' token value */ #define H5O_TOKEN_UNDEF (H5OPEN H5O_TOKEN_UNDEF_g) H5_DLLVAR const H5O_token_t H5O_TOKEN_UNDEF_g; diff --git a/src/H5PLpublic.h b/src/H5PLpublic.h index a08c78d..f61ad48 100644 --- a/src/H5PLpublic.h +++ b/src/H5PLpublic.h @@ -99,10 +99,8 @@ H5_DLL herr_t H5PLset_loading_state(unsigned int plugin_control_mask); * disabled.\n * A plugin bit set to 1 (one) indicates that that the dynamic plugin type is * enabled.\n - * If the value of \p plugin_control_mask is negative, all dynamic plugin types - * are enabled.\n - * If the value of \p plugin_control_mask is 0 (zero), all dynamic plugins - * are disabled. + * If the value of \p plugin_control_mask is negative, all dynamic plugin + * types are enabled.\n If the value of \p plugin_control_mask is 0 (zero), all dynamic plugins are disabled. * \return \herr_t * * \details H5PLget_loading_state() retrieves the bitmask that controls whether a certain type of plugins diff --git a/src/H5Ppkg.h b/src/H5Ppkg.h index 157e34a..4013c0a 100644 --- a/src/H5Ppkg.h +++ b/src/H5Ppkg.h @@ -86,7 +86,8 @@ struct H5P_genclass_t { char * name; /* Name of property list class */ H5P_plist_type_t type; /* Type of property */ size_t nprops; /* Number of properties in class */ - unsigned plists; /* Number of property lists that have been created since the last modification to the class */ + unsigned + plists; /* Number of property lists that have been created since the last modification to the class */ unsigned classes; /* Number of classes that have been derived since the last modification to the class */ unsigned ref_count; /* Number of outstanding ID's open on this class object */ hbool_t deleted; /* Whether this class has been deleted and is waiting for dependent classes & proplists diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index a978895..6493895 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -374,7 +374,7 @@ H5_DLL herr_t H5Pclose(hid_t plist_id); * \since 1.0.0 * */ -H5_DLL hid_t H5Pcreate(hid_t cls_id); +H5_DLL hid_t H5Pcreate(hid_t cls_id); H5_DLL hid_t H5Pcreate_class(hid_t parent, const char *name, H5P_cls_create_func_t cls_create, void *create_data, H5P_cls_copy_func_t cls_copy, void *copy_data, H5P_cls_close_func_t cls_close, void *close_data); @@ -472,30 +472,27 @@ H5_DLL hid_t H5Pcopy(hid_t plist_id); * \since 1.8.0 * */ -H5_DLL H5Z_filter_t H5Pget_filter2(hid_t plist_id, unsigned idx, - unsigned int *flags/*out*/, - size_t *cd_nelmts/*out*/, - unsigned cd_values[]/*out*/, - size_t namelen, char name[], - unsigned *filter_config /*out*/); -H5_DLL herr_t H5Pset_attr_phase_change(hid_t plist_id, unsigned max_compact, unsigned min_dense); -H5_DLL herr_t H5Pget_attr_phase_change(hid_t plist_id, unsigned *max_compact, unsigned *min_dense); -H5_DLL herr_t H5Pset_attr_creation_order(hid_t plist_id, unsigned crt_order_flags); -H5_DLL herr_t H5Pget_attr_creation_order(hid_t plist_id, unsigned *crt_order_flags); -H5_DLL herr_t H5Pset_obj_track_times(hid_t plist_id, hbool_t track_times); -H5_DLL herr_t H5Pget_obj_track_times(hid_t plist_id, hbool_t *track_times); +H5_DLL H5Z_filter_t H5Pget_filter2(hid_t plist_id, unsigned idx, unsigned int *flags /*out*/, + size_t *cd_nelmts /*out*/, unsigned cd_values[] /*out*/, size_t namelen, + char name[], unsigned *filter_config /*out*/); +H5_DLL herr_t H5Pset_attr_phase_change(hid_t plist_id, unsigned max_compact, unsigned min_dense); +H5_DLL herr_t H5Pget_attr_phase_change(hid_t plist_id, unsigned *max_compact, unsigned *min_dense); +H5_DLL herr_t H5Pset_attr_creation_order(hid_t plist_id, unsigned crt_order_flags); +H5_DLL herr_t H5Pget_attr_creation_order(hid_t plist_id, unsigned *crt_order_flags); +H5_DLL herr_t H5Pset_obj_track_times(hid_t plist_id, hbool_t track_times); +H5_DLL herr_t H5Pget_obj_track_times(hid_t plist_id, hbool_t *track_times); H5_DLL herr_t H5Pmodify_filter(hid_t plist_id, H5Z_filter_t filter, unsigned int flags, size_t cd_nelmts, const unsigned int cd_values[/*cd_nelmts*/]); H5_DLL herr_t H5Pset_filter(hid_t plist_id, H5Z_filter_t filter, unsigned int flags, size_t cd_nelmts, const unsigned int c_values[]); H5_DLL int H5Pget_nfilters(hid_t plist_id); -H5_DLL herr_t H5Pget_filter_by_id2(hid_t plist_id, H5Z_filter_t id, unsigned int *flags /*out*/, - size_t *cd_nelmts /*out*/, unsigned cd_values[] /*out*/, size_t namelen, - char name[] /*out*/, unsigned *filter_config /*out*/); -H5_DLL htri_t H5Pall_filters_avail(hid_t plist_id); -H5_DLL herr_t H5Premove_filter(hid_t plist_id, H5Z_filter_t filter); -H5_DLL herr_t H5Pset_deflate(hid_t plist_id, unsigned aggression); -H5_DLL herr_t H5Pset_fletcher32(hid_t plist_id); +H5_DLL herr_t H5Pget_filter_by_id2(hid_t plist_id, H5Z_filter_t id, unsigned int *flags /*out*/, + size_t *cd_nelmts /*out*/, unsigned cd_values[] /*out*/, size_t namelen, + char name[] /*out*/, unsigned *filter_config /*out*/); +H5_DLL htri_t H5Pall_filters_avail(hid_t plist_id); +H5_DLL herr_t H5Premove_filter(hid_t plist_id, H5Z_filter_t filter); +H5_DLL herr_t H5Pset_deflate(hid_t plist_id, unsigned aggression); +H5_DLL herr_t H5Pset_fletcher32(hid_t plist_id); /* File creation property list (FCPL) routines */ H5_DLL herr_t H5Pset_userblock(hid_t plist_id, hsize_t size); @@ -610,7 +607,7 @@ H5_DLL herr_t H5Pget_page_buffer_size(hid_t plist_id, size_t *buf_size, unsigned * \since 1.0.0 * */ -H5_DLL int H5Pget_chunk(hid_t plist_id, int max_ndims, hsize_t dim[]/*out*/); +H5_DLL int H5Pget_chunk(hid_t plist_id, int max_ndims, hsize_t dim[] /*out*/); /** *------------------------------------------------------------------------- * @@ -683,8 +680,7 @@ H5_DLL herr_t H5Pget_chunk_opts(hid_t plist_id, unsigned *opts); * \since 1.6.0 * */ -H5_DLL herr_t H5Pget_fill_time(hid_t plist_id, H5D_fill_time_t - *fill_time/*out*/); +H5_DLL herr_t H5Pget_fill_time(hid_t plist_id, H5D_fill_time_t *fill_time /*out*/); /** *------------------------------------------------------------------------- * @@ -723,8 +719,7 @@ H5_DLL herr_t H5Pget_fill_time(hid_t plist_id, H5D_fill_time_t * \since 1.0.0 * */ -H5_DLL herr_t H5Pget_fill_value(hid_t plist_id, hid_t type_id, - void *value/*out*/); +H5_DLL herr_t H5Pget_fill_value(hid_t plist_id, hid_t type_id, void *value /*out*/); /** *------------------------------------------------------------------------- * \ingroup DCPL @@ -941,8 +936,7 @@ H5_DLL herr_t H5Pset_fill_time(hid_t plist_id, H5D_fill_time_t fill_time); * \since 1.0.0 * */ -H5_DLL herr_t H5Pset_fill_value(hid_t plist_id, hid_t type_id, - const void *value); +H5_DLL herr_t H5Pset_fill_value(hid_t plist_id, hid_t type_id, const void *value); /** *------------------------------------------------------------------------- * @@ -1173,25 +1167,25 @@ H5_DLL herr_t H5Pset_layout(hid_t plist_id, H5D_layout_t layout); * *-------------------------------------------------------------------------- */ -H5_DLL herr_t H5Pset_szip(hid_t plist_id, unsigned options_mask, unsigned pixels_per_block); -H5_DLL herr_t H5Pset_virtual(hid_t dcpl_id, hid_t vspace_id, const char *src_file_name, - const char *src_dset_name, hid_t src_space_id); -H5_DLL herr_t H5Pget_virtual_count(hid_t dcpl_id, size_t *count /*out*/); -H5_DLL hid_t H5Pget_virtual_vspace(hid_t dcpl_id, size_t index); -H5_DLL hid_t H5Pget_virtual_srcspace(hid_t dcpl_id, size_t index); -H5_DLL ssize_t H5Pget_virtual_filename(hid_t dcpl_id, size_t index, char *name /*out*/, size_t size); -H5_DLL ssize_t H5Pget_virtual_dsetname(hid_t dcpl_id, size_t index, char *name /*out*/, size_t size); -H5_DLL herr_t H5Pset_external(hid_t plist_id, const char *name, off_t offset, hsize_t size); -H5_DLL int H5Pget_external_count(hid_t plist_id); -H5_DLL herr_t H5Pget_external(hid_t plist_id, unsigned idx, size_t name_size, char *name /*out*/, - off_t *offset /*out*/, hsize_t *size /*out*/); -H5_DLL herr_t H5Pset_nbit(hid_t plist_id); -H5_DLL herr_t H5Pset_scaleoffset(hid_t plist_id, H5Z_SO_scale_type_t scale_type, int scale_factor); -H5_DLL herr_t H5Pfill_value_defined(hid_t plist, H5D_fill_value_t *status); -H5_DLL herr_t H5Pset_alloc_time(hid_t plist_id, H5D_alloc_time_t alloc_time); -H5_DLL herr_t H5Pget_alloc_time(hid_t plist_id, H5D_alloc_time_t *alloc_time /*out*/); -H5_DLL herr_t H5Pget_dset_no_attrs_hint(hid_t dcpl_id, hbool_t *minimize); -H5_DLL herr_t H5Pset_dset_no_attrs_hint(hid_t dcpl_id, hbool_t minimize); +H5_DLL herr_t H5Pset_szip(hid_t plist_id, unsigned options_mask, unsigned pixels_per_block); +H5_DLL herr_t H5Pset_virtual(hid_t dcpl_id, hid_t vspace_id, const char *src_file_name, + const char *src_dset_name, hid_t src_space_id); +H5_DLL herr_t H5Pget_virtual_count(hid_t dcpl_id, size_t *count /*out*/); +H5_DLL hid_t H5Pget_virtual_vspace(hid_t dcpl_id, size_t index); +H5_DLL hid_t H5Pget_virtual_srcspace(hid_t dcpl_id, size_t index); +H5_DLL ssize_t H5Pget_virtual_filename(hid_t dcpl_id, size_t index, char *name /*out*/, size_t size); +H5_DLL ssize_t H5Pget_virtual_dsetname(hid_t dcpl_id, size_t index, char *name /*out*/, size_t size); +H5_DLL herr_t H5Pset_external(hid_t plist_id, const char *name, off_t offset, hsize_t size); +H5_DLL int H5Pget_external_count(hid_t plist_id); +H5_DLL herr_t H5Pget_external(hid_t plist_id, unsigned idx, size_t name_size, char *name /*out*/, + off_t *offset /*out*/, hsize_t *size /*out*/); +H5_DLL herr_t H5Pset_nbit(hid_t plist_id); +H5_DLL herr_t H5Pset_scaleoffset(hid_t plist_id, H5Z_SO_scale_type_t scale_type, int scale_factor); +H5_DLL herr_t H5Pfill_value_defined(hid_t plist, H5D_fill_value_t *status); +H5_DLL herr_t H5Pset_alloc_time(hid_t plist_id, H5D_alloc_time_t alloc_time); +H5_DLL herr_t H5Pget_alloc_time(hid_t plist_id, H5D_alloc_time_t *alloc_time /*out*/); +H5_DLL herr_t H5Pget_dset_no_attrs_hint(hid_t dcpl_id, hbool_t *minimize); +H5_DLL herr_t H5Pset_dset_no_attrs_hint(hid_t dcpl_id, hbool_t minimize); /* Dataset access property list (DAPL) routines */ H5_DLL herr_t H5Pset_chunk_cache(hid_t dapl_id, size_t rdcc_nslots, size_t rdcc_nbytes, double rdcc_w0); @@ -1300,15 +1294,15 @@ H5_DLL herr_t H5Pget_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t *func, /* Typedefs */ /* Function prototypes */ -H5_DLL herr_t H5Pregister1(hid_t cls_id, const char *name, size_t size, void *def_value, - H5P_prp_create_func_t prp_create, H5P_prp_set_func_t prp_set, - H5P_prp_get_func_t prp_get, H5P_prp_delete_func_t prp_del, - H5P_prp_copy_func_t prp_copy, H5P_prp_close_func_t prp_close); -H5_DLL herr_t H5Pinsert1(hid_t plist_id, const char *name, size_t size, void *value, - H5P_prp_set_func_t prp_set, H5P_prp_get_func_t prp_get, - H5P_prp_delete_func_t prp_delete, H5P_prp_copy_func_t prp_copy, - H5P_prp_close_func_t prp_close); -H5_DLL herr_t H5Pencode1(hid_t plist_id, void *buf, size_t *nalloc); +H5_DLL herr_t H5Pregister1(hid_t cls_id, const char *name, size_t size, void *def_value, + H5P_prp_create_func_t prp_create, H5P_prp_set_func_t prp_set, + H5P_prp_get_func_t prp_get, H5P_prp_delete_func_t prp_del, + H5P_prp_copy_func_t prp_copy, H5P_prp_close_func_t prp_close); +H5_DLL herr_t H5Pinsert1(hid_t plist_id, const char *name, size_t size, void *value, + H5P_prp_set_func_t prp_set, H5P_prp_get_func_t prp_get, + H5P_prp_delete_func_t prp_delete, H5P_prp_copy_func_t prp_copy, + H5P_prp_close_func_t prp_close); +H5_DLL herr_t H5Pencode1(hid_t plist_id, void *buf, size_t *nalloc); /** *------------------------------------------------------------------------- * \ingroup OCPL @@ -27,10 +27,12 @@ #include "H5private.h" /* Generic Functions */ #include "H5CXprivate.h" /* API Contexts */ #include "H5Eprivate.h" /* Error handling */ +#include "H5ESprivate.h" /* Event Sets */ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5Rpkg.h" /* References */ #include "H5Sprivate.h" /* Dataspaces */ +#include "H5VLprivate.h" /* Virtual Object Layer */ /****************/ /* Local Macros */ @@ -44,6 +46,14 @@ /* Local Prototypes */ /********************/ +/* Helper routines for sync/async API calls */ +static hid_t H5R__open_object_api_common(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static hid_t H5R__open_region_api_common(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static hid_t H5R__open_attr_api_common(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t aapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); + /*********************/ /* Package Variables */ /*********************/ @@ -448,28 +458,29 @@ done: } /* end H5Rcopy() */ /*------------------------------------------------------------------------- - * Function: H5Ropen_object + * Function: H5R__open_object_api_common * - * Purpose: Given a reference to some object, open that object and - * return an ID for that object. + * Purpose: This is the common function for opening an object via a reference. * * Return: Valid ID on success / H5I_INVALID_HID on failure * *------------------------------------------------------------------------- */ -hid_t -H5Ropen_object(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id) +static hid_t +H5R__open_object_api_common(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) { - hid_t loc_id; /* Reference location ID */ - H5VL_object_t * vol_obj = NULL; /* Object of loc_id */ - H5VL_loc_params_t loc_params; /* Location parameters */ - H5O_token_t obj_token = {0}; /* Object token */ - H5I_type_t opened_type; /* Opened object type */ - void * opened_obj = NULL; /* Opened object */ - hid_t ret_value = H5I_INVALID_HID; /* Return value */ - - FUNC_ENTER_API(H5I_INVALID_HID) - H5TRACE3("i", "*Rrii", ref_ptr, rapl_id, oapl_id); + hid_t loc_id; /* Reference location ID */ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters */ + H5O_token_t obj_token = {0}; /* Object token */ + H5I_type_t opened_type; /* Opened object type */ + void * opened_obj = NULL; /* Opened object */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_STATIC /* Check args */ if (ref_ptr == NULL) @@ -489,52 +500,117 @@ H5Ropen_object(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENFILE, H5I_INVALID_HID, "cannot re-open referenced file") } - /* Get object token */ - if (H5R__get_obj_token((const H5R_ref_priv_t *)ref_ptr, &obj_token, NULL) < 0) - HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, H5I_INVALID_HID, "unable to get object token") - /* Verify access property list and set up collective metadata if appropriate */ if (H5CX_set_apl(&oapl_id, H5P_CLS_DACC, loc_id, FALSE) < 0) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info") - /* Get the VOL object */ - if (NULL == (vol_obj = H5VL_vol_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier") + /* Get object token */ + if (H5R__get_obj_token((const H5R_ref_priv_t *)ref_ptr, &obj_token, NULL) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, H5I_INVALID_HID, "unable to get object token") - /* 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); + /* Set up arguments for object access by token */ + if (H5VL_setup_token_args(loc_id, &obj_token, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, H5I_INVALID_HID, "can't set object access arguments") /* Open object by token */ - if (NULL == (opened_obj = H5VL_object_open(vol_obj, &loc_params, &opened_type, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL))) + if (NULL == (opened_obj = H5VL_object_open(*vol_obj_ptr, &loc_params, &opened_type, + H5P_DATASET_XFER_DEFAULT, token_ptr))) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object by token") /* Register object */ - if ((ret_value = H5VL_register(opened_type, opened_obj, vol_obj->connector, TRUE)) < 0) + if ((ret_value = H5VL_register(opened_type, opened_obj, (*vol_obj_ptr)->connector, TRUE)) < 0) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object handle") done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5R__open_object_api_common() */ + +/*------------------------------------------------------------------------- + * Function: H5Ropen_object + * + * Purpose: Given a reference to some object, open that object and + * return an ID for that object. + * + * Return: Valid ID on success / H5I_INVALID_HID on failure + * + *------------------------------------------------------------------------- + */ +hid_t +H5Ropen_object(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id) +{ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE3("i", "*Rrii", ref_ptr, rapl_id, oapl_id); + + /* Open the dataset synchronously */ + if ((ret_value = H5R__open_object_api_common(ref_ptr, rapl_id, oapl_id, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object synchronously") + +done: FUNC_LEAVE_API(ret_value) } /* end H5Ropen_object() */ /*------------------------------------------------------------------------- - * Function: H5Ropen_region + * Function: H5Ropen_object_async * - * Purpose: Given a reference to some object, creates a copy of the dataset - * pointed to's dataspace and defines a selection in the copy - * which is the region pointed to. + * Purpose: Asynchronous version of H5Ropen_object * * Return: Valid ID on success / H5I_INVALID_HID on failure * *------------------------------------------------------------------------- */ hid_t -H5Ropen_region(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id) +H5Ropen_object_async(const char *app_file, const char *app_func, unsigned app_line, H5R_ref_t *ref_ptr, + hid_t rapl_id, hid_t oapl_id, hid_t es_id) { - hid_t loc_id; /* Reference location ID */ - H5VL_object_t * vol_obj = NULL; /* Object of loc_id */ + H5VL_object_t *vol_obj = NULL; /* Object of loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE7("i", "*s*sIu*Rriii", app_file, app_func, app_line, ref_ptr, rapl_id, oapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Open the object asynchronously */ + if ((ret_value = H5R__open_object_api_common(ref_ptr, rapl_id, oapl_id, token_ptr, &vol_obj)) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object asynchronously") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE7(FUNC, "*s*sIu*Rriii", app_file, app_func, app_line, ref_ptr, rapl_id, + oapl_id, es_id)) < 0) { + if (H5I_dec_app_ref_always_close(ret_value) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDEC, H5I_INVALID_HID, "can't decrement count on object ID") + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Ropen_object_async() */ + +/*------------------------------------------------------------------------- + * Function: H5R__open_region_api_common + * + * Purpose: This is the common function for opening a region. + * + * Return: Valid ID on success / H5I_INVALID_HID on failure + * + *------------------------------------------------------------------------- + */ +static hid_t +H5R__open_region_api_common(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) +{ + hid_t loc_id; /* Reference location ID */ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ H5VL_loc_params_t loc_params; /* Location parameters */ H5O_token_t obj_token = {0}; /* Object token */ H5I_type_t opened_type; /* Opened object type */ @@ -544,8 +620,7 @@ H5Ropen_region(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id) hid_t space_id = H5I_INVALID_HID; /* Dataspace ID */ hid_t ret_value = H5I_INVALID_HID; /* Return value */ - FUNC_ENTER_API(H5I_INVALID_HID) - H5TRACE3("i", "*Rrii", ref_ptr, rapl_id, oapl_id); + FUNC_ENTER_STATIC /* Check args */ if (ref_ptr == NULL) @@ -569,22 +644,17 @@ H5Ropen_region(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id) if (H5R__get_obj_token((const H5R_ref_priv_t *)ref_ptr, &obj_token, NULL) < 0) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, H5I_INVALID_HID, "unable to get object token") - /* Get the VOL object */ - if (NULL == (vol_obj = H5VL_vol_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "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); + /* Set up arguments for object access by token */ + if (H5VL_setup_token_args(loc_id, &obj_token, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, H5I_INVALID_HID, "can't set object access arguments") /* Open object by token */ - if (NULL == (opened_obj = H5VL_object_open(vol_obj, &loc_params, &opened_type, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL))) + if (NULL == (opened_obj = H5VL_object_open(*vol_obj_ptr, &loc_params, &opened_type, + H5P_DATASET_XFER_DEFAULT, token_ptr))) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object by token") /* Register object */ - if ((opened_obj_id = H5VL_register(opened_type, opened_obj, vol_obj->connector, FALSE)) < 0) + if ((opened_obj_id = H5VL_register(opened_type, opened_obj, (*vol_obj_ptr)->connector, FALSE)) < 0) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object handle") /* Get VOL object object */ @@ -612,24 +682,96 @@ done: if ((space_id != H5I_INVALID_HID) && (H5I_dec_ref(space_id) < 0)) HDONE_ERROR(H5E_REFERENCE, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close dataspace") + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5R__open_region_api_common() */ + +/*------------------------------------------------------------------------- + * Function: H5Ropen_region + * + * Purpose: Given a reference to some object, creates a copy of the dataset + * pointed to's dataspace and defines a selection in the copy + * which is the region pointed to. + * + * Return: Valid ID on success / H5I_INVALID_HID on failure + * + *------------------------------------------------------------------------- + */ +hid_t +H5Ropen_region(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id) +{ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE3("i", "*Rrii", ref_ptr, rapl_id, oapl_id); + + /* Open the region synchronously */ + if ((ret_value = H5R__open_region_api_common(ref_ptr, rapl_id, oapl_id, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open region synchronously") + +done: FUNC_LEAVE_API(ret_value) } /* end H5Ropen_region() */ /*------------------------------------------------------------------------- - * Function: H5Ropen_attr + * Function: H5Ropen_region_async * - * Purpose: Given a reference to some attribute, open that attribute and - * return an ID for that attribute. + * Purpose: Asynchronous version of H5Ropen_region * * Return: Valid ID on success / H5I_INVALID_HID on failure * *------------------------------------------------------------------------- */ hid_t -H5Ropen_attr(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t aapl_id) +H5Ropen_region_async(const char *app_file, const char *app_func, unsigned app_line, H5R_ref_t *ref_ptr, + hid_t rapl_id, hid_t oapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object of loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE7("i", "*s*sIu*Rriii", app_file, app_func, app_line, ref_ptr, rapl_id, oapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Open the region asynchronously */ + if ((ret_value = H5R__open_region_api_common(ref_ptr, rapl_id, oapl_id, token_ptr, &vol_obj)) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open region asynchronously") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE7(FUNC, "*s*sIu*Rriii", app_file, app_func, app_line, ref_ptr, rapl_id, + oapl_id, es_id)) < 0) { + if (H5I_dec_app_ref_always_close(ret_value) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDEC, H5I_INVALID_HID, "can't decrement count on region ID") + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Ropen_region_async() */ + +/*------------------------------------------------------------------------- + * Function: H5R__open_attr_api_common + * + * Purpose: This is the common function for opening an attribute via a reference. + * + * Return: Valid ID on success / H5I_INVALID_HID on failure + * + *------------------------------------------------------------------------- + */ +static hid_t +H5R__open_attr_api_common(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t aapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) { - hid_t loc_id; /* Reference location ID */ - H5VL_object_t * vol_obj = NULL; /* Object of loc_id */ + hid_t loc_id; /* Reference location ID */ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ H5VL_loc_params_t loc_params; /* Location parameters */ H5O_token_t obj_token = {0}; /* Object token */ H5I_type_t opened_type; /* Opened object type */ @@ -638,9 +780,9 @@ H5Ropen_attr(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t aapl_id) void * opened_attr = NULL; /* Opened attribute */ hid_t ret_value = H5I_INVALID_HID; /* Return value */ - FUNC_ENTER_API(H5I_INVALID_HID) - H5TRACE3("i", "*Rrii", ref_ptr, rapl_id, aapl_id); + FUNC_ENTER_STATIC + fprintf(stderr, "H5R__open_attr_api_common is here\n"); /* Check args */ if (ref_ptr == NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid reference pointer") @@ -663,7 +805,7 @@ H5Ropen_attr(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t aapl_id) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, H5I_INVALID_HID, "unable to get object token") /* Get the VOL object */ - if (NULL == (vol_obj = H5VL_vol_object(loc_id))) + if (NULL == (*vol_obj_ptr = H5VL_vol_object(loc_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier") /* Set location parameters */ @@ -672,12 +814,12 @@ H5Ropen_attr(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t aapl_id) loc_params.obj_type = H5I_get_type(loc_id); /* Open object by token */ - if (NULL == (opened_obj = H5VL_object_open(vol_obj, &loc_params, &opened_type, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL))) + if (NULL == (opened_obj = H5VL_object_open(*vol_obj_ptr, &loc_params, &opened_type, + H5P_DATASET_XFER_DEFAULT, token_ptr))) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object by token") /* Register object */ - if ((opened_obj_id = H5VL_register(opened_type, opened_obj, vol_obj->connector, FALSE)) < 0) + if ((opened_obj_id = H5VL_register(opened_type, opened_obj, (*vol_obj_ptr)->connector, FALSE)) < 0) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object handle") /* Verify access property list and set up collective metadata if appropriate */ @@ -700,19 +842,89 @@ H5Ropen_attr(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t aapl_id) H5R_REF_ATTRNAME((const H5R_ref_priv_t *)ref_ptr)) /* Register the attribute and get an ID for it */ - if ((ret_value = H5VL_register(H5I_ATTR, opened_attr, vol_obj->connector, TRUE)) < 0) + if ((ret_value = H5VL_register(H5I_ATTR, opened_attr, (*vol_obj_ptr)->connector, TRUE)) < 0) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register attribute handle") done: if ((opened_obj_id != H5I_INVALID_HID) && (H5I_dec_ref(opened_obj_id) < 0)) HDONE_ERROR(H5E_REFERENCE, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close object") if (H5I_INVALID_HID == ret_value) /* Cleanup on failure */ - if (opened_attr && H5VL_attr_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) + if (opened_attr && H5VL_attr_close(*vol_obj_ptr, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) HDONE_ERROR(H5E_REFERENCE, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close attribute") + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5R__open_attr_api_common() */ + +/*------------------------------------------------------------------------- + * Function: H5Ropen_attr + * + * Purpose: Given a reference to some attribute, open that attribute and + * return an ID for that attribute. + * + * Return: Valid ID on success / H5I_INVALID_HID on failure + * + *------------------------------------------------------------------------- + */ +hid_t +H5Ropen_attr(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t aapl_id) +{ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE3("i", "*Rrii", ref_ptr, rapl_id, aapl_id); + + /* Open the attribute synchronously */ + if ((ret_value = H5R__open_attr_api_common(ref_ptr, rapl_id, aapl_id, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_OPENERROR, H5I_INVALID_HID, "unable to open attribute synchronously") + +done: FUNC_LEAVE_API(ret_value) } /* end H5Ropen_attr() */ +/*-------------------------------------------------------------------------- + * Function: H5Ropen_attr_async + * + * Purpose: Asynchronous version of H5Ropen_attr + * + * Return: An attribute ID on success / H5I_INVALID_HID on failure + * + *------------------------------------------------------------------------- + */ +hid_t +H5Ropen_attr_async(const char *app_file, const char *app_func, unsigned app_line, H5R_ref_t *ref_ptr, + hid_t rapl_id, hid_t aapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE7("i", "*s*sIu*Rriii", app_file, app_func, app_line, ref_ptr, rapl_id, aapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Open the attribute asynchronously */ + if ((ret_value = H5R__open_attr_api_common(ref_ptr, rapl_id, aapl_id, token_ptr, &vol_obj)) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_OPENERROR, H5I_INVALID_HID, "unable to open attribute asynchronously") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE7(FUNC, "*s*sIu*Rriii", app_file, app_func, app_line, ref_ptr, rapl_id, + aapl_id, es_id)) < 0) { + if (H5I_dec_app_ref_always_close(ret_value) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDEC, H5I_INVALID_HID, + "can't decrement count on attribute ID") + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Ropen_attr_async() */ + /*------------------------------------------------------------------------- * Function: H5Rget_obj_type3 * diff --git a/src/H5Rpublic.h b/src/H5Rpublic.h index 6b30b85..b2803de 100644 --- a/src/H5Rpublic.h +++ b/src/H5Rpublic.h @@ -113,8 +113,14 @@ H5_DLL herr_t H5Rcopy(const H5R_ref_t *src_ref_ptr, H5R_ref_t *dst_ref_ptr); /* Dereference */ H5_DLL hid_t H5Ropen_object(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id); +H5_DLL hid_t H5Ropen_object_async(const char *app_file, const char *app_func, unsigned app_line, + H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id, hid_t es_id); H5_DLL hid_t H5Ropen_region(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id); +H5_DLL hid_t H5Ropen_region_async(const char *app_file, const char *app_func, unsigned app_line, + H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id, hid_t es_id); H5_DLL hid_t H5Ropen_attr(H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t aapl_id); +H5_DLL hid_t H5Ropen_attr_async(const char *app_file, const char *app_func, unsigned app_line, + H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t aapl_id, hid_t es_id); /* Get type */ H5_DLL herr_t H5Rget_obj_type3(H5R_ref_t *ref_ptr, hid_t rapl_id, H5O_type_t *obj_type); @@ -124,6 +130,21 @@ H5_DLL ssize_t H5Rget_file_name(const H5R_ref_t *ref_ptr, char *buf, size_t size H5_DLL ssize_t H5Rget_obj_name(H5R_ref_t *ref_ptr, hid_t rapl_id, char *buf, size_t size); H5_DLL ssize_t H5Rget_attr_name(const H5R_ref_t *ref_ptr, char *buf, size_t size); +/* API Wrappers for async routines */ +/* (Must be defined _after_ the function prototype) */ +/* (And must only defined when included in application code, not the library) */ +#ifndef H5R_MODULE +#define H5Ropen_object_async(...) H5Ropen_object_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Ropen_region_async(...) H5Ropen_region_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Ropen_attr_async(...) H5Ropen_attr_async(__FILE__, __func__, __LINE__, __VA_ARGS__) + +/* Define "wrapper" versions of function calls, to allow compile-time values to + * be passed in by language wrapper or library layer on top of HDF5. */ +#define H5Ropen_object_async_wrap H5_NO_EXPAND(H5Ropen_object_async) +#define H5Ropen_region_async_wrap H5_NO_EXPAND(H5Ropen_region_async) +#define H5Ropen_attr_async_wrap H5_NO_EXPAND(H5Ropen_attr_async) +#endif /* H5R_MODULE */ + /* Symbols defined for compatibility with previous versions of the HDF5 API. * * Use of these symbols is or will be deprecated. @@ -99,6 +99,27 @@ static const H5I_class_t H5I_SPACE_SEL_ITER_CLS[1] = {{ /* Flag indicating "top" of interface has been initialized */ static hbool_t H5S_top_package_initialize_s = FALSE; +/*------------------------------------------------------------------------- + * Function: H5S_init + * + * Purpose: Initialize the interface from some other layer. + * + * Return: Success: non-negative + * Failure: negative + *------------------------------------------------------------------------- + */ +herr_t +H5S_init(void) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + /* FUNC_ENTER() does all the work */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_init() */ + /*-------------------------------------------------------------------------- NAME H5S__init_package -- Initialize interface-specific information @@ -1364,16 +1364,13 @@ H5SM__write_mesg(H5F_t *f, H5O_t *open_oh, H5SM_index_header_t *header, hbool_t HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index") if (defer) { - htri_t bt2_find; /* Result from searching in the v2 B-tree */ - /* If this returns 0, it means that the message wasn't found. */ /* If it return 1, set the heap_id in the shared struct. It will * return a heap ID, since a message with a reference count greater * than 1 is always shared in the heap. */ - if ((bt2_find = H5B2_find(bt2, &key, NULL, NULL)) < 0) + if (H5B2_find(bt2, &key, &found, NULL, NULL) < 0) HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "can't search for message in index") - found = (hbool_t)bt2_find; } /* end if */ else { H5SM_incr_ref_opdata op_data; @@ -2231,7 +2228,7 @@ H5SM_get_refcount(H5F_t *f, unsigned type_id, const H5O_shared_t *sh_mesg, hsize message = list->messages[list_pos]; } /* end if */ else { - htri_t msg_exists; /* Whether the message exists in the v2 B-tree */ + hbool_t msg_exists; /* Whether the message exists in the v2 B-tree */ /* Index is a B-tree */ HDassert(header->index_type == H5SM_BTREE); @@ -2241,7 +2238,8 @@ H5SM_get_refcount(H5F_t *f, unsigned type_id, const H5O_shared_t *sh_mesg, hsize HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index") /* Look up the message in the v2 B-tree */ - if ((msg_exists = H5B2_find(bt2, &key, H5SM__get_refcount_bt2_cb, &message)) < 0) + msg_exists = FALSE; + if (H5B2_find(bt2, &key, &msg_exists, H5SM__get_refcount_bt2_cb, &message) < 0) HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "error finding message in index") if (!msg_exists) HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "message not in index") diff --git a/src/H5Spkg.h b/src/H5Spkg.h index b744a6a..8b1922b 100644 --- a/src/H5Spkg.h +++ b/src/H5Spkg.h @@ -280,23 +280,28 @@ typedef struct { H5S_sel_copy_func_t copy; /* Method to make a copy of a selection */ H5S_sel_release_func_t release; /* Method to release current selection */ H5S_sel_is_valid_func_t is_valid; /* Method to determine if current selection is valid for dataspace */ - H5S_sel_serial_size_func_t serial_size; /* Method to determine number of bytes required to store current selection */ + H5S_sel_serial_size_func_t + serial_size; /* Method to determine number of bytes required to store current selection */ H5S_sel_serialize_func_t serialize; /* Method to store current selection in "serialized" form (a byte sequence suitable for storing on disk) */ H5S_sel_deserialize_func_t deserialize; /* Method to store create selection from "serialized" form (a byte sequence suitable for storing on disk) */ - H5S_sel_bounds_func_t bounds; /* Method to determine to smallest n-D bounding box containing the current selection */ - H5S_sel_offset_func_t offset; /* Method to determine linear offset of initial element in selection within dataspace */ + H5S_sel_bounds_func_t + bounds; /* Method to determine to smallest n-D bounding box containing the current selection */ + H5S_sel_offset_func_t + offset; /* Method to determine linear offset of initial element in selection within dataspace */ H5S_sel_unlim_dim_func_t unlim_dim; /* Method to get unlimited dimension of selection (or -1 for none) */ H5S_sel_num_elem_non_unlim_func_t num_elem_non_unlim; /* Method to get the number of elements in a slice through the unlimited dimension */ H5S_sel_is_contiguous_func_t is_contiguous; /* Method to determine if current selection is contiguous */ H5S_sel_is_single_func_t is_single; /* Method to determine if current selection is a single block */ H5S_sel_is_regular_func_t is_regular; /* Method to determine if current selection is "regular" */ - H5S_sel_shape_same_func_t shape_same; /* Method to determine if two dataspaces' selections are the same shape */ - H5S_sel_intersect_block_func_t intersect_block; /* Method to determine if a dataspaces' selection intersects a block */ - H5S_sel_adjust_u_func_t adjust_u; /* Method to adjust a selection by an offset */ - H5S_sel_adjust_s_func_t adjust_s; /* Method to adjust a selection by an offset (signed) */ + H5S_sel_shape_same_func_t + shape_same; /* Method to determine if two dataspaces' selections are the same shape */ + H5S_sel_intersect_block_func_t + intersect_block; /* Method to determine if a dataspaces' selection intersects a block */ + H5S_sel_adjust_u_func_t adjust_u; /* Method to adjust a selection by an offset */ + H5S_sel_adjust_s_func_t adjust_s; /* Method to adjust a selection by an offset (signed) */ H5S_sel_project_scalar project_scalar; /* Method to construct scalar dataspace projection */ H5S_sel_project_simple project_simple; /* Method to construct simple dataspace projection */ H5S_sel_iter_init_func_t iter_init; /* Method to initialize iterator for current selection */ @@ -347,13 +352,20 @@ typedef struct H5S_sel_iter_class_t { H5S_sel_type type; /* Type of selection (all, none, points or hyperslab) */ /* Methods on selections */ - H5S_sel_iter_coords_func_t iter_coords; /* Method to retrieve the current coordinates of iterator for current selection */ - H5S_sel_iter_block_func_t iter_block; /* Method to retrieve the current block of iterator for current selection */ - H5S_sel_iter_nelmts_func_t iter_nelmts; /* Method to determine number of elements left in iterator for current selection */ - H5S_sel_iter_has_next_block_func_t iter_has_next_block; /* Method to query if there is another block left in the selection */ - H5S_sel_iter_next_func_t iter_next; /* Method to move selection iterator to the next element in the selection */ - H5S_sel_iter_next_block_func_t iter_next_block; /* Method to move selection iterator to the next block in the selection */ - H5S_sel_iter_get_seq_list_func_t iter_get_seq_list; /* Method to retrieve a list of offset/length sequences for selection iterator */ + H5S_sel_iter_coords_func_t + iter_coords; /* Method to retrieve the current coordinates of iterator for current selection */ + H5S_sel_iter_block_func_t + iter_block; /* Method to retrieve the current block of iterator for current selection */ + H5S_sel_iter_nelmts_func_t + iter_nelmts; /* Method to determine number of elements left in iterator for current selection */ + H5S_sel_iter_has_next_block_func_t + iter_has_next_block; /* Method to query if there is another block left in the selection */ + H5S_sel_iter_next_func_t + iter_next; /* Method to move selection iterator to the next element in the selection */ + H5S_sel_iter_next_block_func_t + iter_next_block; /* Method to move selection iterator to the next block in the selection */ + H5S_sel_iter_get_seq_list_func_t + iter_get_seq_list; /* Method to retrieve a list of offset/length sequences for selection iterator */ H5S_sel_iter_release_func_t iter_release; /* Method to release iterator for current selection */ } H5S_sel_iter_class_t; diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index 3389e1f..4598a41 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -201,6 +201,7 @@ struct H5O_loc_t; typedef struct H5S_t H5S_t; /* Operations on dataspaces */ +H5_DLL herr_t H5S_init(void); H5_DLL H5S_t * H5S_copy(const H5S_t *src, hbool_t share_selection, hbool_t copy_max); H5_DLL herr_t H5S_close(H5S_t *ds); H5_DLL H5S_class_t H5S_get_simple_extent_type(const H5S_t *ds); diff --git a/src/H5Spublic.h b/src/H5Spublic.h index c16af93..62e2128 100644 --- a/src/H5Spublic.h +++ b/src/H5Spublic.h @@ -171,7 +171,7 @@ H5_DLL herr_t H5Sclose(hid_t space_id); * \since 1.0.0 * */ -H5_DLL hid_t H5Screate(H5S_class_t type); +H5_DLL hid_t H5Screate(H5S_class_t type); /** * \ingroup H5S * \brief Creates a new simple dataspace and opens it for access @@ -222,7 +222,7 @@ H5_DLL hid_t H5Screate(H5S_class_t type); * \since 1.0.0 * */ -H5_DLL hid_t H5Screate_simple(int rank, const hsize_t dims[], const hsize_t maxdims[]); +H5_DLL hid_t H5Screate_simple(int rank, const hsize_t dims[], const hsize_t maxdims[]); /*--------------------------------------------------------------------------*/ /**\ingroup H5S * @@ -269,8 +269,7 @@ H5_DLL hssize_t H5Sget_select_npoints(hid_t spaceid); * \since 1.0.0 * */ -H5_DLL int H5Sget_simple_extent_dims(hid_t space_id, hsize_t dims[], - hsize_t maxdims[]); +H5_DLL int H5Sget_simple_extent_dims(hid_t space_id, hsize_t dims[], hsize_t maxdims[]); /*-------------------------------------------------------------------------*/ /**\ingroup H5S * @@ -394,9 +393,8 @@ H5_DLL int H5Sget_simple_extent_ndims(hid_t space_id); * \since 1.0.0 * */ -H5_DLL herr_t H5Sselect_hyperslab(hid_t space_id, H5S_seloper_t op, - const hsize_t start[], const hsize_t stride[], const hsize_t count[], - const hsize_t block[]); +H5_DLL herr_t H5Sselect_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_t start[], + const hsize_t stride[], const hsize_t count[], const hsize_t block[]); H5_DLL herr_t H5Sset_extent_simple(hid_t space_id, int rank, const hsize_t dims[], const hsize_t max[]); H5_DLL hid_t H5Scopy(hid_t space_id); H5_DLL herr_t H5Sencode2(hid_t obj_id, void *buf, size_t *nalloc, hid_t fapl); @@ -32,6 +32,7 @@ #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 "H5FOprivate.h" /* File objects */ @@ -325,7 +326,7 @@ /* Adjust information for this type */ \ H5_GLUE3(H5T_INIT_TYPE_, GUTS, _CORE) \ \ - /* Register result */ \ + /* Register result */ \ if ((GLOBAL = H5I_register(H5I_DATATYPE, dt, FALSE)) < 0) \ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype atom") \ } @@ -1923,6 +1924,7 @@ H5Tcopy(hid_t obj_id) 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, H5I_INVALID_HID, "not a datatype or dataset") @@ -1954,12 +1956,12 @@ done: /*------------------------------------------------------------------------- * Function: H5Tclose * - * Purpose: Frees a datatype and all associated memory. + * Purpose: Frees a datatype and all associated memory. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * - * Programmer: Robb Matzke - * Tuesday, December 9, 1997 + * Programmer: Robb Matzke + * Tuesday, December 9, 1997 *------------------------------------------------------------------------- */ herr_t @@ -1986,6 +1988,66 @@ done: } /* end H5Tclose() */ /*------------------------------------------------------------------------- + * Function: H5Tclose_async + * + * Purpose: Asynchronous version of H5Tclose. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tclose_async(const char *app_file, const char *app_func, unsigned app_line, hid_t type_id, hid_t es_id) +{ + H5T_t * dt; /* Pointer to datatype to close */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + H5VL_object_t *vol_obj = NULL; /* VOL object of dset_id */ + H5VL_t * connector = NULL; /* VOL connector */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "*s*sIuii", app_file, app_func, app_line, type_id, es_id); + + /* Check args */ + if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") + if (H5T_STATE_IMMUTABLE == dt->shared->state) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "immutable datatype") + + /* Get dataset object's connector */ + if (NULL == (vol_obj = H5VL_vol_object(type_id))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get VOL object for dataset") + + /* Prepare for possible asynchronous operation */ + if (H5ES_NONE != es_id) { + /* Increase connector's refcount, so it doesn't get closed if closing + * the dataset closes the file */ + connector = vol_obj->connector; + H5VL_conn_inc_rc(connector); + + /* Point at token for operation to set up */ + token_ptr = &token; + } /* end if */ + + /* When the reference count reaches zero the resources are freed */ + if (H5I_dec_app_ref_async(type_id, token_ptr) < 0) + HGOTO_ERROR(H5E_ID, H5E_BADID, FAIL, "problem freeing id") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE5(FUNC, "*s*sIuii", app_file, app_func, app_line, type_id, es_id)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + if (connector && H5VL_conn_dec_rc(connector) < 0) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't decrement ref count on connector") + + FUNC_LEAVE_API(ret_value) +} /* end H5Tclose_async() */ + +/*------------------------------------------------------------------------- * Function: H5Tequal * * Purpose: Determines if two datatypes are equal. @@ -56,6 +56,8 @@ typedef void *(*H5TS_thread_cb_t)(void *); /* Local Prototypes */ /********************/ static void H5TS__key_destructor(void *key_val); +static herr_t H5TS__mutex_acquire(H5TS_mutex_t *mutex, unsigned int lock_count, hbool_t *acquired); +static herr_t H5TS__mutex_unlock(H5TS_mutex_t *mutex, unsigned int *lock_count); /*********************/ /* Package Variables */ @@ -303,6 +305,9 @@ H5TS_pthread_first_thread_init(void) HDpthread_cond_init(&H5_g.init_lock.cond_var, NULL); H5_g.init_lock.lock_count = 0; + HDpthread_mutex_init(&H5_g.init_lock.atomic_lock2, NULL); + H5_g.init_lock.attempt_lock_count = 0; + /* Initialize integer thread identifiers. */ H5TS_tid_init(); @@ -325,6 +330,90 @@ H5TS_pthread_first_thread_init(void) #endif /* H5_HAVE_WIN_THREADS */ /*-------------------------------------------------------------------------- + * Function: H5TS__mutex_acquire + * + * Purpose: Attempts to acquire a mutex lock, without blocking + * + * Note: On success, the 'acquired' flag indicates if the HDF5 library + * global lock was acquired. + * + * Note: The Windows threads code is very likely bogus. + * + * Return: Non-negative on success / Negative on failure + * + * Programmer: Quincey Koziol + * Februrary 27, 2019 + * + *-------------------------------------------------------------------------- + */ +static herr_t +H5TS__mutex_acquire(H5TS_mutex_t *mutex, unsigned int lock_count, hbool_t *acquired) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC_NAMECHECK_ONLY + +#ifdef H5_HAVE_WIN_THREADS + EnterCriticalSection(&mutex->CriticalSection); + *acquired = TRUE; +#else /* H5_HAVE_WIN_THREADS */ + /* Attempt to acquire the mutex lock */ + if (0 == HDpthread_mutex_lock(&mutex->atomic_lock)) { + pthread_t my_thread_id = HDpthread_self(); + + /* Check if locked already */ + if (mutex->lock_count) { + /* Check for this thread already owning the lock */ + if (HDpthread_equal(my_thread_id, mutex->owner_thread)) { + /* Already owned by self - increment count */ + mutex->lock_count += lock_count; + *acquired = TRUE; + } /* end if */ + else + *acquired = FALSE; + } /* end if */ + else { + /* Take ownership of the mutex */ + mutex->owner_thread = my_thread_id; + mutex->lock_count = lock_count; + *acquired = TRUE; + } /* end else */ + + if (0 != HDpthread_mutex_unlock(&mutex->atomic_lock)) + ret_value = -1; + } /* end if */ + else + ret_value = -1; +#endif /* H5_HAVE_WIN_THREADS */ + + FUNC_LEAVE_NOAPI_NAMECHECK_ONLY(ret_value) +} /* end H5TS__mutex_acquire() */ + +/*-------------------------------------------------------------------------- + * Function: H5TSmutex_acquire + * + * Purpose: Attempts to acquire the HDF5 library global lock + * + * Note: On success, the 'acquired' flag indicates if the HDF5 library + * global lock was acquired. + * + * Return: Non-negative on success / Negative on failure + * + * Programmer: Quincey Koziol + * Februrary 27, 2019 + * + *-------------------------------------------------------------------------- + */ +herr_t +H5TSmutex_acquire(unsigned int lock_count, hbool_t *acquired){ + FUNC_ENTER_API_NAMECHECK_ONLY + + /*NO TRACE*/ + + FUNC_LEAVE_API_NAMECHECK_ONLY(H5TS__mutex_acquire(&H5_g.init_lock, lock_count, acquired))} +/* end H5TSmutex_acquire() */ + +/*-------------------------------------------------------------------------- * NAME * H5TS_mutex_lock * @@ -344,8 +433,7 @@ H5TS_pthread_first_thread_init(void) * *-------------------------------------------------------------------------- */ -herr_t -H5TS_mutex_lock(H5TS_mutex_t *mutex) +herr_t H5TS_mutex_lock(H5TS_mutex_t *mutex) { herr_t ret_value = SUCCEED; @@ -354,6 +442,15 @@ H5TS_mutex_lock(H5TS_mutex_t *mutex) #ifdef H5_HAVE_WIN_THREADS EnterCriticalSection(&mutex->CriticalSection); #else /* H5_HAVE_WIN_THREADS */ + /* Acquire the "attempt" lock, increment the attempt lock count, release the lock */ + ret_value = HDpthread_mutex_lock(&mutex->atomic_lock2); + if (ret_value) + HGOTO_DONE(ret_value); + mutex->attempt_lock_count++; + ret_value = HDpthread_mutex_unlock(&mutex->atomic_lock2); + if (ret_value) + HGOTO_DONE(ret_value); + /* Acquire the library lock */ ret_value = HDpthread_mutex_lock(&mutex->atomic_lock); if (ret_value) @@ -383,6 +480,61 @@ done: /*-------------------------------------------------------------------------- * NAME + * H5TS__mutex_unlock + * + * USAGE + * H5TS__mutex_unlock(&mutex_var, &lock_count) + * + * RETURNS + * Non-negative on success / Negative on failure + * + * DESCRIPTION + * Recursive lock semantics for HDF5 (unlocking) - + * Reset the lock and return the current lock count + * + * PROGRAMMER: Houjun Tang + * Nov 3, 2020 + * + *-------------------------------------------------------------------------- + */ +static herr_t +H5TS__mutex_unlock(H5TS_mutex_t *mutex, unsigned int *lock_count) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NAMECHECK_ONLY + +#ifdef H5_HAVE_WIN_THREADS + /* Releases ownership of the specified critical section object. */ + LeaveCriticalSection(&mutex->CriticalSection); +#else /* H5_HAVE_WIN_THREADS */ + + /* Reset the lock count for this thread */ + ret_value = HDpthread_mutex_lock(&mutex->atomic_lock); + if (ret_value) + HGOTO_DONE(ret_value); + *lock_count = mutex->lock_count; + mutex->lock_count = 0; + ret_value = HDpthread_mutex_unlock(&mutex->atomic_lock); + + /* If the lock count drops to zero, signal the condition variable, to + * wake another thread. + */ + if (mutex->lock_count == 0) { + int err; + + err = HDpthread_cond_signal(&mutex->cond_var); + if (err != 0) + ret_value = err; + } /* end if */ +#endif /* H5_HAVE_WIN_THREADS */ + +done: + FUNC_LEAVE_NOAPI_NAMECHECK_ONLY(ret_value) +} /* H5TS__mutex_unlock */ + +/*-------------------------------------------------------------------------- + * NAME * H5TS_mutex_unlock * * USAGE @@ -437,6 +589,67 @@ done: } /* H5TS_mutex_unlock */ /*-------------------------------------------------------------------------- + * Function: H5TSmutex_get_attempt_count + * + * Purpose: Get the current count of the global lock attempt + * + * Return: Non-negative on success / Negative on failure + * + * Programmer: Houjun Tang + * June 24, 2019 + * + *-------------------------------------------------------------------------- + */ +herr_t +H5TSmutex_get_attempt_count(unsigned int *count) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API_NAMECHECK_ONLY + /*NO TRACE*/ + + ret_value = HDpthread_mutex_lock(&H5_g.init_lock.atomic_lock2); + if (ret_value) + HGOTO_DONE(ret_value); + + *count = H5_g.init_lock.attempt_lock_count; + + ret_value = HDpthread_mutex_unlock(&H5_g.init_lock.atomic_lock2); + if (ret_value) + HGOTO_DONE(ret_value); + +done: + FUNC_LEAVE_API_NAMECHECK_ONLY(ret_value) +} /* end H5TSmutex_get_attempt_count() */ + +/*-------------------------------------------------------------------------- + * Function: H5TSmutex_release + * + * Purpose: Releases the HDF5 library global lock + * + * Return: Non-negative on success / Negative on failure + * + * Programmer: Quincey Koziol + * Februrary 27, 2019 + * + *-------------------------------------------------------------------------- + */ +herr_t +H5TSmutex_release(unsigned int *lock_count) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API_NAMECHECK_ONLY + /*NO TRACE*/ + + *lock_count = 0; + if (0 != H5TS__mutex_unlock(&H5_g.init_lock, lock_count)) + ret_value = -1; + + FUNC_LEAVE_API_NAMECHECK_ONLY(ret_value) +} /* end H5TSmutex_release() */ + +/*-------------------------------------------------------------------------- * NAME * H5TS_cancel_count_inc * @@ -495,7 +708,7 @@ H5TS_cancel_count_inc(void) HDfree(cancel_counter); HGOTO_DONE(FAIL); } /* end if */ - } /* end if */ + } /* end if */ /* Check if thread entering library */ if (cancel_counter->cancel_count == 0) diff --git a/src/H5TSprivate.h b/src/H5TSprivate.h index dc85145..ccc7910 100644 --- a/src/H5TSprivate.h +++ b/src/H5TSprivate.h @@ -26,9 +26,7 @@ #ifdef H5_HAVE_THREADSAFE /* Public headers needed by this file */ -#ifdef LATER #include "H5TSpublic.h" /* Public API prototypes */ -#endif /* LATER */ #ifdef H5_HAVE_WIN_THREADS @@ -81,6 +79,9 @@ typedef struct H5TS_mutex_struct { pthread_mutex_t atomic_lock; /* lock for atomicity of new mechanism */ pthread_cond_t cond_var; /* condition variable */ unsigned int lock_count; + + pthread_mutex_t atomic_lock2; /* lock for attempt_lock_count */ + unsigned int attempt_lock_count; } H5TS_mutex_t; /* Portability wrappers around pthread types */ diff --git a/src/H5TSpublic.h b/src/H5TSpublic.h new file mode 100644 index 0000000..d246093 --- /dev/null +++ b/src/H5TSpublic.h @@ -0,0 +1,52 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains public declarations for the H5TS (threadsafety) module. + */ + +#ifndef _H5TSpublic_H +#define _H5TSpublic_H + +/* Public headers needed by this file */ +#include "H5public.h" /* Generic Functions */ + +/*****************/ +/* Public Macros */ +/*****************/ + +/*******************/ +/* Public Typedefs */ +/*******************/ + +/********************/ +/* Public Variables */ +/********************/ + +/*********************/ +/* Public Prototypes */ +/*********************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* HDF5 global library lock routines */ +H5_DLL herr_t H5TSmutex_acquire(unsigned int lock_count, hbool_t *acquired); +H5_DLL herr_t H5TSmutex_release(unsigned int *lock_count); +H5_DLL herr_t H5TSmutex_get_attempt_count(unsigned int *count); + +#ifdef __cplusplus +} +#endif + +#endif /* _H5TSpublic_H */ diff --git a/src/H5Tcommit.c b/src/H5Tcommit.c index 3eecfb3..1298909 100644 --- a/src/H5Tcommit.c +++ b/src/H5Tcommit.c @@ -29,6 +29,7 @@ #include "H5ACprivate.h" /* Metadata cache */ #include "H5CXprivate.h" /* API Contexts */ #include "H5Eprivate.h" /* Error handling */ +#include "H5ESprivate.h" /* Event Sets */ #include "H5FLprivate.h" /* Free lists */ #include "H5FOprivate.h" /* File objects */ #include "H5Iprivate.h" /* IDs */ @@ -54,6 +55,11 @@ /********************/ /* Local Prototypes */ /********************/ +static herr_t H5T__commit_api_common(hid_t loc_id, const char *name, hid_t type_id, hid_t lcpl_id, + hid_t tcpl_id, hid_t tapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); +static hid_t H5T__open_api_common(hid_t loc_id, const char *name, hid_t tapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr); static H5T_t *H5T__open_oid(const H5G_loc_t *loc); /*********************/ @@ -79,30 +85,28 @@ H5FL_EXTERN(H5VL_t); H5FL_EXTERN(H5VL_object_t); /*------------------------------------------------------------------------- - * Function: H5Tcommit2 + * Function: H5T__commit_api_common * - * Purpose: Save a transient datatype to a file and turn the type handle - * into a "named", immutable type. + * Purpose: This is the common function for committing a datytype. * * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol - * April 5, 2007 - * *------------------------------------------------------------------------- */ -herr_t -H5Tcommit2(hid_t loc_id, const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id) +static herr_t +H5T__commit_api_common(hid_t loc_id, const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, + hid_t tapl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr) { - void * data = NULL; /* VOL-managed datatype data */ - H5VL_object_t * new_obj = NULL; /* VOL object that holds the datatype object and the VOL info */ - H5T_t * dt = NULL; /* High level datatype object that wraps the VOL object */ - H5VL_object_t * vol_obj = NULL; /* object of loc_id */ - H5VL_loc_params_t loc_params; - herr_t ret_value = SUCCEED; /* Return value */ + void * data = NULL; /* VOL-managed datatype data */ + H5VL_object_t * new_obj = NULL; /* VOL object that holds the datatype object and the VOL info */ + H5T_t * dt = NULL; /* High level datatype object that wraps the VOL object */ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ + H5VL_loc_params_t loc_params; /* Location parameters */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API(FAIL) - H5TRACE6("e", "i*siiii", loc_id, name, type_id, lcpl_id, tcpl_id, tapl_id); + FUNC_ENTER_STATIC /* Check arguments */ if (!name) @@ -129,27 +133,19 @@ H5Tcommit2(hid_t loc_id, const char *name, hid_t type_id, hid_t lcpl_id, hid_t t /* Set the LCPL for the API context */ H5CX_set_lcpl(lcpl_id); - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&tapl_id, H5P_CLS_TACC, loc_id, TRUE) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't set access property list info") - - /* Fill in location struct fields */ - loc_params.type = H5VL_OBJECT_BY_SELF; - loc_params.obj_type = H5I_get_type(loc_id); - - /* Get the object from the loc_id */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier") + /* Set up object access arguments */ + if (H5VL_setup_acc_args(loc_id, H5P_CLS_TACC, TRUE, &tapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't set object access arguments") /* Commit the type */ - if (NULL == (data = H5VL_datatype_commit(vol_obj, &loc_params, name, type_id, lcpl_id, tcpl_id, tapl_id, - H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL))) + if (NULL == (data = H5VL_datatype_commit(*vol_obj_ptr, &loc_params, name, type_id, lcpl_id, tcpl_id, + tapl_id, H5P_DATASET_XFER_DEFAULT, token_ptr))) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to commit datatype") /* Set up VOL object */ if (NULL == (new_obj = H5FL_CALLOC(H5VL_object_t))) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "can't allocate top object structure") - new_obj->connector = vol_obj->connector; + new_obj->connector = (*vol_obj_ptr)->connector; new_obj->connector->nrefs++; new_obj->data = data; @@ -157,10 +153,82 @@ H5Tcommit2(hid_t loc_id, const char *name, hid_t type_id, hid_t lcpl_id, hid_t t dt->vol_obj = new_obj; done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__commit_api_common() */ + +/*------------------------------------------------------------------------- + * Function: H5Tcommit2 + * + * Purpose: Save a transient datatype to a file and turn the type handle + * into a "named", immutable type. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * April 5, 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tcommit2(hid_t loc_id, const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE6("e", "i*siiii", loc_id, name, type_id, lcpl_id, tcpl_id, tapl_id); + + /* Commit the dataset synchronously */ + if ((ret_value = H5T__commit_api_common(loc_id, name, type_id, lcpl_id, tcpl_id, tapl_id, NULL, NULL)) < + 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to commit datatype synchronously") + +done: FUNC_LEAVE_API(ret_value) } /* end H5Tcommit2() */ /*------------------------------------------------------------------------- + * Function: H5Tcommit_async + * + * Purpose: Asynchronous version of H5Tcommit2 + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tcommit_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, const char *name, + hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE10("e", "*s*sIui*siiiii", app_file, app_func, app_line, loc_id, name, type_id, lcpl_id, tcpl_id, + tapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; + + /* Commit the datatype asynchronously */ + if ((ret_value = H5T__commit_api_common(loc_id, name, type_id, lcpl_id, tcpl_id, tapl_id, token_ptr, + &vol_obj)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to commit datatype asynchronously") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE10(FUNC, "*s*sIui*siiiii", app_file, app_func, app_line, loc_id, name, + type_id, lcpl_id, tcpl_id, tapl_id, es_id)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "can't insert token into event set") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Tcommit_async() */ + +/*------------------------------------------------------------------------- * Function: H5T__commit_named * * Purpose: Internal routine to save a transient datatype to a file and @@ -545,30 +613,28 @@ done: } /* end H5T_link() */ /*------------------------------------------------------------------------- - * Function: H5Topen2 + * Function: H5T__open_api_common * - * Purpose: Opens a named datatype using a Datatype Access Property - * List. + * Purpose: This is the common function for opening a datatype. * * Return: Success: Object ID of the named datatype * * Failure: H5I_INVALID_HID * - * Programmer: James Laird - * Thursday July 27, 2006 - * *------------------------------------------------------------------------- */ -hid_t -H5Topen2(hid_t loc_id, const char *name, hid_t tapl_id) +static hid_t +H5T__open_api_common(hid_t loc_id, const char *name, hid_t tapl_id, void **token_ptr, + H5VL_object_t **_vol_obj_ptr) { - void * dt = NULL; /* datatype object created by VOL connector */ - H5VL_object_t * vol_obj = NULL; /* object of loc_id */ + void * dt = NULL; /* datatype object created by VOL connector */ + H5VL_object_t * tmp_vol_obj = NULL; /* Object for loc_id */ + H5VL_object_t **vol_obj_ptr = + (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */ H5VL_loc_params_t loc_params; hid_t ret_value = H5I_INVALID_HID; /* Return value */ - FUNC_ENTER_API(H5I_INVALID_HID) - H5TRACE3("i", "i*si", loc_id, name, tapl_id); + FUNC_ENTER_STATIC /* Check args */ if (!name) @@ -576,37 +642,107 @@ H5Topen2(hid_t loc_id, const char *name, hid_t tapl_id) if (!*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be an empty string") - /* Verify access property list and set up collective metadata if appropriate */ - if (H5CX_set_apl(&tapl_id, H5P_CLS_TACC, loc_id, FALSE) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't set access property list info") - - /* Fill in location struct fields */ - loc_params.type = H5VL_OBJECT_BY_SELF; - loc_params.obj_type = H5I_get_type(loc_id); - - /* get the location object */ - if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid file identifier") + /* Set up object access arguments */ + if (H5VL_setup_acc_args(loc_id, H5P_CLS_TACC, FALSE, &tapl_id, vol_obj_ptr, &loc_params) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, H5I_INVALID_HID, "can't set object access arguments") /* Open the datatype */ - if (NULL == (dt = H5VL_datatype_open(vol_obj, &loc_params, name, tapl_id, H5P_DATASET_XFER_DEFAULT, - H5_REQUEST_NULL))) + if (NULL == (dt = H5VL_datatype_open(*vol_obj_ptr, &loc_params, name, tapl_id, H5P_DATASET_XFER_DEFAULT, + token_ptr))) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open named datatype") /* Register the type and return the ID */ - if ((ret_value = H5VL_register(H5I_DATATYPE, dt, vol_obj->connector, TRUE)) < 0) + if ((ret_value = H5VL_register(H5I_DATATYPE, dt, (*vol_obj_ptr)->connector, TRUE)) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register named datatype") done: /* Cleanup on error */ if (H5I_INVALID_HID == ret_value) - if (dt && H5VL_datatype_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) + if (dt && H5VL_datatype_close(*vol_obj_ptr, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release datatype") + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__open_api_common() */ + +/*------------------------------------------------------------------------- + * Function: H5Topen2 + * + * Purpose: Opens a named datatype using a Datatype Access Property + * List. + * + * Return: Success: Object ID of the named datatype + * + * Failure: H5I_INVALID_HID + * + * Programmer: James Laird + * Thursday July 27, 2006 + * + *------------------------------------------------------------------------- + */ +hid_t +H5Topen2(hid_t loc_id, const char *name, hid_t tapl_id) +{ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE3("i", "i*si", loc_id, name, tapl_id); + + /* Open the datatype synchronously */ + if ((ret_value = H5T__open_api_common(loc_id, name, tapl_id, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, H5I_INVALID_HID, + "unable to open named datatype synchronously") +done: FUNC_LEAVE_API(ret_value) } /* end H5Topen2() */ /*------------------------------------------------------------------------- + * Function: H5Topen_async + * + * Purpose: Asynchronous version of H5Topen2. + * + * Return: Success: Object ID of the named datatype + * + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Topen_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, const char *name, + hid_t tapl_id, hid_t es_id) +{ + H5VL_object_t *vol_obj = NULL; /* Object for loc_id */ + void * token = NULL; /* Request token for async operation */ + void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE7("i", "*s*sIui*sii", app_file, app_func, app_line, loc_id, name, tapl_id, es_id); + + /* Set up request token pointer for asynchronous operation */ + if (H5ES_NONE != es_id) + token_ptr = &token; /* Point at token for VOL connector to set up */ + + /* Open the datatype asynchronously */ + if ((ret_value = H5T__open_api_common(loc_id, name, tapl_id, token_ptr, &vol_obj)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, H5I_INVALID_HID, + "unable to open named datatype asynchronously") + + /* If a token was created, add the token to the event set */ + if (NULL != token) + if (H5ES_insert(es_id, vol_obj->connector, token, + H5ARG_TRACE7(FUNC, "*s*sIui*sii", app_file, app_func, app_line, loc_id, name, tapl_id, + es_id)) < 0) { + if (H5I_dec_app_ref_always_close(ret_value) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, H5I_INVALID_HID, + "can't decrement count on datatype ID") + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert token into event set") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Topen_async() */ + +/*------------------------------------------------------------------------- * Function: H5Tget_create_plist * * Purpose: Returns a copy of the datatype creation property list. diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index 4f3d89d..e96921f 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -338,7 +338,8 @@ typedef struct H5T_shared_t { H5T_class_t type; /*which class of type is this? */ size_t size; /*total size of an instance of this type */ unsigned version; /* Version of object header message to encode this object with */ - hbool_t force_conv; /* Set if this type always needs to be converted and H5T__conv_noop cannot be called */ + hbool_t + force_conv; /* Set if this type always needs to be converted and H5T__conv_noop cannot be called */ struct H5T_t * parent; /*parent type for derived datatypes */ H5VL_object_t *owned_vol_obj; /* Vol object owned by this type (free on close) */ union { diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index b3dc064..52f1c14 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -24,12 +24,12 @@ typedef struct H5T_t H5T_t; #include "H5Tpublic.h" /* Other public headers needed by this file */ -#include "H5MMpublic.h" /* Memory management */ +#include "H5MMpublic.h" /* Memory management */ /* Private headers needed by this file */ -#include "H5private.h" /* Generic Functions */ -#include "H5Gprivate.h" /* Groups */ -#include "H5Rprivate.h" /* References */ +#include "H5private.h" /* Generic Functions */ +#include "H5Gprivate.h" /* Groups */ +#include "H5Rprivate.h" /* References */ #include "H5VLprivate.h" /* VOL Drivers */ /* Macro for size of temporary buffers to contain a single element */ diff --git a/src/H5Tpublic.h b/src/H5Tpublic.h index 68a1d79..4006ceb 100644 --- a/src/H5Tpublic.h +++ b/src/H5Tpublic.h @@ -30,20 +30,20 @@ */ //! [H5T_class_t_snip] typedef enum H5T_class_t { - H5T_NO_CLASS = -1, /**< error */ - H5T_INTEGER = 0, /**< integer types */ - H5T_FLOAT = 1, /**< floating-point types */ - H5T_TIME = 2, /**< date and time types */ - H5T_STRING = 3, /**< character string types */ - H5T_BITFIELD = 4, /**< bit field types */ - H5T_OPAQUE = 5, /**< opaque types */ - H5T_COMPOUND = 6, /**< compound types */ - H5T_REFERENCE = 7, /**< reference types */ - H5T_ENUM = 8, /**< enumeration types */ - H5T_VLEN = 9, /**< variable-Length types */ - H5T_ARRAY = 10, /**< array types */ + H5T_NO_CLASS = -1, /**< error */ + H5T_INTEGER = 0, /**< integer types */ + H5T_FLOAT = 1, /**< floating-point types */ + H5T_TIME = 2, /**< date and time types */ + H5T_STRING = 3, /**< character string types */ + H5T_BITFIELD = 4, /**< bit field types */ + H5T_OPAQUE = 5, /**< opaque types */ + H5T_COMPOUND = 6, /**< compound types */ + H5T_REFERENCE = 7, /**< reference types */ + H5T_ENUM = 8, /**< enumeration types */ + H5T_VLEN = 9, /**< variable-Length types */ + H5T_ARRAY = 10, /**< array types */ - H5T_NCLASSES /**< sentinel: this must be last */ + H5T_NCLASSES /**< sentinel: this must be last */ } H5T_class_t; //! [H5T_class_t_snip] @@ -52,12 +52,12 @@ typedef enum H5T_class_t { */ //! [H5T_order_t_snip] typedef enum H5T_order_t { - H5T_ORDER_ERROR = -1, /**< error */ - H5T_ORDER_LE = 0, /**< little endian */ - H5T_ORDER_BE = 1, /**< bit endian */ - H5T_ORDER_VAX = 2, /**< VAX mixed endian */ - H5T_ORDER_MIXED = 3, /**< Compound type with mixed member orders */ - H5T_ORDER_NONE = 4 /**< no particular order (strings, bits,..) */ + H5T_ORDER_ERROR = -1, /**< error */ + H5T_ORDER_LE = 0, /**< little endian */ + H5T_ORDER_BE = 1, /**< bit endian */ + H5T_ORDER_VAX = 2, /**< VAX mixed endian */ + H5T_ORDER_MIXED = 3, /**< Compound type with mixed member orders */ + H5T_ORDER_NONE = 4 /**< no particular order (strings, bits,..) */ /*H5T_ORDER_NONE must be last */ } H5T_order_t; //! [H5T_order_t_snip] @@ -67,11 +67,11 @@ typedef enum H5T_order_t { */ //! [H5T_sign_t_snip] typedef enum H5T_sign_t { - H5T_SGN_ERROR = -1, /**< error */ - H5T_SGN_NONE = 0, /**< this is an unsigned type */ - H5T_SGN_2 = 1, /**< two's complement */ + H5T_SGN_ERROR = -1, /**< error */ + H5T_SGN_NONE = 0, /**< this is an unsigned type */ + H5T_SGN_2 = 1, /**< two's complement */ - H5T_NSGN = 2 /** sentinel: this must be last! */ + H5T_NSGN = 2 /** sentinel: this must be last! */ } H5T_sign_t; //! [H5T_sign_t_snip] @@ -80,10 +80,10 @@ typedef enum H5T_sign_t { */ //! [H5T_norm_t_snip] typedef enum H5T_norm_t { - H5T_NORM_ERROR = -1, /**< error */ - H5T_NORM_IMPLIED = 0, /**< msb of mantissa isn't stored, always 1 */ - H5T_NORM_MSBSET = 1, /**< msb of mantissa is always 1 */ - H5T_NORM_NONE = 2 /**< not normalized */ + H5T_NORM_ERROR = -1, /**< error */ + H5T_NORM_IMPLIED = 0, /**< msb of mantissa isn't stored, always 1 */ + H5T_NORM_MSBSET = 1, /**< msb of mantissa is always 1 */ + H5T_NORM_NONE = 2 /**< not normalized */ /*H5T_NORM_NONE must be last */ } H5T_norm_t; //! [H5T_norm_t_snip] @@ -93,62 +93,62 @@ typedef enum H5T_norm_t { * \internal Do not change these values since they appear in HDF5 files! */ typedef enum H5T_cset_t { - H5T_CSET_ERROR = -1, /**< error */ - H5T_CSET_ASCII = 0, /**< US ASCII */ - H5T_CSET_UTF8 = 1, /**< UTF-8 Unicode encoding */ - H5T_CSET_RESERVED_2 = 2, /**< reserved for later use */ - H5T_CSET_RESERVED_3 = 3, /**< reserved for later use */ - H5T_CSET_RESERVED_4 = 4, /**< reserved for later use */ - H5T_CSET_RESERVED_5 = 5, /**< reserved for later use */ - H5T_CSET_RESERVED_6 = 6, /**< reserved for later use */ - H5T_CSET_RESERVED_7 = 7, /**< reserved for later use */ - H5T_CSET_RESERVED_8 = 8, /**< reserved for later use */ - H5T_CSET_RESERVED_9 = 9, /**< reserved for later use */ - H5T_CSET_RESERVED_10 = 10, /**< reserved for later use */ - H5T_CSET_RESERVED_11 = 11, /**< reserved for later use */ - H5T_CSET_RESERVED_12 = 12, /**< reserved for later use */ - H5T_CSET_RESERVED_13 = 13, /**< reserved for later use */ - H5T_CSET_RESERVED_14 = 14, /**< reserved for later use */ - H5T_CSET_RESERVED_15 = 15 /**< reserved for later use */ + H5T_CSET_ERROR = -1, /**< error */ + H5T_CSET_ASCII = 0, /**< US ASCII */ + H5T_CSET_UTF8 = 1, /**< UTF-8 Unicode encoding */ + H5T_CSET_RESERVED_2 = 2, /**< reserved for later use */ + H5T_CSET_RESERVED_3 = 3, /**< reserved for later use */ + H5T_CSET_RESERVED_4 = 4, /**< reserved for later use */ + H5T_CSET_RESERVED_5 = 5, /**< reserved for later use */ + H5T_CSET_RESERVED_6 = 6, /**< reserved for later use */ + H5T_CSET_RESERVED_7 = 7, /**< reserved for later use */ + H5T_CSET_RESERVED_8 = 8, /**< reserved for later use */ + H5T_CSET_RESERVED_9 = 9, /**< reserved for later use */ + H5T_CSET_RESERVED_10 = 10, /**< reserved for later use */ + H5T_CSET_RESERVED_11 = 11, /**< reserved for later use */ + H5T_CSET_RESERVED_12 = 12, /**< reserved for later use */ + H5T_CSET_RESERVED_13 = 13, /**< reserved for later use */ + H5T_CSET_RESERVED_14 = 14, /**< reserved for later use */ + H5T_CSET_RESERVED_15 = 15 /**< reserved for later use */ } H5T_cset_t; -#define H5T_NCSET H5T_CSET_RESERVED_2 /*Number of character sets actually defined */ +#define H5T_NCSET H5T_CSET_RESERVED_2 /*Number of character sets actually defined */ /** * Type of padding to use in character strings. * \internal Do not change these values since they appear in HDF5 files! */ typedef enum H5T_str_t { - H5T_STR_ERROR = -1, /**< error */ - H5T_STR_NULLTERM = 0, /**< null terminate like in C */ - H5T_STR_NULLPAD = 1, /**< pad with nulls */ - H5T_STR_SPACEPAD = 2, /**< pad with spaces like in Fortran */ - H5T_STR_RESERVED_3 = 3, /**< reserved for later use */ - H5T_STR_RESERVED_4 = 4, /**< reserved for later use */ - H5T_STR_RESERVED_5 = 5, /**< reserved for later use */ - H5T_STR_RESERVED_6 = 6, /**< reserved for later use */ - H5T_STR_RESERVED_7 = 7, /**< reserved for later use */ - H5T_STR_RESERVED_8 = 8, /**< reserved for later use */ - H5T_STR_RESERVED_9 = 9, /**< reserved for later use */ - H5T_STR_RESERVED_10 = 10, /**< reserved for later use */ - H5T_STR_RESERVED_11 = 11, /**< reserved for later use */ - H5T_STR_RESERVED_12 = 12, /**< reserved for later use */ - H5T_STR_RESERVED_13 = 13, /**< reserved for later use */ - H5T_STR_RESERVED_14 = 14, /**< reserved for later use */ - H5T_STR_RESERVED_15 = 15 /**< reserved for later use */ + H5T_STR_ERROR = -1, /**< error */ + H5T_STR_NULLTERM = 0, /**< null terminate like in C */ + H5T_STR_NULLPAD = 1, /**< pad with nulls */ + H5T_STR_SPACEPAD = 2, /**< pad with spaces like in Fortran */ + H5T_STR_RESERVED_3 = 3, /**< reserved for later use */ + H5T_STR_RESERVED_4 = 4, /**< reserved for later use */ + H5T_STR_RESERVED_5 = 5, /**< reserved for later use */ + H5T_STR_RESERVED_6 = 6, /**< reserved for later use */ + H5T_STR_RESERVED_7 = 7, /**< reserved for later use */ + H5T_STR_RESERVED_8 = 8, /**< reserved for later use */ + H5T_STR_RESERVED_9 = 9, /**< reserved for later use */ + H5T_STR_RESERVED_10 = 10, /**< reserved for later use */ + H5T_STR_RESERVED_11 = 11, /**< reserved for later use */ + H5T_STR_RESERVED_12 = 12, /**< reserved for later use */ + H5T_STR_RESERVED_13 = 13, /**< reserved for later use */ + H5T_STR_RESERVED_14 = 14, /**< reserved for later use */ + H5T_STR_RESERVED_15 = 15 /**< reserved for later use */ } H5T_str_t; -#define H5T_NSTR H5T_STR_RESERVED_3 /*num H5T_str_t types actually defined */ +#define H5T_NSTR H5T_STR_RESERVED_3 /*num H5T_str_t types actually defined */ /** * Type of padding to use in other atomic types */ //! [H5T_pad_t_snip] typedef enum H5T_pad_t { - H5T_PAD_ERROR = -1, /**< error */ - H5T_PAD_ZERO = 0, /**< always set to zero */ - H5T_PAD_ONE = 1, /**< always set to one */ - H5T_PAD_BACKGROUND = 2, /**< set to background value */ + H5T_PAD_ERROR = -1, /**< error */ + H5T_PAD_ZERO = 0, /**< always set to zero */ + H5T_PAD_ONE = 1, /**< always set to one */ + H5T_PAD_BACKGROUND = 2, /**< set to background value */ - H5T_NPAD = 3 /**< sentinal: THIS MUST BE LAST */ + H5T_NPAD = 3 /**< sentinal: THIS MUST BE LAST */ } H5T_pad_t; //! [H5T_pad_t_snip] @@ -156,18 +156,18 @@ typedef enum H5T_pad_t { * Commands sent to conversion functions */ typedef enum H5T_cmd_t { - H5T_CONV_INIT = 0, /**< query and/or initialize private data */ - H5T_CONV_CONV = 1, /**< convert data from source to dest datatype */ - H5T_CONV_FREE = 2 /**< function is being removed from path */ + H5T_CONV_INIT = 0, /**< query and/or initialize private data */ + H5T_CONV_CONV = 1, /**< convert data from source to dest datatype */ + H5T_CONV_FREE = 2 /**< function is being removed from path */ } H5T_cmd_t; /** * How is the `bkg' buffer used by the conversion function? */ typedef enum H5T_bkg_t { - H5T_BKG_NO = 0, /**< background buffer is not needed, send NULL */ - H5T_BKG_TEMP = 1, /**< bkg buffer used as temp storage only */ - H5T_BKG_YES = 2 /**< init bkg buf with data before conversion */ + H5T_BKG_NO = 0, /**< background buffer is not needed, send NULL */ + H5T_BKG_TEMP = 1, /**< bkg buffer used as temp storage only */ + H5T_BKG_YES = 2 /**< init bkg buf with data before conversion */ } H5T_bkg_t; /** @@ -175,10 +175,10 @@ typedef enum H5T_bkg_t { */ //! [H5T_cdata_t_snip] typedef struct H5T_cdata_t { - H5T_cmd_t command;/**< what should the conversion function do? */ - H5T_bkg_t need_bkg;/**< is the background buffer needed? */ - hbool_t recalc; /**< recalculate private data */ - void *priv; /**< private data */ + H5T_cmd_t command; /**< what should the conversion function do? */ + H5T_bkg_t need_bkg; /**< is the background buffer needed? */ + hbool_t recalc; /**< recalculate private data */ + void * priv; /**< private data */ } H5T_cdata_t; //! [H5T_cdata_t_snip] @@ -186,9 +186,9 @@ typedef struct H5T_cdata_t { * Conversion function persistence */ typedef enum H5T_pers_t { - H5T_PERS_DONTCARE = -1, /**< wild card */ - H5T_PERS_HARD = 0, /**< hard conversion function */ - H5T_PERS_SOFT = 1 /**< soft conversion function */ + H5T_PERS_DONTCARE = -1, /**< wild card */ + H5T_PERS_HARD = 0, /**< hard conversion function */ + H5T_PERS_SOFT = 1 /**< soft conversion function */ } H5T_pers_t; /** @@ -196,9 +196,9 @@ typedef enum H5T_pers_t { */ //! [H5T_direction_t_snip] typedef enum H5T_direction_t { - H5T_DIR_DEFAULT = 0, /**< default direction is inscendent */ - H5T_DIR_ASCEND = 1, /**< in inscendent order */ - H5T_DIR_DESCEND = 2 /**< in descendent order */ + H5T_DIR_DEFAULT = 0, /**< default direction is inscendent */ + H5T_DIR_ASCEND = 1, /**< in inscendent order */ + H5T_DIR_DESCEND = 2 /**< in descendent order */ } H5T_direction_t; //! [H5T_direction_t_snip] @@ -206,22 +206,22 @@ typedef enum H5T_direction_t { * The exception type passed into the conversion callback function */ typedef enum H5T_conv_except_t { - H5T_CONV_EXCEPT_RANGE_HI = 0, /**< source value is greater than destination's range */ - H5T_CONV_EXCEPT_RANGE_LOW = 1, /**< source value is less than destination's range */ - H5T_CONV_EXCEPT_PRECISION = 2, /**< source value loses precision in destination */ - H5T_CONV_EXCEPT_TRUNCATE = 3, /**< source value is truncated in destination */ - H5T_CONV_EXCEPT_PINF = 4, /**< source value is positive infinity(floating number) */ - H5T_CONV_EXCEPT_NINF = 5, /**< source value is negative infinity(floating number) */ - H5T_CONV_EXCEPT_NAN = 6 /**< source value is NaN(floating number) */ + H5T_CONV_EXCEPT_RANGE_HI = 0, /**< source value is greater than destination's range */ + H5T_CONV_EXCEPT_RANGE_LOW = 1, /**< source value is less than destination's range */ + H5T_CONV_EXCEPT_PRECISION = 2, /**< source value loses precision in destination */ + H5T_CONV_EXCEPT_TRUNCATE = 3, /**< source value is truncated in destination */ + H5T_CONV_EXCEPT_PINF = 4, /**< source value is positive infinity(floating number) */ + H5T_CONV_EXCEPT_NINF = 5, /**< source value is negative infinity(floating number) */ + H5T_CONV_EXCEPT_NAN = 6 /**< source value is NaN(floating number) */ } H5T_conv_except_t; /** * The return value from conversion callback function H5T_conv_except_func_t() */ typedef enum H5T_conv_ret_t { - H5T_CONV_ABORT = -1, /**< abort conversion */ - H5T_CONV_UNHANDLED = 0, /**< callback function failed to handle the exception */ - H5T_CONV_HANDLED = 1 /**< callback function handled the exception successfully */ + H5T_CONV_ABORT = -1, /**< abort conversion */ + H5T_CONV_UNHANDLED = 0, /**< callback function failed to handle the exception */ + H5T_CONV_HANDLED = 1 /**< callback function handled the exception successfully */ } H5T_conv_ret_t; /** @@ -1128,6 +1128,16 @@ H5_DLL herr_t H5Tclose(hid_t type_id); /** * \ingroup H5T * + * \brief Asynchronous version of H5Tclose(). + * + * \todo Create an example for H5Tclose_async(). + * + */ +H5_DLL herr_t H5Tclose_async(const char *app_file, const char *app_func, unsigned app_line, hid_t type_id, + hid_t es_id); +/** + * \ingroup H5T + * * \brief Determines whether two datatype identifiers refer to the same datatype * * \type_id{type1_id} @@ -1208,6 +1218,17 @@ H5_DLL herr_t H5Tlock(hid_t type_id); H5_DLL herr_t H5Tcommit2(hid_t loc_id, const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id); /** + * \ingroup H5T + * + * \brief Asynchronous version of H5Tcommit2(). + * + * \todo Create an example for H5Tcommit_async(). + * + */ +H5_DLL herr_t H5Tcommit_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id, + hid_t es_id); +/** * -------------------------------------------------------------------------- * \ingroup H5T * @@ -1234,6 +1255,16 @@ H5_DLL hid_t H5Topen2(hid_t loc_id, const char *name, hid_t tapl_id); /** * \ingroup H5T * + * \brief Asynchronous version of H5Topen2(). + * + * \todo Create an example for H5Topen_async(). + * + */ +H5_DLL hid_t H5Topen_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, + const char *name, hid_t tapl_id, hid_t es_id); +/** + * \ingroup H5T + * * \brief Commits a transient datatype to a file, creating a new named * datatype, but does not link it into the file structure * @@ -2875,6 +2906,22 @@ H5_DLL herr_t H5Treclaim(hid_t type_id, hid_t space_id, hid_t plist_id, void *bu * * Use of these symbols is deprecated. */ + +/* API Wrappers for async routines */ +/* (Must be defined _after_ the function prototype) */ +/* (And must only defined when included in application code, not the library) */ +#ifndef H5T_MODULE +#define H5Tcommit_async(...) H5Tcommit_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Topen_async(...) H5Topen_async(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define H5Tclose_async(...) H5Tclose_async(__FILE__, __func__, __LINE__, __VA_ARGS__) + +/* Define "wrapper" versions of function calls, to allow compile-time values to + * be passed in by language wrapper or library layer on top of HDF5. */ +#define H5Tcommit_async_wrap H5_NO_EXPAND(H5Tcommit_async) +#define H5Topen_async_wrap H5_NO_EXPAND(H5Topen_async) +#define H5Tclose_async_wrap H5_NO_EXPAND(H5Tclose_async) +#endif /* H5T_MODULE */ + #ifndef H5_NO_DEPRECATED_SYMBOLS /* Macros */ @@ -92,8 +92,7 @@ H5VLregister_connector(const H5VL_class_t *cls, hid_t vipl_id) 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") + 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") @@ -631,6 +630,7 @@ H5VLwrap_register(void *obj, H5I_type_t type) case H5I_ERROR_MSG: case H5I_ERROR_STACK: case H5I_SPACE_SEL_ITER: + case H5I_EVENTSET: case H5I_NTYPES: default: HGOTO_ERROR(H5E_VOL, H5E_BADRANGE, H5I_INVALID_HID, "invalid type number") diff --git a/src/H5VLcallback.c b/src/H5VLcallback.c index 427e447..4ab398f 100644 --- a/src/H5VLcallback.c +++ b/src/H5VLcallback.c @@ -153,9 +153,10 @@ static herr_t H5VL__introspect_get_conn_cls(void *obj, const H5VL_class_t *cls, const H5VL_class_t **conn_cls); static herr_t H5VL__introspect_opt_query(void *obj, const H5VL_class_t *cls, H5VL_subclass_t subcls, int opt_type, uint64_t *flags); -static herr_t H5VL__request_wait(void *req, const H5VL_class_t *cls, uint64_t timeout, H5ES_status_t *status); +static herr_t H5VL__request_wait(void *req, const H5VL_class_t *cls, uint64_t timeout, + H5VL_request_status_t *status); static herr_t H5VL__request_notify(void *req, const H5VL_class_t *cls, H5VL_request_notify_t cb, void *ctx); -static herr_t H5VL__request_cancel(void *req, const H5VL_class_t *cls); +static herr_t H5VL__request_cancel(void *req, const H5VL_class_t *cls, H5VL_request_status_t *status); static herr_t H5VL__request_specific(void *req, const H5VL_class_t *cls, H5VL_request_specific_t specific_type, va_list arguments); static herr_t H5VL__request_optional(void *req, const H5VL_class_t *cls, H5VL_request_optional_t opt_type, @@ -5941,16 +5942,13 @@ done: * * Purpose: Waits on an asychronous request through the VOL * - * Note: Releases the request if the operation has completed and the - * connector callback succeeds - * * Return: Success: Non-negative * Failure: Negative * *------------------------------------------------------------------------- */ static herr_t -H5VL__request_wait(void *req, const H5VL_class_t *cls, uint64_t timeout, H5ES_status_t *status) +H5VL__request_wait(void *req, const H5VL_class_t *cls, uint64_t timeout, H5VL_request_status_t *status) { herr_t ret_value = SUCCEED; /* Return value */ @@ -5978,16 +5976,13 @@ done: * * Purpose: Waits on an asychronous request through the VOL * - * Note: Releases the request if the operation has completed and the - * connector callback succeeds - * * Return: Success: Non-negative * Failure: Negative * *------------------------------------------------------------------------- */ herr_t -H5VL_request_wait(const H5VL_object_t *vol_obj, uint64_t timeout, H5ES_status_t *status) +H5VL_request_wait(const H5VL_object_t *vol_obj, uint64_t timeout, H5VL_request_status_t *status) { hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */ herr_t ret_value = SUCCEED; /* Return value */ @@ -6019,16 +6014,13 @@ done: * * Purpose: Waits on a request * - * Note: Releases the request if the operation has completed and the - * connector callback succeeds - * * Return: Success: Non-negative * Failure: Negative * *------------------------------------------------------------------------- */ herr_t -H5VLrequest_wait(void *req, hid_t connector_id, uint64_t timeout, H5ES_status_t *status /*out*/) +H5VLrequest_wait(void *req, hid_t connector_id, uint64_t timeout, H5VL_request_status_t *status /*out*/) { H5VL_class_t *cls; /* VOL connector's class struct */ herr_t ret_value = SUCCEED; /* Return value */ @@ -6054,8 +6046,6 @@ done: * Purpose: Registers a user callback to be invoked when an asynchronous * operation completes * - * Note: Releases the request, if connector callback succeeds - * * Return: Success: Non-negative * Failure: Negative * @@ -6090,8 +6080,6 @@ done: * Purpose: Registers a user callback to be invoked when an asynchronous * operation completes * - * Note: Releases the request, if connector callback succeeds - * * Return: Success: Non-negative * Failure: Negative * @@ -6131,8 +6119,6 @@ done: * Purpose: Registers a user callback to be invoked when an asynchronous * operation completes * - * Note: Releases the request, if connector callback succeeds - * * Return: Success: Non-negative * Failure: Negative * @@ -6164,15 +6150,13 @@ done: * * Purpose: Cancels an asynchronous request through the VOL * - * Note: Releases the request, if connector callback succeeds - * * Return: Success: Non-negative * Failure: Negative * *------------------------------------------------------------------------- */ static herr_t -H5VL__request_cancel(void *req, const H5VL_class_t *cls) +H5VL__request_cancel(void *req, const H5VL_class_t *cls, H5VL_request_status_t *status) { herr_t ret_value = SUCCEED; /* Return value */ @@ -6187,7 +6171,7 @@ H5VL__request_cancel(void *req, const H5VL_class_t *cls) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'async cancel' method") /* Call the corresponding VOL callback */ - if ((cls->request_cls.cancel)(req) < 0) + if ((cls->request_cls.cancel)(req, status) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "request cancel failed") done: @@ -6199,15 +6183,13 @@ done: * * Purpose: Cancels an asynchronous request through the VOL * - * Note: Releases the request, if connector callback succeeds - * * Return: Success: Non-negative * Failure: Negative * *------------------------------------------------------------------------- */ herr_t -H5VL_request_cancel(const H5VL_object_t *vol_obj) +H5VL_request_cancel(const H5VL_object_t *vol_obj, H5VL_request_status_t *status) { hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */ herr_t ret_value = SUCCEED; /* Return value */ @@ -6223,7 +6205,7 @@ H5VL_request_cancel(const H5VL_object_t *vol_obj) vol_wrapper_set = TRUE; /* Call the corresponding internal VOL routine */ - if (H5VL__request_cancel(vol_obj->data, vol_obj->connector->cls) < 0) + if (H5VL__request_cancel(vol_obj->data, vol_obj->connector->cls, status) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "request cancel failed") done: @@ -6239,28 +6221,26 @@ done: * * Purpose: Cancels a request * - * Note: Releases the request, if connector callback succeeds - * * Return: Success: Non-negative * Failure: Negative * *------------------------------------------------------------------------- */ herr_t -H5VLrequest_cancel(void *req, hid_t connector_id) +H5VLrequest_cancel(void *req, hid_t connector_id, H5VL_request_status_t *status) { H5VL_class_t *cls; /* VOL connector's class struct */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API_NOINIT - H5TRACE2("e", "*xi", req, connector_id); + H5TRACE3("e", "*xi*#", req, connector_id, status); /* Get class pointer */ if (NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a VOL connector ID") /* Call the corresponding internal VOL routine */ - if (H5VL__request_cancel(req, cls) < 0) + if (H5VL__request_cancel(req, cls, status) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to cancel request") done: diff --git a/src/H5VLconnector.h b/src/H5VLconnector.h index d873019..442a15c 100644 --- a/src/H5VLconnector.h +++ b/src/H5VLconnector.h @@ -81,7 +81,8 @@ typedef enum H5VL_dataset_get_t { typedef enum H5VL_dataset_specific_t { H5VL_DATASET_SET_EXTENT, /* H5Dset_extent */ H5VL_DATASET_FLUSH, /* H5Dflush */ - H5VL_DATASET_REFRESH /* H5Drefresh */ + H5VL_DATASET_REFRESH, /* H5Drefresh */ + H5VL_DATASET_WAIT /* H5Dwait */ } H5VL_dataset_specific_t; /* Typedef for VOL connector dataset optional VOL operations */ @@ -120,7 +121,8 @@ typedef enum H5VL_file_specific_t { H5VL_FILE_UNMOUNT, /* Unmount a file */ H5VL_FILE_IS_ACCESSIBLE, /* Check if a file is accessible */ H5VL_FILE_DELETE, /* Delete a file */ - H5VL_FILE_IS_EQUAL /* Check if two files are the same */ + H5VL_FILE_IS_EQUAL, /* Check if two files are the same */ + H5VL_FILE_WAIT /* Wait for async operations to complete */ } H5VL_file_specific_t; /* Typedef for VOL connector file optional VOL operations */ @@ -184,11 +186,25 @@ typedef enum H5VL_object_specific_t { /* Typedef for VOL connector object optional VOL operations */ typedef int H5VL_object_optional_t; +/* Status values for async request operations */ +typedef enum H5VL_request_status_t { + H5VL_REQUEST_STATUS_IN_PROGRESS, /* Operation has not yet completed */ + H5VL_REQUEST_STATUS_SUCCEED, /* Operation has completed, successfully */ + H5VL_REQUEST_STATUS_FAIL, /* Operation has completed, but failed */ + H5VL_REQUEST_STATUS_CANT_CANCEL, /* An attempt to cancel this operation was made, but it */ + /* can't be canceled immediately. The operation has */ + /* not completed successfully or failed, and is not yet */ + /* in progress. Another attempt to cancel it may be */ + /* attempted and may (or may not) succeed. */ + H5VL_REQUEST_STATUS_CANCELED /* Operation has not completed and was canceled */ +} H5VL_request_status_t; + /* types for async request SPECIFIC callback */ typedef enum H5VL_request_specific_t { - H5VL_REQUEST_WAITANY, /* Wait until any request completes */ - H5VL_REQUEST_WAITSOME, /* Wait until at least one requesst completes */ - H5VL_REQUEST_WAITALL /* Wait until all requests complete */ + H5VL_REQUEST_WAITANY, /* Wait until any request completes */ + H5VL_REQUEST_WAITSOME, /* Wait until at least one requesst completes */ + H5VL_REQUEST_WAITALL, /* Wait until all requests complete */ + H5VL_REQUEST_GET_ERR_STACK /* Retrieve error stack for failed operation */ } H5VL_request_specific_t; /* Typedef and values for native VOL connector request optional VOL operations */ @@ -394,7 +410,7 @@ typedef struct H5VL_object_class_t { } H5VL_object_class_t; /* Asynchronous request 'notify' callback */ -typedef herr_t (*H5VL_request_notify_t)(void *ctx, H5ES_status_t status); +typedef herr_t (*H5VL_request_notify_t)(void *ctx, H5VL_request_status_t status); /* "Levels" for 'get connector class' introspection callback */ typedef enum H5VL_get_conn_lvl_t { @@ -415,9 +431,9 @@ typedef struct H5VL_introspect_class_t { /* Async request operation routines */ typedef struct H5VL_request_class_t { - herr_t (*wait)(void *req, uint64_t timeout, H5ES_status_t *status); + herr_t (*wait)(void *req, uint64_t timeout, H5VL_request_status_t *status); herr_t (*notify)(void *req, H5VL_request_notify_t cb, void *ctx); - herr_t (*cancel)(void *req); + herr_t (*cancel)(void *req, H5VL_request_status_t *status); herr_t (*specific)(void *req, H5VL_request_specific_t specific_type, va_list arguments); herr_t (*optional)(void *req, H5VL_request_optional_t opt_type, va_list arguments); herr_t (*free)(void *req); diff --git a/src/H5VLconnector_passthru.h b/src/H5VLconnector_passthru.h index 053d912..54864b7 100644 --- a/src/H5VLconnector_passthru.h +++ b/src/H5VLconnector_passthru.h @@ -198,9 +198,10 @@ H5_DLL herr_t H5VLintrospect_opt_query(void *obj, hid_t connector_id, H5VL_subcl uint64_t *flags); /* Public wrappers for asynchronous request callbacks */ -H5_DLL herr_t H5VLrequest_wait(void *req, hid_t connector_id, uint64_t timeout, H5ES_status_t *status); +H5_DLL herr_t H5VLrequest_wait(void *req, hid_t connector_id, uint64_t timeout, + H5VL_request_status_t *status); H5_DLL herr_t H5VLrequest_notify(void *req, hid_t connector_id, H5VL_request_notify_t cb, void *ctx); -H5_DLL herr_t H5VLrequest_cancel(void *req, hid_t connector_id); +H5_DLL herr_t H5VLrequest_cancel(void *req, hid_t connector_id, H5VL_request_status_t *status); H5_DLL herr_t H5VLrequest_specific(void *req, hid_t connector_id, H5VL_request_specific_t specific_type, va_list arguments); H5_DLL herr_t H5VLrequest_optional(void *req, hid_t connector_id, H5VL_request_optional_t opt_type, diff --git a/src/H5VLint.c b/src/H5VLint.c index cdd8139..bc06361 100644 --- a/src/H5VLint.c +++ b/src/H5VLint.c @@ -92,8 +92,6 @@ 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); @@ -572,7 +570,7 @@ H5VL__new_vol_obj(H5I_type_t type, void *object, H5VL_t *vol_connector, hbool_t new_vol_obj->data = object; /* 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 */ @@ -586,7 +584,7 @@ H5VL__new_vol_obj(H5I_type_t type, void *object, H5VL_t *vol_connector, hbool_t done: /* Cleanup on error */ if (NULL == ret_value) { - if (conn_rc_incr && H5VL__conn_dec_rc(vol_connector) < 0) + 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 */ @@ -816,6 +814,45 @@ done: } /* 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; + + /* 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 @@ -871,7 +908,7 @@ done: } /* 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. * @@ -882,10 +919,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(-1) /* Check arguments */ HDassert(connector); @@ -893,11 +932,14 @@ 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; + +done: + 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. * @@ -908,12 +950,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 */ - FUNC_ENTER_STATIC + FUNC_ENTER_NOAPI(-1) /* Check arguments */ HDassert(connector); @@ -936,7 +978,7 @@ 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_free_object @@ -959,7 +1001,7 @@ H5VL_free_object(H5VL_object_t *vol_obj) HDassert(vol_obj); /* Decrement refcount on connector */ - if (H5VL__conn_dec_rc(vol_obj->connector) < 0) + 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); @@ -1776,6 +1818,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") @@ -2095,7 +2138,7 @@ H5VL__free_vol_wrapper(H5VL_wrap_ctx_t *vol_wrap_ctx) "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 */ @@ -2152,7 +2195,7 @@ H5VL_set_vol_wrapper(const H5VL_object_t *vol_obj) HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, FAIL, "can't allocate VOL wrap context") /* Increment the outstanding objects that are using the connector */ - H5VL__conn_inc_rc(vol_obj->connector); + H5VL_conn_inc_rc(vol_obj->connector); /* Set up VOL object wrapper context */ vol_wrap_ctx->rc = 1; @@ -2362,7 +2405,7 @@ done: 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 */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -2375,16 +2418,16 @@ H5VL_check_plugin_load(const H5VL_class_t *cls, const H5PL_key_t *key, hbool_t * 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 */ + *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 */ + *success = TRUE; + } /* end else */ /* Connector is a match, but might not be a compatible version */ if (*success && cls->version != H5VL_VERSION) @@ -2393,3 +2436,273 @@ H5VL_check_plugin_load(const H5VL_class_t *cls, const H5PL_key_t *key, hbool_t * done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_check_plugin_load() */ + +/*------------------------------------------------------------------------- + * 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, 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(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(&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 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 = acspl_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, + 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(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(&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_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 = acspl_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() */ diff --git a/src/H5VLnative.c b/src/H5VLnative.c index 746264f..72c1b0c 100644 --- a/src/H5VLnative.c +++ b/src/H5VLnative.c @@ -19,23 +19,23 @@ /* Module Setup */ /****************/ -#define H5VL_FRIEND /* Suppress error about including H5VLpkg */ +#define H5VL_FRIEND /* Suppress error about including H5VLpkg */ /***********/ /* Headers */ /***********/ -#include "H5private.h" /* Generic Functions */ -#include "H5Aprivate.h" /* Attributes */ -#include "H5Dprivate.h" /* Datasets */ -#include "H5Eprivate.h" /* Error handling */ -#include "H5Fprivate.h" /* Files */ -#include "H5Gprivate.h" /* Groups */ -#include "H5Iprivate.h" /* IDs */ -#include "H5Oprivate.h" /* Object headers */ -#include "H5Pprivate.h" /* Property lists */ -#include "H5Tprivate.h" /* Datatypes */ -#include "H5VLpkg.h" /* Virtual Object Layer */ +#include "H5private.h" /* Generic Functions */ +#include "H5Aprivate.h" /* Attributes */ +#include "H5Dprivate.h" /* Datasets */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fprivate.h" /* Files */ +#include "H5Gprivate.h" /* Groups */ +#include "H5Iprivate.h" /* IDs */ +#include "H5Oprivate.h" /* Object headers */ +#include "H5Pprivate.h" /* Property lists */ +#include "H5Tprivate.h" /* Datatypes */ +#include "H5VLpkg.h" /* Virtual Object Layer */ #include "H5VLnative_private.h" /* Native VOL connector */ @@ -556,6 +556,7 @@ H5VL_native_get_file_struct(void *obj, H5I_type_t type, H5F_t **file) 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, FAIL, "not a file or file object") diff --git a/src/H5VLnative_attr.c b/src/H5VLnative_attr.c index 0c8de6c..3a231c9 100644 --- a/src/H5VLnative_attr.c +++ b/src/H5VLnative_attr.c @@ -430,17 +430,18 @@ H5VL__native_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_ } case H5VL_ATTR_EXISTS: { - const char *attr_name = HDva_arg(arguments, const char *); - htri_t * ret = HDva_arg(arguments, htri_t *); + const char *attr_name = HDva_arg(arguments, const char *); + hbool_t * attr_exists = HDva_arg(arguments, hbool_t *); if (loc_params->type == H5VL_OBJECT_BY_SELF) { /* H5Aexists */ /* Check if the attribute exists */ - if ((*ret = H5O__attr_exists(loc.oloc, attr_name)) < 0) + if (H5O__attr_exists(loc.oloc, attr_name, attr_exists) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to determine if attribute exists") } /* end if */ else if (loc_params->type == H5VL_OBJECT_BY_NAME) { /* H5Aexists_by_name */ /* Check if the attribute exists */ - if ((*ret = H5A__exists_by_name(loc, loc_params->loc_data.loc_by_name.name, attr_name)) < 0) + if (H5A__exists_by_name(loc, loc_params->loc_data.loc_by_name.name, attr_name, attr_exists) < + 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to determine if attribute exists") } /* end else-if */ else diff --git a/src/H5VLnative_dataset.c b/src/H5VLnative_dataset.c index b8c153d..8ba1ef5 100644 --- a/src/H5VLnative_dataset.c +++ b/src/H5VLnative_dataset.c @@ -346,6 +346,13 @@ H5VL__native_dataset_specific(void *obj, H5VL_dataset_specific_t specific_type, break; } + case H5VL_DATASET_WAIT: { /* H5Dwait */ + /* The native VOL connector doesn't support asynchronous + * operations, so this is a no-op. + */ + break; + } + default: HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "invalid specific operation") } /* end switch */ diff --git a/src/H5VLnative_file.c b/src/H5VLnative_file.c index 6fc8e9a..50ae9a5 100644 --- a/src/H5VLnative_file.c +++ b/src/H5VLnative_file.c @@ -404,6 +404,14 @@ H5VL__native_file_specific(void *obj, H5VL_file_specific_t specific_type, hid_t break; } + /* H5Fwait */ + case H5VL_FILE_WAIT: { + /* The native VOL connector doesn't support asynchronous + * operations, so this is a no-op. + */ + break; + } + default: HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "invalid specific operation") } /* end switch */ diff --git a/src/H5VLnative_link.c b/src/H5VLnative_link.c index 33221ae..5ed7f9b 100644 --- a/src/H5VLnative_link.c +++ b/src/H5VLnative_link.c @@ -318,14 +318,14 @@ H5VL__native_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_ switch (specific_type) { case H5VL_LINK_EXISTS: { - htri_t * ret = HDva_arg(arguments, htri_t *); + hbool_t * exists = HDva_arg(arguments, hbool_t *); H5G_loc_t loc; if (H5G_loc_real(obj, loc_params->obj_type, &loc) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object") /* Check for the existence of the link */ - if ((*ret = H5L__exists(&loc, loc_params->loc_data.loc_by_name.name)) < 0) + if (H5L__exists(&loc, loc_params->loc_data.loc_by_name.name, exists) < 0) HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to specific link info") break; } diff --git a/src/H5VLpassthru.c b/src/H5VLpassthru.c index 4097a75..787205c 100644 --- a/src/H5VLpassthru.c +++ b/src/H5VLpassthru.c @@ -228,9 +228,9 @@ static herr_t H5VL_pass_through_introspect_opt_query(void *obj, H5VL_subclass_t uint64_t *flags); /* Async request callbacks */ -static herr_t H5VL_pass_through_request_wait(void *req, uint64_t timeout, H5ES_status_t *status); +static herr_t H5VL_pass_through_request_wait(void *req, uint64_t timeout, H5VL_request_status_t *status); static herr_t H5VL_pass_through_request_notify(void *obj, H5VL_request_notify_t cb, void *ctx); -static herr_t H5VL_pass_through_request_cancel(void *req); +static herr_t H5VL_pass_through_request_cancel(void *req, H5VL_request_status_t *status); static herr_t H5VL_pass_through_request_specific(void *req, H5VL_request_specific_t specific_type, va_list arguments); static herr_t H5VL_pass_through_request_optional(void *req, H5VL_request_optional_t opt_type, @@ -2664,7 +2664,7 @@ H5VL_pass_through_introspect_opt_query(void *obj, H5VL_subclass_t cls, int opt_t *------------------------------------------------------------------------- */ static herr_t -H5VL_pass_through_request_wait(void *obj, uint64_t timeout, H5ES_status_t *status) +H5VL_pass_through_request_wait(void *obj, uint64_t timeout, H5VL_request_status_t *status) { H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; herr_t ret_value; @@ -2725,7 +2725,7 @@ H5VL_pass_through_request_notify(void *obj, H5VL_request_notify_t cb, void *ctx) *------------------------------------------------------------------------- */ static herr_t -H5VL_pass_through_request_cancel(void *obj) +H5VL_pass_through_request_cancel(void *obj, H5VL_request_status_t *status) { H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; herr_t ret_value; @@ -2734,7 +2734,7 @@ H5VL_pass_through_request_cancel(void *obj) printf("------- PASS THROUGH VOL REQUEST Cancel\n"); #endif - ret_value = H5VLrequest_cancel(o->under_object, o->under_vol_id); + ret_value = H5VLrequest_cancel(o->under_object, o->under_vol_id, status); if (ret_value >= 0) H5VL_pass_through_free_obj(o); @@ -2822,13 +2822,13 @@ H5VL_pass_through_request_specific(void *obj, H5VL_request_specific_t specific_t /* Release requests that have completed */ if (H5VL_REQUEST_WAITANY == specific_type) { - size_t * idx; /* Pointer to the index of completed request */ - H5ES_status_t *status; /* Pointer to the request's status */ + size_t * idx; /* Pointer to the index of completed request */ + H5VL_request_status_t *status; /* Pointer to the request's status */ /* Retrieve the remaining arguments */ idx = va_arg(tmp_arguments, size_t *); assert(*idx <= req_count); - status = va_arg(tmp_arguments, H5ES_status_t *); + status = va_arg(tmp_arguments, H5VL_request_status_t *); /* Reissue the WAITANY 'request specific' call */ ret_value = H5VL_pass_through_request_specific_reissue(o->under_object, o->under_vol_id, @@ -2844,15 +2844,15 @@ H5VL_pass_through_request_specific(void *obj, H5VL_request_specific_t specific_t } /* end if */ } /* end if */ else if (H5VL_REQUEST_WAITSOME == specific_type) { - size_t * outcount; /* # of completed requests */ - unsigned * array_of_indices; /* Array of indices for completed requests */ - H5ES_status_t *array_of_statuses; /* Array of statuses for completed requests */ + size_t * outcount; /* # of completed requests */ + unsigned * array_of_indices; /* Array of indices for completed requests */ + H5VL_request_status_t *array_of_statuses; /* Array of statuses for completed requests */ /* Retrieve the remaining arguments */ outcount = va_arg(tmp_arguments, size_t *); assert(*outcount <= req_count); array_of_indices = va_arg(tmp_arguments, unsigned *); - array_of_statuses = va_arg(tmp_arguments, H5ES_status_t *); + array_of_statuses = va_arg(tmp_arguments, H5VL_request_status_t *); /* Reissue the WAITSOME 'request specific' call */ ret_value = H5VL_pass_through_request_specific_reissue( @@ -2872,14 +2872,14 @@ H5VL_pass_through_request_specific(void *obj, H5VL_request_specific_t specific_t tmp_o = (H5VL_pass_through_t *)req_array[idx_array[u]]; H5VL_pass_through_free_obj(tmp_o); - } /* end for */ - } /* end if */ - } /* end else-if */ - else { /* H5VL_REQUEST_WAITALL == specific_type */ - H5ES_status_t *array_of_statuses; /* Array of statuses for completed requests */ + } /* end for */ + } /* end if */ + } /* end else-if */ + else { /* H5VL_REQUEST_WAITALL == specific_type */ + H5VL_request_status_t *array_of_statuses; /* Array of statuses for completed requests */ /* Retrieve the remaining arguments */ - array_of_statuses = va_arg(tmp_arguments, H5ES_status_t *); + array_of_statuses = va_arg(tmp_arguments, H5VL_request_status_t *); /* Reissue the WAITALL 'request specific' call */ ret_value = H5VL_pass_through_request_specific_reissue( diff --git a/src/H5VLpassthru.h b/src/H5VLpassthru.h index 8576d21..917c42c 100644 --- a/src/H5VLpassthru.h +++ b/src/H5VLpassthru.h @@ -25,7 +25,7 @@ /* Characteristics of the pass-through VOL connector */ #define H5VL_PASSTHRU_NAME "pass_through" -#define H5VL_PASSTHRU_VALUE 1 /* VOL connector ID */ +#define H5VL_PASSTHRU_VALUE 1 /* VOL connector ID */ #define H5VL_PASSTHRU_VERSION 0 /* Pass-through VOL connector info */ diff --git a/src/H5VLprivate.h b/src/H5VLprivate.h index b54d8aa..eefd648 100644 --- a/src/H5VLprivate.h +++ b/src/H5VLprivate.h @@ -14,7 +14,7 @@ #define _H5VLprivate_H /* Include package's public header */ -#include "H5VLpublic.h" /* Generic Functions */ +#include "H5VLpublic.h" /* Generic Functions */ /* Private headers needed by this file */ @@ -60,11 +60,13 @@ typedef enum H5VL_get_connector_kind_t { /******************************/ /* Utility functions */ -H5_DLL herr_t H5VL_init_phase1(void); -H5_DLL herr_t H5VL_init_phase2(void); -H5_DLL herr_t H5VL_cmp_connector_cls(int *cmp_value, const H5VL_class_t *cls1, const H5VL_class_t *cls2); -H5_DLL herr_t H5VL_conn_copy(H5VL_connector_prop_t *value); -H5_DLL herr_t H5VL_conn_free(const H5VL_connector_prop_t *info); +H5_DLL herr_t H5VL_init_phase1(void); +H5_DLL herr_t H5VL_init_phase2(void); +H5_DLL herr_t H5VL_cmp_connector_cls(int *cmp_value, const H5VL_class_t *cls1, const H5VL_class_t *cls2); +H5_DLL herr_t H5VL_conn_copy(H5VL_connector_prop_t *value); +H5_DLL int64_t H5VL_conn_inc_rc(H5VL_t *connector); +H5_DLL int64_t H5VL_conn_dec_rc(H5VL_t *connector); +H5_DLL herr_t H5VL_conn_free(const H5VL_connector_prop_t *info); /* Functions that deal with VOL connectors */ union H5PL_key_t; @@ -86,6 +88,7 @@ H5_DLL void *H5VL_object_data(const H5VL_object_t *vol_obj); H5_DLL void *H5VL_object_unwrap(const H5VL_object_t *vol_obj); H5_DLL void *H5VL_object_verify(hid_t id, H5I_type_t obj_type); H5_DLL H5VL_object_t *H5VL_vol_object(hid_t id); +H5_DLL H5VL_object_t *H5VL_create_object(void *object, H5VL_t *vol_connector); H5_DLL H5VL_object_t *H5VL_create_object_using_vol_id(H5I_type_t type, void *obj, hid_t connector_id); H5_DLL herr_t H5VL_free_object(H5VL_object_t *obj); H5_DLL herr_t H5VL_object_is_native(const H5VL_object_t *obj, hbool_t *is_native); @@ -115,6 +118,22 @@ H5_DLL hid_t H5VL_register_using_vol_id(H5I_type_t type, void *obj, hid_t conne H5_DLL 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); +/* Object access functions */ +struct H5P_libclass_t; +H5_DLL herr_t H5VL_setup_args(hid_t loc_id, H5I_type_t id_type, H5VL_object_t **vol_obj); +H5_DLL herr_t H5VL_setup_loc_args(hid_t loc_id, H5VL_object_t **vol_obj, H5VL_loc_params_t *loc_params); +H5_DLL herr_t H5VL_setup_acc_args(hid_t loc_id, const struct H5P_libclass_t *libclass, hbool_t is_collective, + hid_t *acspl_id, H5VL_object_t **vol_obj, H5VL_loc_params_t *loc_params); +H5_DLL herr_t H5VL_setup_self_args(hid_t loc_id, H5VL_object_t **vol_obj, H5VL_loc_params_t *loc_params); +H5_DLL herr_t H5VL_setup_name_args(hid_t loc_id, const char *name, const struct H5P_libclass_t *libclass, + hbool_t is_collective, hid_t acspl_id, H5VL_object_t **vol_obj, + H5VL_loc_params_t *loc_params); +H5_DLL 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, const struct H5P_libclass_t *libclass, hbool_t is_collective, + hid_t acspl_id, H5VL_object_t **vol_obj, H5VL_loc_params_t *loc_params); +H5_DLL 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); + /********************************** * VOL connector callback wrappers *********************************/ @@ -240,9 +259,10 @@ H5_DLL herr_t H5VL_introspect_opt_query(const H5VL_object_t *vol_obj, H5VL_subcl uint64_t *flags); /* Asynchronous functions */ -H5_DLL herr_t H5VL_request_wait(const H5VL_object_t *vol_obj, uint64_t timeout, H5ES_status_t *status); +H5_DLL herr_t H5VL_request_wait(const H5VL_object_t *vol_obj, uint64_t timeout, + H5VL_request_status_t *status); H5_DLL herr_t H5VL_request_notify(const H5VL_object_t *vol_obj, H5VL_request_notify_t cb, void *ctx); -H5_DLL herr_t H5VL_request_cancel(const H5VL_object_t *vol_obj); +H5_DLL herr_t H5VL_request_cancel(const H5VL_object_t *vol_obj, H5VL_request_status_t *status); H5_DLL herr_t H5VL_request_specific(const H5VL_object_t *vol_obj, H5VL_request_specific_t specific_type, ...); H5_DLL herr_t H5VL_request_optional(const H5VL_object_t *vol_obj, H5VL_request_optional_t opt_type, ...); H5_DLL herr_t H5VL_request_free(const H5VL_object_t *vol_obj); diff --git a/src/H5VLpublic.h b/src/H5VLpublic.h index 03bf807..12250aa 100644 --- a/src/H5VLpublic.h +++ b/src/H5VLpublic.h @@ -34,7 +34,7 @@ * implements. The HDF5 library will reject connectors with * incompatible structs. */ -#define H5VL_VERSION 1 +#define H5VL_VERSION 2 /* VOL connector identifier values * These are H5VL_class_value_t values, NOT hid_t values! @@ -103,19 +103,19 @@ typedef int H5VL_class_value_t; * (Used for various queries, etc) */ typedef enum H5VL_subclass_t { - H5VL_SUBCLS_NONE, /**< Operations outside of a subclass */ - H5VL_SUBCLS_INFO, /**< 'Info' subclass */ - H5VL_SUBCLS_WRAP, /**< 'Wrap' subclass */ - H5VL_SUBCLS_ATTR, /**< 'Attribute' subclass */ - H5VL_SUBCLS_DATASET, /**< 'Dataset' subclass */ - H5VL_SUBCLS_DATATYPE, /**< 'Named datatype' subclass */ - H5VL_SUBCLS_FILE, /**< 'File' subclass */ - H5VL_SUBCLS_GROUP, /**< 'Group' subclass */ - H5VL_SUBCLS_LINK, /**< 'Link' subclass */ - H5VL_SUBCLS_OBJECT, /**< 'Object' subclass */ - H5VL_SUBCLS_REQUEST, /**< 'Request' subclass */ - H5VL_SUBCLS_BLOB, /**< 'Blob' subclass */ - H5VL_SUBCLS_TOKEN /**< 'Token' subclass */ + H5VL_SUBCLS_NONE, /**< Operations outside of a subclass */ + H5VL_SUBCLS_INFO, /**< 'Info' subclass */ + H5VL_SUBCLS_WRAP, /**< 'Wrap' subclass */ + H5VL_SUBCLS_ATTR, /**< 'Attribute' subclass */ + H5VL_SUBCLS_DATASET, /**< 'Dataset' subclass */ + H5VL_SUBCLS_DATATYPE, /**< 'Named datatype' subclass */ + H5VL_SUBCLS_FILE, /**< 'File' subclass */ + H5VL_SUBCLS_GROUP, /**< 'Group' subclass */ + H5VL_SUBCLS_LINK, /**< 'Link' subclass */ + H5VL_SUBCLS_OBJECT, /**< 'Object' subclass */ + H5VL_SUBCLS_REQUEST, /**< 'Request' subclass */ + H5VL_SUBCLS_BLOB, /**< 'Blob' subclass */ + H5VL_SUBCLS_TOKEN /**< 'Token' subclass */ } H5VL_subclass_t; /********************/ @@ -361,8 +361,8 @@ H5_DLL herr_t H5VLquery_optional(hid_t obj_id, H5VL_subclass_t subcls, int opt_t #endif /* Semi-public headers mainly for VOL connector authors */ -#include "H5VLconnector.h" /* VOL connector author routines */ +#include "H5VLconnector.h" /* VOL connector author routines */ #include "H5VLconnector_passthru.h" /* Pass-through VOL connector author routines */ -#include "H5VLnative.h" /* Native VOL connector macros, for VOL connector authors */ +#include "H5VLnative.h" /* Native VOL connector macros, for VOL connector authors */ #endif /* _H5VLpublic_H */ diff --git a/src/H5Znbit.c b/src/H5Znbit.c index 46585fb..8b928cf 100644 --- a/src/H5Znbit.c +++ b/src/H5Znbit.c @@ -95,13 +95,13 @@ H5Z_class2_t H5Z_NBIT[1] = {{ }}; /* Local macros */ -#define H5Z_NBIT_ATOMIC 1 /* Atomic datatype class: integer/floating-point */ -#define H5Z_NBIT_ARRAY 2 /* Array datatype class */ -#define H5Z_NBIT_COMPOUND 3 /* Compound datatype class */ -#define H5Z_NBIT_NOOPTYPE 4 /* Other datatype class: nbit does no compression */ +#define H5Z_NBIT_ATOMIC 1 /* Atomic datatype class: integer/floating-point */ +#define H5Z_NBIT_ARRAY 2 /* Array datatype class */ +#define H5Z_NBIT_COMPOUND 3 /* Compound datatype class */ +#define H5Z_NBIT_NOOPTYPE 4 /* Other datatype class: nbit does no compression */ #define H5Z_NBIT_MAX_NPARMS 4096 /* Max number of parameters for filter */ -#define H5Z_NBIT_ORDER_LE 0 /* Little endian for datatype byte order */ -#define H5Z_NBIT_ORDER_BE 1 /* Big endian for datatype byte order */ +#define H5Z_NBIT_ORDER_LE 0 /* Little endian for datatype byte order */ +#define H5Z_NBIT_ORDER_BE 1 /* Big endian for datatype byte order */ /* Local variables */ diff --git a/src/H5Zpublic.h b/src/H5Zpublic.h index 56047ae..70278c3 100644 --- a/src/H5Zpublic.h +++ b/src/H5Zpublic.h @@ -216,10 +216,10 @@ typedef enum H5Z_SO_scale_type_t { * Values to decide if EDC is enabled for reading data */ typedef enum H5Z_EDC_t { - H5Z_ERROR_EDC = -1, /**< error value */ - H5Z_DISABLE_EDC = 0, - H5Z_ENABLE_EDC = 1, - H5Z_NO_EDC = 2 /**< sentinel */ + H5Z_ERROR_EDC = -1, /**< error value */ + H5Z_DISABLE_EDC = 0, + H5Z_ENABLE_EDC = 1, + H5Z_NO_EDC = 2 /**< sentinel */ } H5Z_EDC_t; /* Bit flags for H5Zget_filter_info */ @@ -230,10 +230,10 @@ typedef enum H5Z_EDC_t { * Return values for filter callback function */ typedef enum H5Z_cb_return_t { - H5Z_CB_ERROR = -1, - H5Z_CB_FAIL = 0, /**< I/O should fail if filter fails. */ - H5Z_CB_CONT = 1, /**< I/O continues if filter fails. */ - H5Z_CB_NO = 2 + H5Z_CB_ERROR = -1, + H5Z_CB_FAIL = 0, /**< I/O should fail if filter fails. */ + H5Z_CB_CONT = 1, /**< I/O continues if filter fails. */ + H5Z_CB_NO = 2 } H5Z_cb_return_t; /** diff --git a/src/H5Zscaleoffset.c b/src/H5Zscaleoffset.c index 3330c3f..05309d1 100644 --- a/src/H5Zscaleoffset.c +++ b/src/H5Zscaleoffset.c @@ -103,14 +103,14 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{ /* Local macros */ #define H5Z_SCALEOFFSET_TOTAL_NPARMS 20 /* Total number of parameters for filter */ -#define H5Z_SCALEOFFSET_PARM_SCALETYPE 0 /* "User" parameter for scale type */ -#define H5Z_SCALEOFFSET_PARM_SCALEFACTOR 1 /* "User" parameter for scale factor */ -#define H5Z_SCALEOFFSET_PARM_NELMTS 2 /* "Local" parameter for number of elements in the chunk */ -#define H5Z_SCALEOFFSET_PARM_CLASS 3 /* "Local" parameter for datatype class */ -#define H5Z_SCALEOFFSET_PARM_SIZE 4 /* "Local" parameter for datatype size */ -#define H5Z_SCALEOFFSET_PARM_SIGN 5 /* "Local" parameter for integer datatype sign */ -#define H5Z_SCALEOFFSET_PARM_ORDER 6 /* "Local" parameter for datatype byte order */ -#define H5Z_SCALEOFFSET_PARM_FILAVAIL 7 /* "Local" parameter for dataset fill value existence */ +#define H5Z_SCALEOFFSET_PARM_SCALETYPE 0 /* "User" parameter for scale type */ +#define H5Z_SCALEOFFSET_PARM_SCALEFACTOR 1 /* "User" parameter for scale factor */ +#define H5Z_SCALEOFFSET_PARM_NELMTS 2 /* "Local" parameter for number of elements in the chunk */ +#define H5Z_SCALEOFFSET_PARM_CLASS 3 /* "Local" parameter for datatype class */ +#define H5Z_SCALEOFFSET_PARM_SIZE 4 /* "Local" parameter for datatype size */ +#define H5Z_SCALEOFFSET_PARM_SIGN 5 /* "Local" parameter for integer datatype sign */ +#define H5Z_SCALEOFFSET_PARM_ORDER 6 /* "Local" parameter for datatype byte order */ +#define H5Z_SCALEOFFSET_PARM_FILAVAIL 7 /* "Local" parameter for dataset fill value existence */ #define H5Z_SCALEOFFSET_PARM_FILVAL 8 /* "Local" parameter for start location to store dataset fill value */ #define H5Z_SCALEOFFSET_CLS_INTEGER 0 /* Integer (datatype class) */ @@ -1232,7 +1232,7 @@ H5Z__filter_scaleoffset(unsigned flags, size_t cd_nelmts, const unsigned cd_valu */ minval_size = sizeof(unsigned long long) <= ((unsigned char *)*buf)[4] ? sizeof(unsigned long long) : ((unsigned char *)*buf)[4]; - minval = 0; + minval = 0; for (i = 0; i < minval_size; i++) { minval_mask = ((unsigned char *)*buf)[5 + i]; minval_mask <<= i * 8; diff --git a/src/H5Zshuffle.c b/src/H5Zshuffle.c index 6d480d7..3f56e6e 100644 --- a/src/H5Zshuffle.c +++ b/src/H5Zshuffle.c @@ -122,7 +122,7 @@ H5Z__filter_shuffle(unsigned flags, size_t cd_nelmts, const unsigned cd_values[] size_t numofelements; /* Number of elements in buffer */ size_t i; /* Local index variables */ #ifdef NO_DUFFS_DEVICE - size_t j; /* Local index variable */ + size_t j; /* Local index variable */ #endif /* NO_DUFFS_DEVICE */ size_t leftover; /* Extra bytes at end of buffer */ size_t ret_value = 0; /* Return value */ diff --git a/src/H5err.txt b/src/H5err.txt index e2904fa..671eb66 100644 --- a/src/H5err.txt +++ b/src/H5err.txt @@ -80,6 +80,7 @@ MAJOR, H5E_PLUGIN, Plugin for dynamically loaded library MAJOR, H5E_PAGEBUF, Page Buffering MAJOR, H5E_CONTEXT, API Context MAJOR, H5E_MAP, Map +MAJOR, H5E_EVENTSET, Event Set MAJOR, H5E_NONE_MAJOR, No error # Sections (for grouping minor errors) @@ -103,6 +104,8 @@ SECTION, FSPACE, Free space errors SECTION, PIPELINE, I/O pipeline errors SECTION, SYSTEM, System level errors SECTION, PLUGIN, Plugin errors +SECTION, MAP, Map related errors +SECTION, ASYNC, Asynchronous I/O errors SECTION, NONE, No error # Minor errors @@ -202,6 +205,7 @@ MINOR, BTREE, H5E_CANTINSERT, Unable to insert object MINOR, BTREE, H5E_CANTLIST, Unable to list node MINOR, BTREE, H5E_CANTMODIFY, Unable to modify record MINOR, BTREE, H5E_CANTREMOVE, Unable to remove object +MINOR, BTREE, H5E_CANTFIND, Unable to check for record # Object header related errors MINOR, OHDR, H5E_LINKCOUNT, Bad object header link count @@ -281,5 +285,11 @@ MINOR, SYSTEM, H5E_SYSERRSTR, System error message # Plugin errors MINOR, PLUGIN, H5E_OPENERROR, Can't open directory or file +# Map related errors +MINOR, MAP, H5E_CANTPUT, Can't put value + +# Asynchronous operation errors +MINOR, ASYNC, H5E_CANTWAIT, Can't wait on operation + # No error, for backward compatibility */ MINOR, NONE, H5E_NONE_MINOR, No error diff --git a/src/H5private.h b/src/H5private.h index fd0d8f5..a539432 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -2923,6 +2923,7 @@ H5_DLL int H5CX_term_package(void); H5_DLL int H5D_term_package(void); H5_DLL int H5D_top_term_package(void); H5_DLL int H5E_term_package(void); +H5_DLL int H5ES_term_package(void); H5_DLL int H5F_term_package(void); H5_DLL int H5FD_term_package(void); H5_DLL int H5FL_term_package(void); diff --git a/src/H5public.h b/src/H5public.h index 6252778..29c8b37 100644 --- a/src/H5public.h +++ b/src/H5public.h @@ -91,12 +91,15 @@ extern "C" { #define H5_GCC_DIAG_ON(x) #endif +/* Macro to hide a symbol from further preprocessor substitutions */ +#define H5_NO_EXPAND(x) (x) + /* Version numbers */ -#define H5_VERS_MAJOR 1 /* For major interface/format changes */ -#define H5_VERS_MINOR 13 /* For minor interface/format changes */ -#define H5_VERS_RELEASE 0 /* For tweaks, bug-fixes, or development */ -#define H5_VERS_SUBRELEASE "" /* For pre-releases like snap0 */ - /* Empty string for real releases. */ +#define H5_VERS_MAJOR 1 /* For major interface/format changes */ +#define H5_VERS_MINOR 13 /* For minor interface/format changes */ +#define H5_VERS_RELEASE 0 /* For tweaks, bug-fixes, or development */ +#define H5_VERS_SUBRELEASE "" /* For pre-releases like snap0 */ +/* Empty string for real releases. */ #define H5_VERS_INFO "HDF5 library version: 1.13.0" /* Full version string */ #define H5check() H5check_version(H5_VERS_MAJOR, H5_VERS_MINOR, H5_VERS_RELEASE) diff --git a/src/H5trace.c b/src/H5trace.c index 4beecc3..911aac3 100644 --- a/src/H5trace.c +++ b/src/H5trace.c @@ -1128,10 +1128,6 @@ H5_trace_args(H5RS_str_t *rs, const char *type, va_list ap) H5RS_acat(rs, "H5ES_STATUS_FAIL"); break; - case H5ES_STATUS_CANCELED: - H5RS_acat(rs, "H5ES_STATUS_CANCELED"); - break; - default: H5RS_asprintf_cat(rs, "%ld", (long)status); break; @@ -1663,6 +1659,10 @@ H5_trace_args(H5RS_str_t *rs, const char *type, va_list ap) (unsigned long long)obj); break; + case H5I_EVENTSET: + H5RS_asprintf_cat(rs, "0x%0llx (event set)", (unsigned long long)obj); + break; + case H5I_NTYPES: H5RS_asprintf_cat(rs, "0x%0llx (ntypes - error)", (unsigned long long)obj); break; @@ -1677,6 +1677,15 @@ H5_trace_args(H5RS_str_t *rs, const char *type, va_list ap) case 'I': switch (type[1]) { + case 'D': /* H5I_future_discard_func_t */ + { + H5I_future_discard_func_t ifdisc = + (H5I_future_discard_func_t)HDva_arg(ap, H5I_future_discard_func_t); + + H5RS_asprintf_cat(rs, "%p", (void *)(uintptr_t)ifdisc); + } /* end block */ + break; + case 'f': /* H5I_free_t */ { H5I_free_t ifree = (H5I_free_t)HDva_arg(ap, H5I_free_t); @@ -1753,6 +1762,15 @@ H5_trace_args(H5RS_str_t *rs, const char *type, va_list ap) } /* end block */ break; + case 'R': /* H5I_future_realize_func_t */ + { + H5I_future_realize_func_t ifreal = + (H5I_future_realize_func_t)HDva_arg(ap, H5I_future_realize_func_t); + + H5RS_asprintf_cat(rs, "%p", (void *)(uintptr_t)ifreal); + } /* end block */ + break; + case 's': /* int / int32_t */ { int is = HDva_arg(ap, int); @@ -1843,6 +1861,10 @@ H5_trace_args(H5RS_str_t *rs, const char *type, va_list ap) H5RS_acat(rs, "H5I_SPACE_SEL_ITER"); break; + case H5I_EVENTSET: + H5RS_acat(rs, "H5I_EVENTSET"); + break; + case H5I_NTYPES: H5RS_acat(rs, "H5I_NTYPES"); break; @@ -2963,6 +2985,10 @@ H5_trace_args(H5RS_str_t *rs, const char *type, va_list ap) H5RS_acat(rs, "H5VL_DATASET_REFRESH"); break; + case H5VL_DATASET_WAIT: + H5RS_acat(rs, "H5VL_DATASET_WAIT"); + break; + default: H5RS_asprintf_cat(rs, "%ld", (long)specific); break; @@ -3087,6 +3113,10 @@ H5_trace_args(H5RS_str_t *rs, const char *type, va_list ap) H5RS_acat(rs, "H5VL_FILE_IS_EQUAL"); break; + case H5VL_FILE_WAIT: + H5RS_acat(rs, "H5VL_FILE_WAIT"); + break; + default: H5RS_asprintf_cat(rs, "%ld", (long)specific); break; @@ -3316,6 +3346,10 @@ H5_trace_args(H5RS_str_t *rs, const char *type, va_list ap) H5RS_acat(rs, "H5VL_REQUEST_WAITALL"); break; + case H5VL_REQUEST_GET_ERR_STACK: + H5RS_acat(rs, "H5VL_REQUEST_GET_ERR_STACK"); + break; + default: H5RS_asprintf_cat(rs, "%ld", (long)specific); break; diff --git a/src/H5win32defs.h b/src/H5win32defs.h index d5096e5..4db5327 100644 --- a/src/H5win32defs.h +++ b/src/H5win32defs.h @@ -199,7 +199,7 @@ H5_DLL float Wroundf(float arg); #define HDsetenv(N, V, O) Wsetenv(N, V, O) #define HDflock(F, L) Wflock(F, L) #define HDgetlogin() Wgetlogin() -#define HDsnprintf c99_snprintf /*varargs*/ +#define HDsnprintf c99_snprintf /*varargs*/ #define HDvsnprintf c99_vsnprintf /*varargs*/ /* Non-POSIX functions */ diff --git a/src/Makefile.am b/src/Makefile.am index e18b0ae..9bb2711 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -58,6 +58,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5lib_settings.c H5system.c \ H5E.c H5Edeprec.c H5Eint.c \ H5EA.c H5EAcache.c H5EAdbg.c H5EAdblkpage.c H5EAdblock.c H5EAhdr.c \ H5EAiblock.c H5EAint.c H5EAsblock.c H5EAstat.c H5EAtest.c \ + H5ES.c H5ESevent.c H5ESint.c H5ESlist.c \ H5F.c H5Faccum.c H5Fcwfs.c H5Fdbg.c H5Fdeprec.c H5Fefc.c H5Ffake.c \ H5Fint.c H5Fio.c H5Fmount.c H5Fquery.c H5Fsfile.c H5Fspace.c \ H5Fsuper.c H5Fsuper_cache.c H5Ftest.c \ @@ -154,7 +155,7 @@ include_HEADERS = hdf5.h H5api_adpt.h H5overflow.h H5pubconf.h H5public.h H5vers H5Gpublic.h H5Ipublic.h H5Lpublic.h \ H5Mpublic.h H5MMpublic.h H5Opublic.h H5Ppublic.h \ H5PLextern.h H5PLpublic.h \ - H5Rpublic.h H5Spublic.h H5Tpublic.h \ + H5Rpublic.h H5Spublic.h H5Tpublic.h H5TSpublic.h \ H5VLconnector.h H5VLconnector_passthru.h \ H5VLnative.h H5VLpassthru.h H5VLpublic.h \ H5Zpublic.h @@ -37,6 +37,7 @@ #include "H5Rpublic.h" /* References */ #include "H5Spublic.h" /* Dataspaces */ #include "H5Tpublic.h" /* Datatypes */ +#include "H5TSpublic.h" /* Thread-safety */ #include "H5VLpublic.h" /* Virtual Object Layer */ #include "H5Zpublic.h" /* Data filters */ |