diff options
Diffstat (limited to 'src/H5ES.c')
-rw-r--r-- | src/H5ES.c | 407 |
1 files changed, 336 insertions, 71 deletions
@@ -34,11 +34,12 @@ /***********/ /* Headers */ /***********/ -#include "H5private.h" /* Generic Functions */ -#include "H5Eprivate.h" /* Error handling */ +#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 */ /****************/ /* Local Macros */ @@ -103,10 +104,61 @@ done: } /* end H5EScreate() */ /*------------------------------------------------------------------------- + * Function: H5ESinsert_request + * + * Purpose: Insert a request from a VOL connector into an event set. + * + * Note: This function is primarily targeted at VOL connector + * authors and is _not_ designed for general-purpose application use. + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Friday, December 11, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESinsert_request(hid_t es_id, hid_t connector_id, void *request) +{ + H5ES_t *es; /* Event set */ + H5VL_t *connector = NULL; /* VOL connector */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "ii*x", es_id, connector_id, request); + + /* 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 == request) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL request pointer") + + /* Create new VOL connector object, using the connector ID */ + if (NULL == (connector = H5VL_new_connector(connector_id))) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTCREATE, FAIL, "can't create VOL connector object") + + /* Insert request into event set */ + if (H5ES__insert_request(es, connector, request) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTINSERT, FAIL, "can't insert request into event set") + +done: + /* Clean up on error */ + if (ret_value < 0) + /* Release newly created connector */ + if (connector && H5VL_conn_dec_rc(connector) < 0) + HDONE_ERROR(H5E_EVENTSET, H5E_CANTDEC, FAIL, "unable to decrement ref count on VOL connector") + + FUNC_LEAVE_API(ret_value) +} /* end H5ESinsert_request() */ + +/*------------------------------------------------------------------------- * Function: H5ESget_count * * Purpose: Retrieve the # of events in an event set * + * Note: H5ES_NONE is a valid value for 'es_id', but functions as a no-op + * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol @@ -117,19 +169,23 @@ done: herr_t H5ESget_count(hid_t es_id, size_t *count /*out*/) { - H5ES_t *es; /* Event set */ - herr_t ret_value = SUCCEED; /* Return value */ + 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") + /* Passing H5ES_NONE is valid, but a no-op */ + if (H5ES_NONE != es_id) { + H5ES_t *es; /* Event set */ + + /* 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); + /* Retrieve the count, if non-NULL */ + if (count) + *count = H5ES__list_count(&es->active); + } /* end if */ done: FUNC_LEAVE_API(ret_value) @@ -145,6 +201,8 @@ done: * mechanism for matching operations inserted into the event * set with [possible] errors that occur. * + * Note: H5ES_NONE is a valid value for 'es_id', but functions as a no-op + * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol @@ -155,19 +213,23 @@ done: 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 */ + 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") + /* Passing H5ES_NONE is valid, but a no-op */ + if (H5ES_NONE != es_id) { + H5ES_t *es; /* Event set */ - /* Retrieve the operation counter, if non-NULL */ - if (op_counter) - *op_counter = es->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; + } /* end if */ done: FUNC_LEAVE_API(ret_value) @@ -192,6 +254,8 @@ done: * value returned for the # of operations in progress may be * inaccurate. * + * Note: H5ES_NONE is a valid value for 'es_id', but functions as a no-op + * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol @@ -202,33 +266,82 @@ done: 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 */ + 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") + /* Passing H5ES_NONE is valid, but a no-op */ + if (H5ES_NONE != es_id) { + H5ES_t *es; /* Event set */ + + /* 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") + } /* end if */ done: FUNC_LEAVE_API(ret_value) } /* end H5ESwait() */ /*------------------------------------------------------------------------- + * Function: H5EScancel + * + * Purpose: Attempt to cancel operations in an event set + * + * Note: H5ES_NONE is a valid value for 'es_id', but functions as a no-op + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Thursday, December 10, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5EScancel(hid_t es_id, size_t *num_not_canceled /*out*/, hbool_t *op_failed /*out*/) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "ixx", es_id, num_not_canceled, op_failed); + + /* Passing H5ES_NONE is valid, but a no-op */ + if (H5ES_NONE != es_id) { + H5ES_t *es; /* Event set */ + + /* 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_not_canceled) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL num_not_canceled pointer") + if (NULL == op_failed) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL op_failed pointer") + + /* Cancel operations */ + if (H5ES__cancel(es, num_not_canceled, op_failed) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTCANCEL, FAIL, "can't cancel operations") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5EScancel() */ + +/*------------------------------------------------------------------------- * Function: H5ESget_err_status * * Purpose: Check if event set has failed operations * + * Note: H5ES_NONE is a valid value for 'es_id', but functions as a no-op + * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol @@ -239,19 +352,23 @@ done: 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 */ + 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") + /* Passing H5ES_NONE is valid, but a no-op */ + if (H5ES_NONE != es_id) { + H5ES_t *es; /* Event set */ - /* Retrieve the error flag, if non-NULL */ - if (err_status) - *err_status = es->err_occurred; + /* 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; + } /* end if */ done: FUNC_LEAVE_API(ret_value) @@ -265,6 +382,8 @@ done: * Note: Does not wait for active operations to complete, so count may * not include all failures. * + * Note: H5ES_NONE is a valid value for 'es_id', but functions as a no-op + * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol @@ -275,23 +394,27 @@ done: 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 */ + 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") + /* Passing H5ES_NONE is valid, but a no-op */ + if (H5ES_NONE != es_id) { + H5ES_t *es; /* Event set */ - /* 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 */ + /* 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 */ + } /* end if */ done: FUNC_LEAVE_API(ret_value) @@ -305,6 +428,8 @@ done: * Note: The strings retrieved for each error info must be released * by calling H5free_memory(). * + * Note: H5ES_NONE is a valid value for 'es_id', but functions as a no-op + * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol @@ -316,29 +441,164 @@ 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 */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE4("e", "izxx", es_id, num_err_info, err_info, num_cleared); + /* Passing H5ES_NONE is valid, but a no-op */ + if (H5ES_NONE != es_id) { + H5ES_t *es; /* Event set */ + + /* 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)") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ESget_err_info() */ + +/*------------------------------------------------------------------------- + * Function: H5ESfree_err_info + * + * Purpose: Convenience routine to free 1+ H5ES_err_info_t structs. + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Friday, March 5, 2021 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESfree_err_info(size_t num_err_info, H5ES_err_info_t err_info[]) +{ + size_t u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "z*#", num_err_info, err_info); + /* 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)") + /* Iterate over array, releasing error information */ + for (u = 0; u < num_err_info; u++) { + H5MM_xfree(err_info[u].api_name); + H5MM_xfree(err_info[u].api_args); + H5MM_xfree(err_info[u].app_file_name); + H5MM_xfree(err_info[u].app_func_name); + if (H5I_dec_app_ref(err_info[u].err_stack_id) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTDEC, FAIL, "can't close error stack for err_info #%zu", u) + } /* end for */ done: FUNC_LEAVE_API(ret_value) -} /* end H5ESget_err_info() */ +} /* end H5ESfree_err_info() */ + +/*------------------------------------------------------------------------- + * Function: H5ESregister_insert_func + * + * Purpose: Registers a callback to invoke when a new operation is inserted + * into an event set. + * + * Note: Only one insert callback can be registered for each event set. + * Registering a new callback will replace the existing one. + * + * Note: H5ES_NONE is a valid value for 'es_id', but functions as a no-op + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Friday, December 11, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESregister_insert_func(hid_t es_id, H5ES_event_insert_func_t func, void *ctx) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "iEI*x", es_id, func, ctx); + + /* Passing H5ES_NONE is valid, but a no-op */ + if (H5ES_NONE != es_id) { + H5ES_t *es; /* Event set */ + + /* 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 == func) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL function callback pointer") + + /* Set the event set's insert callback */ + es->ins_func = func; + es->ins_ctx = ctx; + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ESregister_insert_func() */ + +/*------------------------------------------------------------------------- + * Function: H5ESregister_complete_func + * + * Purpose: Registers a callback to invoke when an operation completes + * within an event set. + * + * Note: Only one complete callback can be registered for each event set. + * Registering a new callback will replace the existing one. + * + * Note: H5ES_NONE is a valid value for 'es_id', but functions as a no-op + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Friday, December 11, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESregister_complete_func(hid_t es_id, H5ES_event_complete_func_t func, void *ctx) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "iEC*x", es_id, func, ctx); + + /* Passing H5ES_NONE is valid, but a no-op */ + if (H5ES_NONE != es_id) { + H5ES_t *es; /* Event set */ + + /* 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 == func) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL function callback pointer") + + /* Set the event set's completion callback */ + es->comp_func = func; + es->comp_ctx = ctx; + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ESregister_complete_func() */ /*------------------------------------------------------------------------- * Function: H5ESclose @@ -347,6 +607,8 @@ done: * * Note: Fails if active operations are present. * + * Note: H5ES_NONE is a valid value for 'es_id', but functions as a no-op + * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol @@ -362,16 +624,19 @@ H5ESclose(hid_t es_id) 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") + /* Passing H5ES_NONE is valid, but a no-op */ + if (H5ES_NONE != 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") + } /* end if */ done: FUNC_LEAVE_API(ret_value) |