From 8a98abf66f4d672e6f0fbfa4719d0100b54ff2e0 Mon Sep 17 00:00:00 2001 From: Raymond Lu Date: Mon, 14 Jul 2003 15:08:27 -0500 Subject: [svn-r7225] Purpose: error API gradual checkin Platforms tested: RH 8; c and c++ --- src/H5E.c | 416 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/H5Eprivate.h | 32 +++-- src/H5Epublic.h | 36 +++-- src/H5Iprivate.h | 6 +- src/H5Ipublic.h | 4 +- test/errors.c | 92 +++++++++++- 6 files changed, 547 insertions(+), 39 deletions(-) diff --git a/src/H5E.c b/src/H5E.c index 15657c0..efe937a 100644 --- a/src/H5E.c +++ b/src/H5E.c @@ -206,8 +206,33 @@ static int interface_initialize_g = 0; * types to reset in H5E_term_interface(). */ hid_t H5E_ERR_CLS_g = FAIL; + #endif /* NEW_ERR */ +#ifndef NEW_ERR +#ifdef H5_HAVE_THREADSAFE +/* + * The per-thread error stack. pthread_once() initializes a special + * key that will be used by all threads to create a stack specific to + * each thread individually. The association of stacks to threads will + * be handled by the pthread library. + * + * In order for this macro to work, H5E_get_my_stack() must be preceeded + * by "H5E_t *estack =". + */ +H5E_t_new *H5E_get_stack_new(void); +#define H5E_get_my_stack_new() H5E_get_stack_new() +#else +/* + * The error stack. Eventually we'll have some sort of global table so each + * thread has it's own stack. The stacks will be created on demand when the + * thread first calls H5E_push(). */ +H5E_t_new H5E_stack_g_new[1]; +#define H5E_get_my_stack_new() (H5E_stack_g_new+0) +#endif + +#endif + #ifdef H5_HAVE_THREADSAFE /* * The per-thread error stack. pthread_once() initializes a special @@ -249,9 +274,7 @@ void *H5E_auto_data_g = NULL; /* Static function declarations */ static herr_t H5E_init_interface (void); #ifndef NEW_ERR -static hid_t H5E_register_class(const char *cls_name, const char *lib_name, - const char *version); -static hid_t H5E_unregister_class(H5E_cls_t *cls); +static int H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *key); #endif /* NEW_ERR */ static herr_t H5E_walk_cb (int n, H5E_error_t *err_desc, void *client_data); @@ -318,10 +341,15 @@ H5E_init_interface(void) FUNC_ENTER_NOINIT(H5E_init_interface); - /* Initialize the atom group for the dataset IDs */ - if(H5I_init_group(H5I_ERROR_CLASS, H5I_ERRORCLS_HASHSIZE, H5E_ERRCLS_RESERVED_ATOMS, - (H5I_free_t)H5E_unregister_class)<0) - HGOTO_ERROR (H5E_ERROR, H5E_CANTINIT, FAIL, "unable to initialize interface"); + /* Initialize the atom group for the error class IDs */ + H5I_init_group(H5I_ERROR_CLASS, H5I_ERRCLS_HASHSIZE, H5E_RESERVED_ATOMS, + (H5I_free_t)H5E_unregister_class); + /* Initialize the atom group for the major error IDs */ + H5I_init_group(H5I_ERROR_MSG, H5I_ERRMSG_HASHSIZE, H5E_RESERVED_ATOMS, + (H5I_free_t)H5E_close_msg); + /* Initialize the atom group for the error stacks */ + H5I_init_group(H5I_ERROR_STACK, H5I_ERRSTK_HASHSIZE, H5E_RESERVED_ATOMS, + (H5I_free_t)H5E_close_stack); /* From the old function; take out later */ H5E_auto_data_g = stderr; @@ -407,7 +435,7 @@ done: * *------------------------------------------------------------------------- */ -static hid_t +hid_t H5E_register_class(const char *cls_name, const char *lib_name, const char *version) { hid_t ret_value; /* Return value */ @@ -488,21 +516,383 @@ done: * *------------------------------------------------------------------------- */ -static hid_t +herr_t H5E_unregister_class(H5E_cls_t *cls) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5E_unregister_class, FAIL); + + H5I_search(H5I_ERROR_MSG, H5E_close_msg_cb, cls); + + if(cls) { + if(cls->cls_name) + H5MM_xfree(cls->cls_name); + if(cls->lib_name) + H5MM_xfree(cls->lib_name); + if(cls->lib_vers) + H5MM_xfree(cls->lib_vers); + H5MM_xfree(cls); + } + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5E_close_msg_cb + * + * Purpose: H5I_search callback function to close error messages in the + * error class. + * + * Programmer: Raymond Lu + * July 14, 2003 + * + * Return: Non-negative value on success/Negative on failure + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *key) +{ + herr_t ret_value = SUCCEED; /* Return value */ + H5E_msg_t *err_msg = (H5E_msg_t*)obj_ptr; + H5E_cls_t *cls = (H5E_cls_t*)key; + + FUNC_ENTER_NOAPI(H5_close_msg_cb, FAIL); + + assert(obj_ptr); + + if(err_msg->cls == cls) + H5E_close_msg(err_msg); + + done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Eclose_msg + * + * Purpose: Closes a major or minor error. + * + * Return: Non-negative value on success/Negative on failure + * + * Programmer: Raymond Lu + * Friday, July 11, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Eclose_msg(hid_t err_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + H5E_msg_t *err; + + FUNC_ENTER_API(H5Eclose_msg, FAIL); + H5TRACE1("e","i",err_id); + + /* Need to check for errors */ + err = H5I_object_verify(err_id, H5I_ERROR_MSG); + + /* Decrement the counter. It will be freed if the count reaches zero. */ + H5I_dec_ref(err_id); + +done: + FUNC_LEAVE_API(ret_value); +} + +/*------------------------------------------------------------------------- + * Function: H5E_close_msg + * + * Purpose: Private function to close an error messge. + * + * Return: Non-negative value on success/Negative on failure + * + * Programmer: Raymond Lu + * Friday, July 11, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5E_close_msg(H5E_msg_t *err) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5E_close_msg, FAIL); + + /* Doesn't free err->cls here */ + if(err) { + if(err->msg) + H5MM_xfree(err->msg); + H5MM_xfree(err); + } + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + +/*------------------------------------------------------------------------- + * Function: H5Ecreate_msg + * + * Purpose: Creates a major or minor error, returns an ID. + * + * Return: Non-negative value on success/Negative on failure + * + * Programmer: Raymond Lu + * Friday, July 11, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hid_t +H5Ecreate_msg(hid_t cls, H5E_type_t msg_type, const char *msg) +{ + hid_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5Ecreate_msg, FAIL); + + ret_value = H5E_create_msg(cls, msg_type, msg); + +done: + FUNC_LEAVE_API(ret_value); +} + +/*------------------------------------------------------------------------- + * Function: H5E_create_msg + * + * Purpose: Private function to create a major or minor error. + * + * Return: Non-negative value on success/Negative on failure + * + * Programmer: Raymond Lu + * Friday, July 11, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hid_t +H5E_create_msg(hid_t cls_id, H5E_type_t msg_type, const char *msg) +{ + hid_t ret_value; /* Return value */ + H5E_msg_t *msg_ptr; + + FUNC_ENTER_NOAPI(H5E_create_msg, FAIL); + + /* Check arguments */ + assert(msg); + + /* Need to check for failures from malloc & strdup */ + msg_ptr = H5MM_malloc(sizeof(H5E_msg_t)); + + msg_ptr->cls = H5I_object_verify(cls_id, H5I_ERROR_CLASS); + msg_ptr->type = msg_type; + msg_ptr->msg = HDstrdup(msg); + + /* Register the new error message to get an ID for it */ + /* Need to check for error */ + ret_value = H5I_register(H5I_ERROR_MSG, msg_ptr); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +#ifdef H5_HAVE_THREADSAFE +/*------------------------------------------------------------------------- + * Function: H5E_get_stack_new + * + * Purpose: Support function for H5E_get_my_stack() to initialize and + * acquire per-thread error stack. + * + * Return: Success: error stack (H5E_t *) + * + * Failure: NULL + * + * Programmer: Chee Wai LEE + * April 24, 2000 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5E_t_new * +H5E_get_stack_new(void) +{ + H5E_t_new *estack; + H5E_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5E_get_stack_new,NULL); + + estack = pthread_getspecific(H5TS_errstk_key_g); + if (!estack) { + /* no associated value with current thread - create one */ + estack = (H5E_t_new *)H5MM_malloc(sizeof(H5E_t_new)); + pthread_setspecific(H5TS_errstk_key_g, (void *)estack); + } + + /* Set return value */ + ret_value=estack; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} +#endif /* H5_HAVE_THREADSAFE */ + + +/*------------------------------------------------------------------------- + * Function: H5Eget_current_stack + * + * Purpose: Registers current error stack, returns object handle for it, + * clears it. + * + * Return: Non-negative value as stack ID on success/Negative on failure + * + * Programmer: Raymond Lu + * Friday, July 14, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hid_t +H5Eget_current_stack(void) +{ + hid_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5Eget_current_stack, FAIL); + H5TRACE0("i",""); + + /* Add HGOTO_ERROR later */ + ret_value=H5E_get_current_stack(); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5E_get_current_stack + * + * Purpose: Private function to register an error stack. + * + * Return: Non-negative value as class ID on success/Negative on failure + * + * Programmer: Raymond Lu + * Friday, July 11, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hid_t +H5E_get_current_stack(void) +{ + hid_t ret_value; /* Return value */ + H5E_t_new *estack = H5E_get_my_stack_new (); - H5MM_xfree(cls->cls_name); - H5MM_xfree(cls->lib_name); - H5MM_xfree(cls->lib_vers); - H5MM_xfree(cls); + FUNC_ENTER_NOAPI(H5E_get_current_stack, FAIL); + + /* Register the error stack to get an ID for it */ + /* Need to check for error */ + ret_value = H5I_register(H5I_ERROR_STACK, estack); done: FUNC_LEAVE_NOAPI(ret_value); } + + +/*------------------------------------------------------------------------- + * Function: H5Eclose_stack + * + * Purpose: Closes an error stack. + * + * Return: Non-negative value on success/Negative on failure + * + * Programmer: Raymond Lu + * Friday, July 14, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Eclose_stack(hid_t stack_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + H5E_t_new *err_stack; + + FUNC_ENTER_API(H5Eclose_stack, FAIL); + H5TRACE1("e","i",stack_id); + + /* Add HGOTO_ERROR later */ + if(H5E_DEFAULT == stack_id) + ; + + /* Need to check for errors */ + err_stack = H5I_object_verify(stack_id, H5I_ERROR_STACK); + + /* + * Decrement the counter on the dataset. It will be freed if the count + * reaches zero. + */ + /* Need to check for errors */ + H5I_dec_ref(stack_id); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5E_close_stack + * + * Purpose: Private function to close an error stack. + * + * Return: Non-negative value on success/Negative on failure + * + * Programmer: Raymond Lu + * Friday, July 14, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5E_close_stack(H5E_t_new *err_stack) +{ + herr_t ret_value = SUCCEED; /* Return value */ + H5E_error_t_new *error; + int i; + + FUNC_ENTER_NOAPI(H5E_close_stack, FAIL); + + if(err_stack) { + for(i=0; inused; i++) { + error = &(err_stack->slot[i]); + if(error->func_name) + H5MM_xfree(error->func_name); + if(error->file_name) + H5MM_xfree(error->file_name); + if(error->desc) + H5MM_xfree(error->desc); + } + H5MM_xfree(err_stack); + } + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + #endif /* NEW_ERR */ diff --git a/src/H5Eprivate.h b/src/H5Eprivate.h index 58a7acf..56ed9d5 100644 --- a/src/H5Eprivate.h +++ b/src/H5Eprivate.h @@ -27,7 +27,7 @@ #ifndef NEW_ERR -#define H5E_ERRCLS_RESERVED_ATOMS 0 +#define H5E_RESERVED_ATOMS 0 typedef struct H5E_cls_t { char *cls_name; @@ -35,15 +35,17 @@ typedef struct H5E_cls_t { char *lib_vers; } H5E_cls_t; -typedef struct H5E_maj_t { - char *mesg; - H5E_cls_t *cls; -} H5E_maj_t; +typedef struct H5E_msg_t { + char *msg; + H5E_type_t type; + H5E_cls_t *cls; +} H5E_msg_t; -typedef struct H5E_min_t { - char *mesg; - H5E_cls_t *cls; -} H5E_min_t; +/* An error stack */ +typedef struct H5E_t_new { + int nused; /*num slots currently used in stack */ + H5E_error_t_new slot[H5E_NSLOTS]; /*array of error records */ +} H5E_t_new; #ifdef TMP /* HDF5 error class */ @@ -277,6 +279,18 @@ H5_DLL herr_t H5E_clear (void); H5_DLL herr_t H5E_walk (H5E_direction_t dir, H5E_walk_t func, void *client_data); +#ifndef NEW_ERR +/* New error API */ +H5_DLL hid_t H5E_register_class(const char *cls_name, const char *lib_name, + const char *version); +H5_DLL herr_t H5E_unregister_class(H5E_cls_t *cls); +H5_DLL herr_t H5E_close_msg(H5E_msg_t *err); +H5_DLL hid_t H5E_create_msg(hid_t cls_id, H5E_type_t msg_type, const char *msg); +H5_DLL hid_t H5E_get_current_stack(void); +H5_DLL herr_t H5E_close_stack(H5E_t_new *err_stack); + +#endif /* NEW_ERR */ + #ifdef H5_HAVE_PARALLEL /* * MPI error handling macros. diff --git a/src/H5Epublic.h b/src/H5Epublic.h index 9a46f1f..792c637 100644 --- a/src/H5Epublic.h +++ b/src/H5Epublic.h @@ -26,12 +26,26 @@ #ifndef NEW_ERR -typedef enum H5E_msg_t { - H5E_MSG_ERROR =-1, - H5E_MSG_MAJOR, - H5E_MSG_MINOR, - H5E_MSG_LIMIT -} H5E_msg_t; +#define H5E_DEFAULT 0 + +/* Take out _new later */ +typedef enum H5E_type_t { + H5E_ERROR_new =-1, + H5E_MAJOR_new, + H5E_MINOR_new, + H5E_LIMIT_new +} H5E_type_t; + +/* Information about an error; element of error stack */ +typedef struct H5E_error_t_new { + hid_t cls_id; /*class ID */ + hid_t maj_id; /*major error ID */ + hid_t min_id; /*minor error number */ + const char *func_name; /*function in which error occurred */ + const char *file_name; /*file in which error occurred */ + unsigned line; /*line in file where error occurs */ + const char *desc; /*optional supplied description */ +} H5E_error_t_new; /* When this header is included from H5Eprivate.h, don't make calls to H5open() */ #undef H5OPEN @@ -417,8 +431,6 @@ extern "C" { typedef herr_t (*H5E_walk_t)(int n, H5E_error_t *err_desc, void *client_data); typedef herr_t (*H5E_auto_t)(void *client_data); -H5_DLL hid_t H5Eregister_class(const char *cls_name, const char *lib_name, const char *version); -H5_DLL herr_t H5Eunregister_class(hid_t class_id); H5_DLL herr_t H5Eset_auto (H5E_auto_t func, void *client_data); H5_DLL herr_t H5Eget_auto (H5E_auto_t *func, void **client_data); H5_DLL herr_t H5Eclear (void); @@ -430,6 +442,14 @@ H5_DLL const char *H5Eget_minor (H5E_minor_t minor_number); H5_DLL herr_t H5Epush(const char *file, const char *func, unsigned line, H5E_major_t maj, H5E_minor_t min, const char *str); +/* New error API */ +H5_DLL hid_t H5Eregister_class(const char *cls_name, const char *lib_name, const char *version); +H5_DLL herr_t H5Eunregister_class(hid_t class_id); +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 H5Eget_current_stack(void); +H5_DLL herr_t H5Eclose_stack(hid_t stack_id); + #ifdef __cplusplus } #endif diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h index 1174e5b..3b67ba1 100644 --- a/src/H5Iprivate.h +++ b/src/H5Iprivate.h @@ -42,9 +42,9 @@ #define H5I_VFL_HASHSIZE 64 #define H5I_GENPROPCLS_HASHSIZE 64 #define H5I_GENPROPOBJ_HASHSIZE 128 -#define H5I_ERRORCLS_HASHSIZE 64 -#define H5I_MAJORERR_HASHSIZE 64 -#define H5I_MINORERR_HASHSIZE 64 +#define H5I_ERRCLS_HASHSIZE 64 +#define H5I_ERRMSG_HASHSIZE 64 +#define H5I_ERRSTK_HASHSIZE 64 /* * Function for freeing objects. This function will be called with an object diff --git a/src/H5Ipublic.h b/src/H5Ipublic.h index acf64af..3087ce9 100644 --- a/src/H5Ipublic.h +++ b/src/H5Ipublic.h @@ -43,8 +43,8 @@ typedef enum { H5I_GENPROP_CLS, /*group ID for generic property list classes */ H5I_GENPROP_LST, /*group ID for generic property lists */ H5I_ERROR_CLASS, /*group ID for error classes */ - H5I_ERROR_MAJOR, /*group ID for major errors */ - H5I_ERROR_MINOR, /*group ID for minor errors */ + H5I_ERROR_MSG, /*group ID for error messages */ + H5I_ERROR_STACK, /*group ID for error stacks */ H5I_NGROUPS /*number of valid groups, MUST BE LAST! */ } H5I_type_t; diff --git a/test/errors.c b/test/errors.c index bd832d6..f1e967c 100644 --- a/test/errors.c +++ b/test/errors.c @@ -34,6 +34,7 @@ int ipoints2[DIM0][DIM1], icheck2[DIM0][DIM1]; hid_t ERR_CLS; hid_t ERR_MAJ_TEST; hid_t ERR_MIN_SUBROUTINE; +hid_t ERR_STACK; #define DSET_NAME "a_dataset" @@ -179,18 +180,91 @@ init_error(void) if((ERR_CLS = H5Eregister_class(ERR_CLS_NAME, PROG_NAME, PROG_VERS))<0) goto error; - /* - if((ERR_MAJ_TEST = H5Ecreate_mesg(ERR_CLS, H5E_MAJOR, "Error in test"))<0) + if((ERR_MAJ_TEST = H5Ecreate_msg(ERR_CLS, H5E_MAJOR_new, "Error in test"))<0) goto error; - if((ERR_MIN_SUBROUTINE = H5Ecreate_mesg(ERR_CLS, H5E_MINOR, "Error in subroutine"))<0) + if((ERR_MIN_SUBROUTINE = H5Ecreate_msg(ERR_CLS, H5E_MINOR_new, "Error in subroutine"))<0) + goto error; + + PASSED(); + return 0; + + error: + return -1; +} + + +/*------------------------------------------------------------------------- + * Function: error_stack + * + * Purpose: Manipulates current error stack. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Raymond Lu + * July 14, 2003 + * + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +error_stack(void) +{ + if((ERR_STACK = H5Eget_current_stack())<0) + goto error; + + if(H5Eclose_stack(ERR_STACK)<0) + goto error; + + PASSED(); + return 0; + + error: + return -1; +} + + + +/*------------------------------------------------------------------------- + * Function: close_error + * + * Purpose: Closes error information. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Raymond Lu + * July 10, 2003 + * + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +close_error(void) +{ + /* + if(H5Eclose_msg(ERR_MAJ_TEST)<0) + goto error; + if(H5Eclose_msg(ERR_MIN_SUBROUTINE)<0) goto error; */ + + if(H5Eunregister_class(ERR_CLS)<0) + goto error; + PASSED(); return 0; error: return -1; } + #endif /* NEW_ERR */ @@ -225,6 +299,11 @@ main(void) h5_fixname(FILENAME[0], fapl, filename, sizeof filename); if ((file=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) goto error; + +#ifndef NEW_ERR + if(error_stack()<0) + goto error; +#endif /* NEW_ERR */ /*if(test_error(file)<0) {*/ #ifndef NEW_ERR @@ -234,9 +313,14 @@ main(void) }*/ if (H5Fclose(file)<0) goto error; - printf("All error API test based on native datatype test passed.\n"); h5_cleanup(FILENAME, fapl); +#ifndef NEW_ERR + if(close_error()<0) + goto error; +#endif /* NEW_ERR */ + printf("All error API test based on native datatype test passed.\n"); + return 0; error: -- cgit v0.12