diff --git a/src/H5E.c b/src/H5E.c index acc407185b..222f0e9e05 100644 --- a/src/H5E.c +++ b/src/H5E.c @@ -222,16 +222,16 @@ hid_t H5E_ERR_CLS_g = FAIL; */ H5E_t_new *H5E_get_stack_new(void); #define H5E_get_my_stack_new() H5E_get_stack_new() -#else +#else /* H5_HAVE_THREADSAFE */ /* * 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 +#define H5E_get_my_stack_new() (H5E_stack_g_new+0) +#endif /* H5_HAVE_THREADSAFE */ -#endif +#endif /* NEW_ERR */ #ifdef H5_HAVE_THREADSAFE /* @@ -276,7 +276,6 @@ static herr_t H5E_init_interface (void); #ifndef NEW_ERR static int H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *key); static herr_t H5E_walk_cb_new(int n, H5E_error_t_new *err_desc, void *client_data); -static htri_t H5E_same_class(H5E_cls_t *cls); #endif /* NEW_ERR */ static herr_t H5E_walk_cb (int n, H5E_error_t *err_desc, void *client_data); @@ -353,6 +352,9 @@ H5E_init_interface(void) H5I_init_group(H5I_ERROR_STACK, H5I_ERRSTK_HASHSIZE, H5E_RESERVED_ATOMS, (H5I_free_t)H5E_close_stack); + H5E_stack_g_new[0].func = &(H5Eprint_new); + H5E_stack_g_new[0].auto_data = stderr; + /* From the old function; take out later */ H5E_auto_data_g = stderr; @@ -885,7 +887,9 @@ H5E_get_stack_new(void) 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)); + estack = (H5E_t_new *)H5MM_calloc(sizeof(H5E_t_new)); + estack->func = &(H5Eprint_new); + estack->auto_data = stderr; pthread_setspecific(H5TS_errstk_key_g, (void *)estack); } @@ -1199,7 +1203,7 @@ H5Eget_num(hid_t error_stack_id) estack = H5E_get_my_stack_new(); else estack = H5I_object_verify(error_stack_id, H5I_ERROR_STACK); - + /* Add HGOTO_ERROR later */ ret_value=H5E_get_num(estack); @@ -1536,28 +1540,17 @@ H5E_clear_new(H5E_t_new *estack) FUNC_ENTER_NOAPI(H5E_clear_new, FAIL); /* Empty the error stack */ -fprintf(stderr, "%s: %d\n", FUNC, __LINE__); if (estack) { -fprintf(stderr, "%s: %d nused=%d\n", FUNC, __LINE__, estack->nused); for(i=0; inused; i++) { -fprintf(stderr, "%s: %d\n", FUNC, __LINE__); error = &(estack->slot[i]); -fprintf(stderr, "%s: %d error=%p, func_name=%p, func_name=%s\n", FUNC, __LINE__, error, - error->func_name, error->func_name); if(error->func_name) H5MM_xfree((void*)error->func_name); -fprintf(stderr, "%s: %d\n file_name=%p", FUNC, __LINE__, error->file_name); if(error->file_name) H5MM_xfree((void*)error->file_name); -fprintf(stderr, "%s: %d desc=%p\n", FUNC, __LINE__, error->desc); if(error->desc) H5MM_xfree((void*)error->desc); -fprintf(stderr, "%s: %d\n", FUNC, __LINE__); } -fprintf(stderr, "%s: %d\n", FUNC, __LINE__); HDmemset(estack->slot, 0, sizeof(H5E_error_t_new)*estack->nused); -fprintf(stderr, "%s: %d\n", FUNC, __LINE__); - estack->nused = 0; } done: @@ -1643,17 +1636,40 @@ done: herr_t H5E_print_new(H5E_t_new *estack, FILE *stream) { - /*herr_t ret_value = FAIL;*/ herr_t ret_value = SUCCEED; - + H5E_print_t *eprint = NULL; + H5E_cls_t origin_cls={"Unknown class", "Unknown library", "Unknown library version"}; + /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Eprint, FAIL); /*NO TRACE*/ - - if (!stream) stream = stderr; - ret_value = H5E_walk_new (estack, H5E_WALK_DOWNWARD, H5E_walk_cb_new, (void*)stream); + eprint = H5MM_calloc(sizeof(H5E_print_t)); + if (!stream) + eprint->stream = stderr; + else + eprint->stream = stream; + + eprint->cls = H5MM_calloc(sizeof(H5E_cls_t)); + + eprint->cls->cls_name = HDstrdup(origin_cls.cls_name); + eprint->cls->lib_name = HDstrdup(origin_cls.lib_name); + eprint->cls->lib_vers = HDstrdup(origin_cls.lib_vers); + + ret_value = H5E_walk_new (estack, H5E_WALK_DOWNWARD, H5E_walk_cb_new, (void*)eprint); + + /* Free memory. */ + if(eprint && eprint->cls) { + if(eprint->cls->cls_name) H5MM_free(eprint->cls->cls_name); + if(eprint->cls->lib_name) H5MM_free(eprint->cls->lib_name); + if(eprint->cls->lib_vers) H5MM_free(eprint->cls->lib_vers); + } + if(eprint) { + if(eprint->cls) H5MM_free(eprint->cls); + H5MM_free(eprint); + } + done: FUNC_LEAVE_API(ret_value); } @@ -1800,7 +1816,8 @@ done: static herr_t H5E_walk_cb_new(int n, H5E_error_t_new *err_desc, void *client_data) { - FILE *stream = (FILE *)client_data; + H5E_print_t *eprint = (H5E_print_t *)client_data; + FILE *stream = NULL; H5E_cls_t *cls_ptr = NULL; H5E_msg_t *maj_ptr = NULL; H5E_msg_t *min_ptr = NULL; @@ -1814,8 +1831,9 @@ H5E_walk_cb_new(int n, H5E_error_t_new *err_desc, void *client_data) /* Check arguments */ assert (err_desc); - if (!client_data) client_data = stderr; - + if (!client_data) stream = stderr; + else stream = eprint->stream; + /* Get descriptions for the major and minor error numbers */ /* Need to check for errors */ maj_ptr = H5I_object_verify(err_desc->maj_id, H5I_ERROR_MSG); @@ -1831,7 +1849,16 @@ H5E_walk_cb_new(int n, H5E_error_t_new *err_desc, void *client_data) cls_str = maj_ptr->cls->cls_name; /* Print error message */ - if(!H5E_same_class(cls_ptr)) { + if(HDstrcmp(cls_ptr->lib_name, eprint->cls->lib_name)) { + /* store the new class information, free the old one. */ + if(eprint->cls->cls_name) H5MM_free(eprint->cls->cls_name); + if(eprint->cls->lib_name) H5MM_free(eprint->cls->lib_name); + if(eprint->cls->lib_vers) H5MM_free(eprint->cls->lib_vers); + + if(cls_ptr->cls_name) eprint->cls->cls_name = HDstrdup(cls_ptr->cls_name); + if(cls_ptr->lib_name) eprint->cls->lib_name = HDstrdup(cls_ptr->lib_name); + if(cls_ptr->lib_vers) eprint->cls->lib_vers = HDstrdup(cls_ptr->lib_vers); + fprintf (stream, "%s-DIAG: Error detected in %s ", cls_ptr->lib_name, cls_ptr->lib_vers); /* try show the process or thread id in multiple processes cases*/ @@ -1866,39 +1893,168 @@ H5E_walk_cb_new(int n, H5E_error_t_new *err_desc, void *client_data) /*------------------------------------------------------------------------- - * Function: H5E_same_class + * Function: H5Eget_auto_new * - * Purpose: Compare the error class name with the one in record. + * Purpose: Returns the current settings for the automatic error stack + * traversal function and its data for specific error stack. + * Either (or both) arguments may be null in which case the + * value is not returned. * - * Return: Non-zero value when true/zero when false + * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke - * Friday, December 12, 1997 + * Saturday, February 28, 1998 + * + * Modifications: + * Raymond Lu + * July 18, 2003 + * Added error stack in the parameters. It returns the + * traversal function and data for that error stack. + * + *------------------------------------------------------------------------- + */ +herr_t +H5Eget_auto_new(hid_t estack_id, H5E_auto_t *func, void **client_data) +{ + herr_t ret_value=SUCCEED; /* Return value */ + H5E_t_new *estack_ptr = NULL; + + FUNC_ENTER_API(H5Eget_auto_new, FAIL); + H5TRACE3("e","i*x*x",estack_id,func,client_data); + + if(estack_id == H5E_DEFAULT) + estack_ptr = H5E_get_my_stack_new(); + else + estack_ptr = H5I_object_verify(estack_id, H5I_ERROR_STACK); + + ret_value = H5E_get_auto_new(estack_ptr, func, client_data); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5E_get_auto_new + * + * Purpose: Private function to return the current settings for the + * automatic error stack traversal function and its data + * for specific error stack. Either (or both) arguments may + * be null in which case the value is not returned. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * July 18, 2003 * * Modifications: * *------------------------------------------------------------------------- */ -static htri_t -H5E_same_class(H5E_cls_t *cls) +herr_t +H5E_get_auto_new(H5E_t_new *estack, H5E_auto_t *func, void **client_data) { - htri_t ret_value = FALSE; - static H5E_cls_t origin_cls={"Unknown class", "Unknown library", "Unknown library version"}; - - FUNC_ENTER_NOINIT(H5E_same_class); - /*NO TRACE*/ + herr_t ret_value=SUCCEED; /* Return value */ - /* Check arguments */ - assert (cls); + FUNC_ENTER_NOAPI(H5E_get_auto_new, FAIL); - if(strcmp(cls->lib_name, origin_cls.lib_name)) { - origin_cls.cls_name = HDstrdup(cls->cls_name); - origin_cls.lib_name = HDstrdup(cls->lib_name); - origin_cls.lib_vers = HDstrdup(cls->lib_vers); - ret_value = FALSE; - } else - ret_value = TRUE; + assert (estack); + + if(func) *func = estack->func; + if(client_data) *client_data = estack->auto_data; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Eset_auto_new + * + * Purpose: Turns on or off automatic printing of errors for certain + * error stack. When turned on (non-null FUNC pointer) any + * API function which returns an error indication will first + * call FUNC passing it CLIENT_DATA as an argument. + * + * The default values before this function is called are + * H5Eprint() with client data being the standard error stream, + * stderr. + * + * Automatic stack traversal is always in the H5E_WALK_DOWNWARD + * direction. + * + * See Also: H5Ewalk() + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Friday, February 27, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Eset_auto_new(hid_t estack_id, H5E_auto_t func, void *client_data) +{ + herr_t ret_value=SUCCEED; /* Return value */ + H5E_t_new *estack_ptr = NULL; + FUNC_ENTER_API(H5Eset_auto_new, FAIL); + H5TRACE3("e","ixx",estack_id,func,client_data); + + if(estack_id == H5E_DEFAULT) + estack_ptr = H5E_get_my_stack_new(); + else + estack_ptr = H5I_object_verify(estack_id, H5I_ERROR_STACK); + + ret_value = H5E_set_auto_new(estack_ptr, func, client_data); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5E_set_auto_new + * + * Purpose: Private function to turn on or off automatic printing of + * errors for certain error stack. When turned on (non-null + * FUNC pointer) any API function which returns an error + * indication will first call FUNC passing it CLIENT_DATA + * as an argument. + * + * The default values before this function is called are + * H5Eprint() with client data being the standard error stream, + * stderr. + * + * Automatic stack traversal is always in the H5E_WALK_DOWNWARD + * direction. + * + * See Also: H5Ewalk() + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Friday, February 27, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5E_set_auto_new(H5E_t_new *estack, H5E_auto_t func, void *client_data) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5E_set_auto_new, FAIL); + + assert(estack); + + estack->func = &func; + estack->auto_data = client_data; + +done: FUNC_LEAVE_NOAPI(ret_value); } diff --git a/src/H5Eprivate.h b/src/H5Eprivate.h index a08a727152..d4ce7e576f 100644 --- a/src/H5Eprivate.h +++ b/src/H5Eprivate.h @@ -41,10 +41,22 @@ typedef struct H5E_msg_t { H5E_cls_t *cls; } H5E_msg_t; +/* Printing information */ +typedef struct H5E_print_t { + FILE *stream; + H5E_cls_t *cls; +} H5E_print_t; + +/*H5_DLLVAR herr_t (*H5E_auto_g_new)(hid_t estack, void *client_data); +H5_DLLVAR void *H5E_auto_data_g_new; +*/ + /* 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_auto_t func; + void *auto_data; } H5E_t_new; #ifdef TMP @@ -303,6 +315,8 @@ H5_DLL herr_t H5E_clear_new(H5E_t_new *estack); H5_DLL herr_t H5E_print_new(H5E_t_new *estack, FILE *stream); H5_DLL herr_t H5E_walk_new (H5E_t_new *estack, H5E_direction_t direction, H5E_walk_t_new func, void *client_data); +H5_DLL herr_t H5E_get_auto_new(H5E_t_new *estack, H5E_auto_t *func, void **client_data); +H5_DLL herr_t H5E_set_auto_new(H5E_t_new *estack, H5E_auto_t func, void *client_data); #endif /* NEW_ERR */ diff --git a/src/H5Epublic.h b/src/H5Epublic.h index e579daed4c..28ecb77575 100644 --- a/src/H5Epublic.h +++ b/src/H5Epublic.h @@ -429,7 +429,7 @@ extern "C" { /* Error stack traversal callback function */ 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); +typedef herr_t (*H5E_auto_t)(hid_t estack, void *client_data); 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); @@ -461,6 +461,8 @@ H5_DLL herr_t H5Eprint_new(hid_t err_stack, FILE *stream); typedef herr_t (*H5E_walk_t_new)(int n, H5E_error_t_new *err_desc, void *client_data); H5_DLL herr_t H5Ewalk_new(hid_t err_stack, H5E_direction_t direction, H5E_walk_t_new func, void *client_data); +H5_DLL herr_t H5Eget_auto_new(hid_t estack_id, H5E_auto_t *func, void **client_data); +H5_DLL herr_t H5Eset_auto_new(hid_t estack_id, H5E_auto_t func, void *client_data); #ifdef __cplusplus }