diff options
-rw-r--r-- | src/H5E.c | 587 | ||||
-rw-r--r-- | src/H5Eprivate.h | 11 | ||||
-rw-r--r-- | src/H5Epublic.h | 9 | ||||
-rw-r--r-- | test/errors.c | 155 |
4 files changed, 713 insertions, 49 deletions
@@ -275,6 +275,8 @@ void *H5E_auto_data_g = NULL; 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); @@ -527,12 +529,12 @@ H5E_unregister_class(H5E_cls_t *cls) if(cls) { if(cls->cls_name) - H5MM_xfree(cls->cls_name); + H5MM_xfree((void*)cls->cls_name); if(cls->lib_name) - H5MM_xfree(cls->lib_name); + H5MM_xfree((void*)cls->lib_name); if(cls->lib_vers) - H5MM_xfree(cls->lib_vers); - H5MM_xfree(cls); + H5MM_xfree((void*)cls->lib_vers); + H5MM_xfree((void*)cls); } done: @@ -541,7 +543,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5Eget_class + * Function: H5Eget_class_name * * Purpose: Retrieves error class name. * @@ -556,18 +558,18 @@ done: *------------------------------------------------------------------------- */ ssize_t -H5Eget_class(hid_t class_id, char *name, size_t size) +H5Eget_class_name(hid_t class_id, char *name, size_t size) { ssize_t ret_value; /* Return value */ H5E_cls_t *cls; - FUNC_ENTER_API(H5Eget_class, FAIL); + FUNC_ENTER_API(H5Eget_class_name, FAIL); H5TRACE3("Zs","isz",class_id,name,size); /* Need to check for errors */ cls = H5I_object_verify(class_id, H5I_ERROR_CLASS); - ret_value = H5E_get_class(cls, name, size); + ret_value = H5E_get_class_name(cls, name, size); done: FUNC_LEAVE_API(ret_value); @@ -575,7 +577,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5E_get_class + * Function: H5E_get_class_name * * Purpose: Private function to retrieve error class name. * @@ -590,12 +592,12 @@ done: *------------------------------------------------------------------------- */ ssize_t -H5E_get_class(H5E_cls_t *cls, char *name, size_t size) +H5E_get_class_name(H5E_cls_t *cls, char *name, size_t size) { ssize_t ret_value; /* Return value */ ssize_t len; - FUNC_ENTER_NOAPI(H5E_get_class, FAIL); + FUNC_ENTER_NOAPI(H5E_get_class_name, FAIL); len = HDstrlen(cls->cls_name); @@ -704,8 +706,8 @@ H5E_close_msg(H5E_msg_t *err) /* Doesn't free err->cls here */ if(err) { if(err->msg) - H5MM_xfree(err->msg); - H5MM_xfree(err); + H5MM_xfree((void*)err->msg); + H5MM_xfree((void*)err); } done: @@ -972,11 +974,11 @@ H5E_get_current_stack(void) for(i=0; i<current_stack->nused; i++) { current_error = &(current_stack->slot[i]); if(current_error->func_name) - H5MM_xfree(current_error->func_name); + H5MM_xfree((void*)current_error->func_name); if(current_error->file_name) - H5MM_xfree(current_error->file_name); + H5MM_xfree((void*)current_error->file_name); if(current_error->desc) - H5MM_xfree(current_error->desc); + H5MM_xfree((void*)current_error->desc); } HDmemset(current_stack->slot, 0, sizeof(H5E_error_t_new)*current_stack->nused); current_stack->nused = 0; @@ -1055,11 +1057,11 @@ H5E_set_current_stack(H5E_t_new *estack) for(i=0; i<current_stack->nused; i++) { current_error = &(current_stack->slot[i]); if(current_error->func_name) - H5MM_xfree(current_error->func_name); + H5MM_xfree((void*)current_error->func_name); if(current_error->file_name) - H5MM_xfree(current_error->file_name); + H5MM_xfree((void*)current_error->file_name); if(current_error->desc) - H5MM_xfree(current_error->desc); + H5MM_xfree((void*)current_error->desc); } HDmemset(current_stack->slot, 0, sizeof(H5E_error_t_new)*current_stack->nused); current_stack->nused = 0; @@ -1155,13 +1157,13 @@ H5E_close_stack(H5E_t_new *err_stack) error = &(err_stack->slot[i]); if(error->func_name) - H5MM_xfree(error->func_name); + H5MM_xfree((void*)error->func_name); if(error->file_name) - H5MM_xfree(error->file_name); + H5MM_xfree((void*)error->file_name); if(error->desc) - H5MM_xfree(error->desc); + H5MM_xfree((void*)error->desc); } - H5MM_xfree(err_stack); + H5MM_xfree((void*)err_stack); } done: @@ -1235,6 +1237,109 @@ done: /*------------------------------------------------------------------------- + * Function: H5Epop + * + * Purpose: Deletes some error messages from the top of error stack. + * + * Return: Non-negative value on success/Negative on failure + * + * Programmer: Raymond Lu + * Friday, July 16, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Epop(hid_t err_stack, size_t count) +{ + herr_t ret_value = SUCCEED; /* Return value */ + H5E_t_new *estack; + + FUNC_ENTER_API(H5Epop, FAIL); + H5TRACE2("e","iz",err_stack,count); + + /* Need to check for errors */ + if(err_stack == H5E_DEFAULT) + estack = H5E_get_my_stack_new(); + else + estack = H5I_object_verify(err_stack, H5I_ERROR_STACK); + + if(count > estack->nused) + count = estack->nused; + + /* Add HGOTO_ERROR later */ + ret_value=H5E_pop(estack, count); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5E_pop + * + * Purpose: Private function to delete some error messages from the top + * of error stack. + * + * Return: Non-negative value on success/Negative on failure + * + * Programmer: Raymond Lu + * Friday, July 16, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5E_pop(H5E_t_new *err_stack, size_t count) +{ + herr_t ret_value = SUCCEED; /* Return value */ + H5E_error_t_new *old_head, *new_head, *delete_head; + size_t delete_count; + int i; + + FUNC_ENTER_NOAPI(H5E_pop, FAIL); + + assert(err_stack); + + /* Do an in-place move. Shift the remaining errors to the top of stack. */ + if(count != err_stack->nused) { + old_head = &(err_stack->slot[0]); + new_head = &(err_stack->slot[count]); + + /* Free memory for the errors to be deleted */ + for(i=0; i<count; i++) { + H5E_error_t_new *error = &(err_stack->slot[i]); + if(error->func_name) + H5MM_xfree((void*)error->func_name); + if(error->file_name) + H5MM_xfree((void*)error->file_name); + if(error->desc) + H5MM_xfree((void*)error->desc); + } + + /* Move the rest errors to the top of stack. Watch out: func_name, file_name, desc in new slot + * each points to the same location as the old slot. Do not free them when deleting the old + * slot. */ + HDmemmove(old_head, new_head, (err_stack->nused-count)*sizeof(H5E_error_t_new)); + + /* Point to the beginning of errors to be removed, delete the old moved slots. */ + delete_head = &(err_stack->slot[err_stack->nused-count]); + delete_count = count; + HDmemset(delete_head, 0, delete_count*sizeof(H5E_error_t_new)); + + err_stack->nused = err_stack->nused - count; + } else { + H5E_clear_new(err_stack); + } + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- * Function: H5Epush_new * * Purpose: Pushes a new error record onto error stack for the current @@ -1271,7 +1376,7 @@ H5Epush_new(hid_t err_stack, const char *file, const char *func, unsigned line, H5E_msg_t *maj_ptr, *min_ptr; va_list ap; hid_t cls_id; - char tmp[128]; + char tmp[128]; /* What's the maximal length? */ FUNC_ENTER_API(H5Epush_new, FAIL); H5TRACE7("e","issIuiis",err_stack,file,func,line,maj_id,min_id,fmt); @@ -1358,16 +1463,444 @@ H5E_push_new(H5E_t_new *estack, const char *file, const char *func, unsigned lin estack->slot[estack->nused].cls_id = cls_id; estack->slot[estack->nused].maj_id = maj_id; estack->slot[estack->nused].min_id = min_id; - estack->slot[estack->nused].func_name = func; - estack->slot[estack->nused].file_name = file; + estack->slot[estack->nused].func_name = HDstrdup(func); + estack->slot[estack->nused].file_name = HDstrdup(file); estack->slot[estack->nused].line = line; - estack->slot[estack->nused].desc = desc; + estack->slot[estack->nused].desc = HDstrdup(desc); estack->nused++; } FUNC_LEAVE_NOAPI(SUCCEED); } + +/*------------------------------------------------------------------------- + * Function: H5Eclear_new + * + * Purpose: Clears the error stack for the specified error stack. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * Wednesday, July 16, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Eclear_new(hid_t err_stack) +{ + herr_t ret_value=SUCCEED; /* Return value */ + H5E_t_new *estack_ptr; + + FUNC_ENTER_API(H5Eclear_new, FAIL); + H5TRACE1("e","i",err_stack); + /* FUNC_ENTER() does all the work */ + + /* Need to check for errors */ + if(err_stack == H5E_DEFAULT) + estack_ptr = H5E_get_my_stack_new(); + else + estack_ptr = H5I_object_verify(err_stack, H5I_ERROR_STACK); + + ret_value = H5E_clear_new(estack_ptr); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5E_clear_new + * + * Purpose: Private function to clear the error stack for the + * specified error stack. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * Wednesday, July 16, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5E_clear_new(H5E_t_new *estack) +{ + herr_t ret_value=SUCCEED; /* Return value */ + H5E_error_t_new *error; + int i; + + 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; i<estack->nused; 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: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5E_print_new + * + * Purpose: Prints the error stack in some default way. This is just a + * convenience function for H5Ewalk() with a function that + * prints error messages. Users are encouraged to write there + * own more specific error handlers. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Friday, February 27, 1998 + * + * Modifications: + * Albert Cheng, 2000/12/02 + * Show MPI process rank id if applicable. + * Albert Cheng, 2001/07/14 + * Show HDF5 library version information string too. + * + * Raymond Lu, 2003/7/16 + * Print for specified error stack. A line will appear before the error + * messages of each error class. It states the information of library + * name, version number and thread ID. + * + *------------------------------------------------------------------------- + */ +herr_t +H5Eprint_new(hid_t err_stack, FILE *stream) +{ + herr_t ret_value=SUCCEED; /* Return value */ + H5E_t_new *estack_ptr; + + /* Don't clear the error stack! :-) */ + FUNC_ENTER_API_NOCLEAR(H5Eprint_new, FAIL); + /*NO TRACE*/ + + /* Need to check for errors */ + if(err_stack == H5E_DEFAULT) + estack_ptr = H5E_get_my_stack_new(); + else + estack_ptr = H5I_object_verify(err_stack, H5I_ERROR_STACK); + + ret_value = H5E_print_new(estack_ptr, stream); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5E_print_new + * + * Purpose: Private function to print the error stack in some default + * way. This is just a convenience function for H5Ewalk() + * with a function that prints error messages. Users are + * encouraged to write there own more specific error handlers. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Friday, February 27, 1998 + * + * Modifications: + * Albert Cheng, 2000/12/02 + * Show MPI process rank id if applicable. + * Albert Cheng, 2001/07/14 + * Show HDF5 library version information string too. + * + * Raymond Lu, 2003/7/16 + * Print for specified error stack. A line will appear before the error + * messages of each error class. It states the information of library + * name, version number and thread ID. + * + *------------------------------------------------------------------------- + */ +herr_t +H5E_print_new(H5E_t_new *estack, FILE *stream) +{ + /*herr_t ret_value = FAIL;*/ + herr_t ret_value = SUCCEED; + + /* 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); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Ewalk_new + * + * Purpose: Walks the error stack for the current thread and calls some + * function for each error along the way. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Friday, February 27, 1998 + * + * Modifications: + * + * Raymond Lu + * Wednesday, July 16, 2003 + * Let it walk through specified error stack. + * + *------------------------------------------------------------------------- + */ +herr_t +H5Ewalk_new(hid_t err_stack, H5E_direction_t direction, H5E_walk_t_new func, void *client_data) +{ + H5E_t_new *estack_ptr; + herr_t ret_value; + + /* Don't clear the error stack! :-) */ + FUNC_ENTER_API_NOCLEAR(H5Ewalk_new, FAIL); + H5TRACE4("e","iEdxx",err_stack,direction,func,client_data); + + /* Need to check for errors */ + if(err_stack == H5E_DEFAULT) + estack_ptr = H5E_get_my_stack_new(); + else + estack_ptr = H5I_object_verify(err_stack, H5I_ERROR_STACK); + + ret_value = H5E_walk_new (estack_ptr, direction, func, client_data); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5E_walk_new + * + * Purpose: Private function for H5Ewalk_new. + * Walks the error stack, calling the specified function for + * each error on the stack. The DIRECTION argument determines + * whether the stack is walked from the inside out or the + * outside in. The value H5E_WALK_UPWARD means begin with the + * most specific error and end at the API; H5E_WALK_DOWNWARD + * means to start at the API and end at the inner-most function + * where the error was first detected. + * + * The function pointed to by FUNC will be called for each error + * in the error stack. It's arguments will include an index + * number (beginning at zero regardless of stack traversal + * direction), an error stack entry, and the CLIENT_DATA pointer + * passed to H5E_print. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Friday, December 12, 1997 + * + * Modifications: + * + * Raymond Lu + * Wednesday, July 16, 2003 + * Let it walk through specified error stack. + * + *------------------------------------------------------------------------- + */ +herr_t +H5E_walk_new (H5E_t_new *estack, H5E_direction_t direction, H5E_walk_t_new func, void *client_data) +{ + int i; + herr_t status; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5E_walk_new, FAIL); + + /* check args, but rather than failing use some default value */ + if (direction!=H5E_WALK_UPWARD && direction!=H5E_WALK_DOWNWARD) { + direction = H5E_WALK_UPWARD; + } + + /* walk the stack */ + assert (estack); + + if (func && H5E_WALK_UPWARD==direction) { + for (i=0, status=SUCCEED; i<estack->nused && status>=0; i++) { + status = (func)(i, estack->slot+i, client_data); + } + } else if (func && H5E_WALK_DOWNWARD==direction) { + for (i=estack->nused-1, status=SUCCEED; i>=0 && status>=0; --i) { + status = (func)(estack->nused-(i+1), estack->slot+i, client_data); + } + } + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5E_walk_cb_new + * + * Purpose: This is a default error stack traversal callback function + * that prints error messages to the specified output stream. + * It is not meant to be called directly but rather as an + * argument to the H5Ewalk() function. This function is called + * also by H5Eprint(). Application writers are encouraged to + * use this function as a model for their own error stack + * walking functions. + * + * N is a counter for how many times this function has been + * called for this particular traversal of the stack. It always + * begins at zero for the first error on the stack (either the + * top or bottom error, or even both, depending on the traversal + * direction and the size of the stack). + * + * ERR_DESC is an error description. It contains all the + * information about a particular error. + * + * CLIENT_DATA is the same pointer that was passed as the + * CLIENT_DATA argument of H5Ewalk(). It is expected to be a + * file pointer (or stderr if null). + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Friday, December 12, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5E_walk_cb_new(int n, H5E_error_t_new *err_desc, void *client_data) +{ + FILE *stream = (FILE *)client_data; + H5E_cls_t *cls_ptr = NULL; + H5E_msg_t *maj_ptr = NULL; + H5E_msg_t *min_ptr = NULL; + const char *maj_str = NULL; + const char *min_str = NULL; + const char *cls_str = NULL; + const int indent = 2; + + FUNC_ENTER_NOINIT(H5E_walk_cb_new); + /*NO TRACE*/ + + /* Check arguments */ + assert (err_desc); + if (!client_data) client_data = stderr; + + /* 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); + min_ptr = H5I_object_verify(err_desc->min_id, H5I_ERROR_MSG); + maj_str = maj_ptr->msg; + min_str = min_ptr->msg; + + /* Get error class info */ + /* add error checking later */ + if(HDstrcmp(maj_ptr->cls->cls_name, min_ptr->cls->cls_name)) + ; + cls_ptr = maj_ptr->cls; + cls_str = maj_ptr->cls->cls_name; + + /* Print error message */ + if(!H5E_same_class(cls_ptr)) { + 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*/ +#ifdef H5_HAVE_PARALLEL + { int mpi_rank, mpi_initialized; + MPI_Initialized(&mpi_initialized); + if (mpi_initialized){ + MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); + fprintf (stream, "MPI-process %d.", mpi_rank); + }else + fprintf (stream, "thread 0."); + } +#elif defined(H5_HAVE_THREADSAFE) + fprintf (stream, "thread %d.", (int)pthread_self()); +#else + fprintf (stream, "thread 0."); +#endif + /* Don't know what this is for */ + /*if (estack && estack->nused>0) fprintf (stream, " Back trace follows.");*/ + HDfputc ('\n', stream); + } + + fprintf (stream, "%*s#%03d: %s line %u in %s(): %s\n", + indent, "", n, err_desc->file_name, err_desc->line, + err_desc->func_name, err_desc->desc); + fprintf (stream, "%*sclass: %s\n", indent*2, "", cls_str); + fprintf (stream, "%*smajor: %s\n", indent*2, "", maj_str); + fprintf (stream, "%*sminor: %s\n", indent*2, "", min_str); + + FUNC_LEAVE_NOAPI(SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5E_same_class + * + * Purpose: Compare the error class name with the one in record. + * + * Return: Non-zero value when true/zero when false + * + * Programmer: Robb Matzke + * Friday, December 12, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static htri_t +H5E_same_class(H5E_cls_t *cls) +{ + 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*/ + + /* Check arguments */ + assert (cls); + + 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; + + FUNC_LEAVE_NOAPI(ret_value); +} #endif /* NEW_ERR */ diff --git a/src/H5Eprivate.h b/src/H5Eprivate.h index c993c69..a08a727 100644 --- a/src/H5Eprivate.h +++ b/src/H5Eprivate.h @@ -204,7 +204,11 @@ typedef struct H5E_t_new { * and a FUNC_LEAVE() within a function body. The arguments are the major * error number, the minor error number, and a description of the error. */ +#ifdef NEW_ERR +#define HERROR(maj, min, str) H5E_push_new(H5E_DEFAULT, __FILE__, FUNC, __LINE__, maj, min, str) +#else #define HERROR(maj, min, str) H5E_push(maj, min, FUNC, __FILE__, __LINE__, str) +#endif /* NEW_ERR */ /* * HCOMMON_ERROR macro, used by HDONE_ERROR and HGOTO_ERROR @@ -288,12 +292,17 @@ 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); -H5_DLL ssize_t H5E_get_class(H5E_cls_t *cls, char *name, size_t size); +H5_DLL ssize_t H5E_get_class_name(H5E_cls_t *cls, char *name, size_t size); H5_DLL ssize_t H5E_get_msg(H5E_msg_t *msg_ptr, H5E_type_t *type, char *msg, size_t size); H5_DLL int H5E_get_num(H5E_t_new *err_stack); H5_DLL herr_t H5E_set_current_stack(H5E_t_new *estack); H5_DLL herr_t H5E_push_new(H5E_t_new *estack, const char *file, const char *func, unsigned line, hid_t cls_id, hid_t maj_id, hid_t min_id, const char *desc); +H5_DLL herr_t H5E_pop(H5E_t_new *err_stack, size_t count); +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); #endif /* NEW_ERR */ diff --git a/src/H5Epublic.h b/src/H5Epublic.h index 038acc2..e579dae 100644 --- a/src/H5Epublic.h +++ b/src/H5Epublic.h @@ -449,14 +449,19 @@ 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); -H5_DLL ssize_t H5Eget_class(hid_t class_id, char *name, size_t size); +H5_DLL ssize_t H5Eget_class_name(hid_t class_id, char *name, size_t size); H5_DLL ssize_t H5Eget_msg(hid_t msg_id, H5E_type_t *type, char *msg, size_t size); H5_DLL int H5Eget_num(hid_t error_stack_id); H5_DLL herr_t H5Eset_current_stack(hid_t err_stack_id); H5_DLL herr_t H5Epush_new(hid_t err_stack, const char *file, const char *func, unsigned line, hid_t maj_id, hid_t min_id, const char *msg, ...); +H5_DLL herr_t H5Epop(hid_t err_stack, size_t count); +H5_DLL herr_t H5Eclear_new(hid_t err_stack); +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); - #ifdef __cplusplus } #endif diff --git a/test/errors.c b/test/errors.c index e7373d5..975a3ec 100644 --- a/test/errors.c +++ b/test/errors.c @@ -32,29 +32,40 @@ const char *FILENAME[] = { int ipoints2[DIM0][DIM1], icheck2[DIM0][DIM1]; hid_t ERR_CLS; +hid_t ERR_STACK; hid_t ERR_MAJ_TEST; hid_t ERR_MAJ_IO; +hid_t ERR_MAJ_API; hid_t ERR_MIN_SUBROUTINE; +hid_t ERR_MIN_ERRSTACK; hid_t ERR_MIN_CREATE; +hid_t ERR_MIN_GETNUM; #define DSET_NAME "a_dataset" #define ERR_CLS_NAME "Error Test" #define PROG_NAME "Error Program" #define PROG_VERS "1.0" + #define ERR_MAJ_TEST_MSG "Error in test" #define ERR_MAJ_IO_MSG "Error in IO" +#define ERR_MAJ_API_MSG "Error in API" #define ERR_MIN_SUBROUTINE_MSG "Error in subroutine" +#define ERR_MIN_ERRSTACK_MSG "Error in error stack" #define ERR_MIN_CREATE_MSG "Error in H5Dcreate" +#define ERR_MIN_GETNUM_MSG "Error in H5Eget_num" +#define MSG_SIZE 64 #define SPACE1_DIM1 4 #define SPACE1_RANK 1 #define SPACE2_RANK 2 #define SPACE2_DIM1 10 #define SPACE2_DIM2 10 +herr_t custom_print_cb(int n, H5E_error_t_new *err_desc, void* client_data); + /*------------------------------------------------------------------------- * Function: test_error @@ -81,7 +92,7 @@ test_error(hid_t file) int i, j, n; hsize_t dims[2]; void *tmp; - char *FUNC_test_error="test_error()"; + const char *FUNC_test_error="test_error"; TESTING("error API based on atomic datatype"); @@ -99,14 +110,16 @@ test_error(hid_t file) /*------------------- Test data values ------------------------*/ /* Create the dataset */ + /* Make it H5Dcreate fail */ + /*file = 0;*/ if ((dataset = H5Dcreate(file, DSET_NAME, H5T_STD_I32BE, space, H5P_DEFAULT))<0) { #ifndef NEW_ERR H5Epush_new(H5E_DEFAULT, __FILE__, FUNC_test_error, __LINE__, ERR_MAJ_IO, ERR_MIN_CREATE, "H5Dcreate failed"); #endif /* NEW_ERR */ - - TEST_ERROR; + goto error; + /*TEST_ERROR;*/ } /* Write the data to the dataset */ @@ -192,16 +205,18 @@ test_error(hid_t file) static herr_t init_error(void) { - size_t cls_size = strlen(ERR_CLS_NAME)+1; + ssize_t cls_size = strlen(ERR_CLS_NAME)+1; char *cls_name = malloc(strlen(ERR_CLS_NAME)+1); - size_t msg_size = strlen(ERR_MIN_SUBROUTINE_MSG) + 1; + ssize_t msg_size = strlen(ERR_MIN_SUBROUTINE_MSG) + 1; char *msg = malloc(strlen(ERR_MIN_SUBROUTINE_MSG)+1); H5E_type_t *msg_type= malloc(sizeof(H5E_type_t)); if((ERR_CLS = H5Eregister_class(ERR_CLS_NAME, PROG_NAME, PROG_VERS))<0) TEST_ERROR; + if((ERR_CLS = H5Eregister_class(ERR_CLS_NAME, PROG_NAME, PROG_VERS))<0) + TEST_ERROR; - if(cls_size != H5Eget_class(ERR_CLS, cls_name, cls_size) + 1) + if(cls_size != H5Eget_class_name(ERR_CLS, cls_name, (size_t)cls_size) + 1) TEST_ERROR; if(strcmp(ERR_CLS_NAME, cls_name)) TEST_ERROR; @@ -210,13 +225,19 @@ init_error(void) TEST_ERROR; if((ERR_MAJ_IO = H5Ecreate_msg(ERR_CLS, H5E_MAJOR_new, ERR_MAJ_IO_MSG))<0) TEST_ERROR; + if((ERR_MAJ_API = H5Ecreate_msg(ERR_CLS, H5E_MAJOR_new, ERR_MAJ_API_MSG))<0) + TEST_ERROR; if((ERR_MIN_SUBROUTINE = H5Ecreate_msg(ERR_CLS, H5E_MINOR_new, ERR_MIN_SUBROUTINE_MSG))<0) TEST_ERROR; + if((ERR_MIN_ERRSTACK = H5Ecreate_msg(ERR_CLS, H5E_MINOR_new, ERR_MIN_ERRSTACK_MSG))<0) + TEST_ERROR; if((ERR_MIN_CREATE = H5Ecreate_msg(ERR_CLS, H5E_MINOR_new, ERR_MIN_CREATE_MSG))<0) TEST_ERROR; + if((ERR_MIN_GETNUM = H5Ecreate_msg(ERR_CLS, H5E_MINOR_new, ERR_MIN_GETNUM_MSG))<0) + TEST_ERROR; - if(msg_size != H5Eget_msg(ERR_MIN_SUBROUTINE, msg_type, msg, msg_size) + 1) + if(msg_size != H5Eget_msg(ERR_MIN_SUBROUTINE, msg_type, msg, (size_t)msg_size) + 1) TEST_ERROR; if(*msg_type != H5E_MINOR_new) TEST_ERROR; @@ -255,23 +276,30 @@ init_error(void) static herr_t error_stack(void) { - hid_t err_stack; int err_num; + const char *FUNC_error_stack="error_stack"; if((err_num = H5Eget_num(H5E_DEFAULT))<0) TEST_ERROR; if(err_num) TEST_ERROR; - if((err_stack = H5Eget_current_stack())<0) + if((ERR_STACK = H5Eget_current_stack())<0) TEST_ERROR; - if((err_num = H5Eget_num(err_stack))<0) - TEST_ERROR; + /* Make it push error */ + if((err_num = H5Eget_num(ERR_STACK))<0) { + H5Epush_new(ERR_STACK, __FILE__, FUNC_error_stack, __LINE__, ERR_MAJ_API, ERR_MIN_GETNUM, + "Get number test failed, returned %d", err_num); + goto error; + /*TEST_ERROR;*/ + } if(err_num) TEST_ERROR; - - if(H5Eclose_stack(err_stack)<0) + + if(H5Eclear_new(ERR_STACK)<0) + TEST_ERROR; + if(H5Eclose_stack(ERR_STACK)<0) TEST_ERROR; PASSED(); @@ -281,6 +309,86 @@ error_stack(void) return -1; } + +/*------------------------------------------------------------------------- + * Function: dump_error + * + * Purpose: Prints error stack in default and customized ways. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Raymond Lu + * July 17, 2003 + * + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +dump_error(hid_t estack) +{ + /* Print errors in library default way */ + fprintf(stderr, "********* Print error stack in HDF5 default way *********\n"); + H5Eprint_new(estack, stderr); + + /* Customized way to print errors */ + fprintf(stderr, "\n********* Print error stack in customized way *********\n"); + H5Ewalk_new(estack, H5E_WALK_UPWARD, custom_print_cb, stderr); + + PASSED(); + return 0; + + error: + return -1; +} + +/*------------------------------------------------------------------------- + * Function: custom_print_cb + * + * Purpose: Callback function to print error stack in customized way. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Raymond Lu + * July 17, 2003 + * + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +custom_print_cb(int n, H5E_error_t_new *err_desc, void* client_data) +{ + FILE *stream = (FILE *)client_data; + char maj[MSG_SIZE]; + char min[MSG_SIZE]; + char cls[MSG_SIZE]; + const int indent = 4; + + /* Get descriptions for the major and minor error numbers */ + H5Eget_class_name(err_desc->cls_id, cls, MSG_SIZE); + H5Eget_msg(err_desc->maj_id, NULL, maj, MSG_SIZE); + H5Eget_msg(err_desc->maj_id, NULL, min, MSG_SIZE); + + fprintf (stream, "%*serror #%03d: %s in %s(): line %u\n", + indent, "", n, err_desc->file_name, + err_desc->func_name, err_desc->line); + fprintf (stream, "%*sclass: %s\n", indent*2, "", cls); + fprintf (stream, "%*smajor: %s\n", indent*2, "", maj); + fprintf (stream, "%*sminor: %s\n", indent*2, "", min); + + PASSED(); + return 0; + + error: + return -1; +} /*------------------------------------------------------------------------- @@ -340,7 +448,7 @@ main(void) { hid_t file, fapl; char filename[1024]; - const char *FUNC_main="main()"; + const char *FUNC_main="main"; h5_reset(); #ifndef NEW_ERR @@ -355,16 +463,25 @@ main(void) TEST_ERROR ; #ifndef NEW_ERR - if(error_stack()<0) - TEST_ERROR ; + if(error_stack()<0) { + H5Epush_new(ERR_STACK, __FILE__, FUNC_main, __LINE__, ERR_MAJ_TEST, ERR_MIN_ERRSTACK, + "Error stack test failed"); + H5Epop(ERR_STACK, 1); + dump_error(ERR_STACK); + /*H5Eprint_new(ERR_STACK, stderr);*/ + H5Eclose_stack(ERR_STACK); + TEST_ERROR; + } #endif /* NEW_ERR */ if(test_error(file)<0) { #ifndef NEW_ERR H5Epush_new(H5E_DEFAULT, __FILE__, FUNC_main, __LINE__, ERR_MAJ_TEST, ERR_MIN_SUBROUTINE, - "Error test failed because %s", "it's wrong"); -#endif /* NEW_ERR */ - TEST_ERROR ; + "Error test failed, %s", "it's wrong"); + H5Eprint_new(H5E_DEFAULT, stderr); +#endif /* NEW_ERR */ + goto error; + /*TEST_ERROR;*/ } if (H5Fclose(file)<0) TEST_ERROR ; |