diff options
-rw-r--r-- | c++/src/H5Exception.cpp | 6 | ||||
-rw-r--r-- | c++/src/H5Exception.h | 2 | ||||
-rw-r--r-- | src/H5.c | 2 | ||||
-rw-r--r-- | src/H5E.c | 227 | ||||
-rw-r--r-- | src/H5Eprivate.h | 2 | ||||
-rw-r--r-- | src/H5Epublic.h | 17 | ||||
-rw-r--r-- | test/error_test.c | 6 | ||||
-rw-r--r-- | test/testerror.sh | 1 | ||||
-rw-r--r-- | test/testfiles/err_compat_1 | 2 |
9 files changed, 225 insertions, 40 deletions
diff --git a/c++/src/H5Exception.cpp b/c++/src/H5Exception.cpp index c52e974..3ac47b6 100644 --- a/c++/src/H5Exception.cpp +++ b/c++/src/H5Exception.cpp @@ -227,7 +227,7 @@ void Exception::clearErrorStack() ///\par /// Data structure to describe the error: ///\code -/// typedef struct H5E_error_t { +/// typedef struct H5E_error_stack_t { /// hid_t cls_id; //class ID /// hid_t maj_num; //major error ID /// hid_t min_num; //minor error number @@ -235,11 +235,11 @@ void Exception::clearErrorStack() /// 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; +/// } H5E_error_stack_t; ///\endcode // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- -void Exception::walkErrorStack( H5E_direction_t direction, H5E_walk_t func, void* client_data ) +void Exception::walkErrorStack( H5E_direction_t direction, H5E_walk_stack_t func, void* client_data ) { // calls the C API routine H5Ewalk to walk the error stack herr_t ret_value = H5Ewalk_stack( H5E_DEFAULT, direction, func, client_data ); diff --git a/c++/src/H5Exception.h b/c++/src/H5Exception.h index 8ea3da0..66219c7 100644 --- a/c++/src/H5Exception.h +++ b/c++/src/H5Exception.h @@ -63,7 +63,7 @@ class H5_DLLCPP Exception { // Walks the error stack for the current thread, calling the // specified function. static void walkErrorStack( H5E_direction_t direction, - H5E_walk_t func, void* client_data); + H5E_walk_stack_t func, void* client_data); // Prints the error stack in a default manner. virtual void printError( FILE* stream = NULL ) const; @@ -1760,7 +1760,7 @@ H5_trace (const double *returning, const char *func, const char *type, ...) fprintf(out, "NULL"); } } else { - H5E_error_t *error = va_arg (ap, H5E_error_t*); /*lint !e64 Type mismatch not really occuring */ + H5E_error_stack_t *error = va_arg (ap, H5E_error_stack_t*); /*lint !e64 Type mismatch not really occuring */ fprintf (out, "0x%lx", (unsigned long)error); } break; @@ -107,10 +107,11 @@ static herr_t H5E_close_stack(H5E_t *err_stack); static ssize_t H5E_get_num(const H5E_t *err_stack); static herr_t H5E_pop(H5E_t *err_stack, size_t count); static herr_t H5E_clear_entries(H5E_t *estack, size_t nentries); -static herr_t H5E_print_stack(const H5E_t *estack, FILE *stream); -static herr_t H5E_walk_stack(const H5E_t *estack, H5E_direction_t direction, H5E_walk_t func, - void *client_data); +static herr_t H5E_print_stack(const H5E_t *estack, FILE *stream, hbool_t bk_compatible); +static herr_t H5E_walk_stack(const H5E_t *estack, H5E_direction_t direction, H5E_walk_t func, + H5E_walk_stack_t stack_func, hbool_t bk_compatible, void *client_data); static herr_t H5E_walk_cb(unsigned n, const H5E_error_t *err_desc, void *client_data); +static herr_t H5E_walk_stack_cb(unsigned n, const H5E_error_stack_t *err_desc, void *client_data); static herr_t H5E_get_auto_stack(const H5E_t *estack, hbool_t new_api, void **func, void **client_data); static herr_t H5E_set_auto_stack(H5E_t *estack, hbool_t new_api, void *func, void *client_data); @@ -1026,7 +1027,7 @@ H5E_get_current_stack(void) /* Make a copy of current error stack */ estack_copy->nused = current_stack->nused; for(u=0; u<current_stack->nused; u++) { - H5E_error_t *current_error, *new_error; /* Pointers to errors on each stack */ + H5E_error_stack_t *current_error, *new_error; /* Pointers to errors on each stack */ /* Get pointers into the current error stack location */ current_error = &(current_stack->slot[u]); @@ -1140,7 +1141,7 @@ H5E_set_current_stack(H5E_t *estack) /* Copy new stack to current error stack */ current_stack->nused = estack->nused; for(u=0; u<current_stack->nused; u++) { - H5E_error_t *current_error, *new_error; /* Pointers to errors on each stack */ + H5E_error_stack_t *current_error, *new_error; /* Pointers to errors on each stack */ /* Get pointers into the current error stack location */ current_error = &(current_stack->slot[u]); @@ -1759,7 +1760,7 @@ done: static herr_t H5E_clear_entries(H5E_t *estack, size_t nentries) { - H5E_error_t *error; /* Pointer to error stack entry to clear */ + H5E_error_stack_t *error; /* Pointer to error stack entry to clear */ unsigned u; /* Local index variable */ herr_t ret_value=SUCCEED; /* Return value */ @@ -1872,7 +1873,7 @@ H5Eprint(FILE *stream) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") /* Print error stack */ - if(H5E_print_stack(estack, stream)<0) + if(H5E_print_stack(estack, stream, TRUE)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't display error stack") done: @@ -1930,7 +1931,7 @@ H5Eprint_stack(hid_t err_stack, FILE *stream) } /* end else */ /* Print error stack */ - if(H5E_print_stack(estack, stream)<0) + if(H5E_print_stack(estack, stream, FALSE)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't display error stack") done: @@ -1966,9 +1967,9 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5E_print_stack(const H5E_t *estack, FILE *stream) +H5E_print_stack(const H5E_t *estack, FILE *stream, hbool_t bk_compatible) { - H5E_print_t eprint; /* Callback information to pass to H5E_walk_cb() */ + H5E_print_t eprint; /* Callback information to pass to H5E_walk_stack_cb() */ herr_t ret_value = SUCCEED; /* Don't clear the error stack! :-) */ @@ -1987,8 +1988,13 @@ H5E_print_stack(const H5E_t *estack, FILE *stream) HDmemset(&eprint.cls,0,sizeof(H5E_cls_t)); /* Walk the error stack */ - if(H5E_walk_stack(estack, H5E_WALK_DOWNWARD, H5E_walk_cb, (void*)&eprint)<0) - HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack") + if(bk_compatible) { + if(H5E_walk_stack(estack, H5E_WALK_DOWNWARD, H5E_walk_cb, NULL, TRUE, (void*)&eprint)<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack") + } else { + if(H5E_walk_stack(estack, H5E_WALK_DOWNWARD, NULL, H5E_walk_stack_cb, FALSE, (void*)&eprint)<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack") + } done: FUNC_LEAVE_NOAPI(ret_value) @@ -2025,7 +2031,7 @@ H5Ewalk(H5E_direction_t direction, H5E_walk_t func, void *client_data) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") /* Walk the error stack */ - if(H5E_walk_stack(estack, direction, func, client_data)<0) + if(H5E_walk_stack(estack, direction, func, NULL, TRUE, client_data)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack") done: @@ -2053,7 +2059,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5Ewalk_stack(hid_t err_stack, H5E_direction_t direction, H5E_walk_t func, void *client_data) +H5Ewalk_stack(hid_t err_stack, H5E_direction_t direction, H5E_walk_stack_t stack_func, void *client_data) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ @@ -2076,7 +2082,7 @@ H5Ewalk_stack(hid_t err_stack, H5E_direction_t direction, H5E_walk_t func, void } /* end else */ /* Walk the error stack */ - if(H5E_walk_stack(estack, direction, func, client_data)<0) + if(H5E_walk_stack(estack, direction, NULL, stack_func, FALSE, client_data)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack") done: @@ -2096,11 +2102,16 @@ done: * 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. + * The function pointed to by STACK_FUNC will be called for + * each error record 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_stack. + * + * The function FUNC is also provided for backward compatibility. + * When BK_COMPATIBLE is set to be TRUE, FUNC is used to be + * compatible with older library. If BK_COMPATIBLE is FALSE, + * STACK_FUNC is used. * * Return: Non-negative on success/Negative on failure * @@ -2113,10 +2124,16 @@ done: * Wednesday, July 16, 2003 * Let it walk through specified error stack. * + * Raymond Lu + * Friday, May 12, 2006 + * Added backward compatibility support. FUNC is for older + * library; STACK_FUNC is for new library. + * *------------------------------------------------------------------------- */ static herr_t -H5E_walk_stack(const H5E_t *estack, H5E_direction_t direction, H5E_walk_t func, void *client_data) +H5E_walk_stack(const H5E_t *estack, H5E_direction_t direction, H5E_walk_t func, H5E_walk_stack_t stack_func, + hbool_t bk_compatible, void *client_data) { int i; /* Local index variable */ herr_t status; /* Status from callback function */ @@ -2132,15 +2149,56 @@ H5E_walk_stack(const H5E_t *estack, H5E_direction_t direction, H5E_walk_t func, direction = H5E_WALK_UPWARD; /* Walk the stack if a callback function was given */ - if(func) { + if(bk_compatible && func) { + H5E_error_t old_err; + + status=SUCCEED; + if (H5E_WALK_UPWARD==direction) { + for (i=0; i<(int)estack->nused && status>=0; i++) { + /*Copy each error record on the stack and pass it to callback function.*/ + old_err.maj_num = estack->slot[i].maj_num; + old_err.min_num = estack->slot[i].min_num; + old_err.func_name = HDstrdup(estack->slot[i].func_name); + old_err.file_name = HDstrdup(estack->slot[i].file_name); + old_err.desc = HDstrdup(estack->slot[i].desc); + old_err.line = estack->slot[i].line; + + status = (func)((unsigned)i, &old_err, client_data); + + HDfree(old_err.func_name); + HDfree(old_err.file_name); + HDfree(old_err.desc); + } + } else { + H5_CHECK_OVERFLOW(estack->nused-1,size_t,int); + for (i=(int)(estack->nused-1); i>=0 && status>=0; i--) { + /*Copy each error record on the stack and pass it to callback function.*/ + old_err.maj_num = estack->slot[i].maj_num; + old_err.min_num = estack->slot[i].min_num; + old_err.func_name = HDstrdup(estack->slot[i].func_name); + old_err.file_name = HDstrdup(estack->slot[i].file_name); + old_err.desc = HDstrdup(estack->slot[i].desc); + old_err.line = estack->slot[i].line; + + status = (func)((unsigned)(estack->nused-(size_t)(i+1)), &old_err, client_data); + + HDfree(old_err.func_name); + HDfree(old_err.file_name); + HDfree(old_err.desc); + } + } + + if(status<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack") + } else if(!bk_compatible && stack_func) { status=SUCCEED; if (H5E_WALK_UPWARD==direction) { for (i=0; i<(int)estack->nused && status>=0; i++) - status = (func)((unsigned)i, estack->slot+i, client_data); + status = (stack_func)((unsigned)i, estack->slot+i, client_data); } else { H5_CHECK_OVERFLOW(estack->nused-1,size_t,int); for (i=(int)(estack->nused-1); i>=0 && status>=0; i--) - status = (func)((unsigned)(estack->nused-(size_t)(i+1)), estack->slot+i, client_data); + status = (stack_func)((unsigned)(estack->nused-(size_t)(i+1)), estack->slot+i, client_data); } if(status<0) @@ -2153,11 +2211,126 @@ done: /*------------------------------------------------------------------------- - * Function: H5E_walk_cb + * Function: H5E_walk_stack_cb * * 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_stack() function. This function is + * called also by H5Eprint_stack(). 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_stack_cb(unsigned n, const H5E_error_stack_t *err_desc, void *client_data) +{ + H5E_print_t *eprint = (H5E_print_t *)client_data; + FILE *stream; /* I/O stream to print output to */ + H5E_cls_t *cls_ptr; /* Pointer to error class */ + H5E_msg_t *maj_ptr; /* Pointer to major error info */ + H5E_msg_t *min_ptr; /* Pointer to minor error info */ + const char *maj_str = "No major description"; /* Major error description */ + const char *min_str = "No minor description"; /* Minor error description */ + unsigned have_desc=1; /* Flag to indicate whether the error has a "real" description */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5E_walk_stack_cb) + + /* Check arguments */ + assert (err_desc); + + /* If no client data was passed, output to stderr */ + if (!client_data) stream = stderr; + else stream = eprint->stream; + + /* Get descriptions for the major and minor error numbers */ + maj_ptr = H5I_object_verify(err_desc->maj_num, H5I_ERROR_MSG); + min_ptr = H5I_object_verify(err_desc->min_num, H5I_ERROR_MSG); + assert(maj_ptr && min_ptr); + if(maj_ptr->msg) + maj_str = maj_ptr->msg; + if(min_ptr->msg) + min_str = min_ptr->msg; + + /* Get error class info */ + cls_ptr = maj_ptr->cls; + + /* Print error class header if new class */ + if(eprint->cls.lib_name==NULL || HDstrcmp(cls_ptr->lib_name, eprint->cls.lib_name)) { + /* update to the new class information */ + if(cls_ptr->cls_name) eprint->cls.cls_name = cls_ptr->cls_name; + if(cls_ptr->lib_name) eprint->cls.lib_name = cls_ptr->lib_name; + if(cls_ptr->lib_vers) eprint->cls.lib_vers = cls_ptr->lib_vers; + + fprintf (stream, "%s-DIAG: Error detected in %s (%s) ", cls_ptr->cls_name, 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) +#ifdef WIN32 + fprintf (stream, "some thread: no way to know the thread number from pthread on windows"); +#else + fprintf (stream, "thread %lu", (unsigned long)pthread_self()); +#endif +#else + fprintf (stream, "thread 0"); +#endif + fprintf (stream, ":\n"); + } + + /* Check for "real" error description - used to format output more nicely */ + if(err_desc->desc==NULL || HDstrlen(err_desc->desc)==0) + have_desc=0; + + /* Print error message */ + fprintf (stream, "%*s#%03u: %s line %u in %s()%s%s\n", + H5E_INDENT, "", n, err_desc->file_name, err_desc->line, + err_desc->func_name, (have_desc ? ": " : ""), + (have_desc ? err_desc->desc : "")); + fprintf (stream, "%*smajor: %s\n", H5E_INDENT*2, "", maj_str); + fprintf (stream, "%*sminor: %s\n", H5E_INDENT*2, "", min_str); + + FUNC_LEAVE_NOAPI(SUCCEED) +} + + +/*------------------------------------------------------------------------- + * Function: H5E_walk_cb + * + * Purpose: This function is for backward compatibility. + * This is a default error stack traversal callback function + * that prints error messages to the specified output stream. + * This function is for backward compatibility with v1.6. + * 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 @@ -2178,8 +2351,8 @@ done: * * Return: Non-negative on success/Negative on failure * - * Programmer: Robb Matzke - * Friday, December 12, 1997 + * Programmer: Raymond Lu + * Thursday, May 11, 2006 * * Modifications: * diff --git a/src/H5Eprivate.h b/src/H5Eprivate.h index 0c99f9f..ff47b8c 100644 --- a/src/H5Eprivate.h +++ b/src/H5Eprivate.h @@ -43,7 +43,7 @@ typedef struct H5E_msg_t { /* Error stack */ typedef struct H5E_t { size_t nused; /* Num slots currently used in stack */ - H5E_error_t slot[H5E_NSLOTS]; /* Array of error records */ + H5E_error_stack_t slot[H5E_NSLOTS]; /* Array of error records */ hbool_t new_api; /* Indicate that the function pointer is for the new (stack) API or the old */ union { H5E_auto_t func; /* Function for 'automatic' error reporting */ diff --git a/src/H5Epublic.h b/src/H5Epublic.h index 001f0a5..8ba97c4 100644 --- a/src/H5Epublic.h +++ b/src/H5Epublic.h @@ -37,8 +37,18 @@ typedef enum H5E_type_t { typedef hid_t H5E_major_t; typedef hid_t H5E_minor_t; -/* Information about an error; element of error stack */ +/* Information about an error; element of error stack. For backward compatibility with v1.6. */ typedef struct H5E_error_t { + H5E_major_t maj_num; /*major error number */ + H5E_minor_t min_num; /*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; + +/* Information about an error; element of error stack */ +typedef struct H5E_error_stack_t { hid_t cls_id; /*class ID */ hid_t maj_num; /*major error ID */ hid_t min_num; /*minor error number */ @@ -46,7 +56,7 @@ typedef struct H5E_error_t { const char *func_name; /*function in which error occurred */ const char *file_name; /*file in which error occurred */ const char *desc; /*optional supplied description */ -} H5E_error_t; +} H5E_error_stack_t; /* When this header is included from a private header, don't make calls to H5open() */ #undef H5OPEN @@ -143,6 +153,7 @@ extern "C" { /* Error stack traversal callback function pointers */ typedef herr_t (*H5E_walk_t)(unsigned n, const H5E_error_t *err_desc, void *client_data); +typedef herr_t (*H5E_walk_stack_t)(unsigned n, const H5E_error_stack_t *err_desc, void *client_data); typedef herr_t (*H5E_auto_t)(void *client_data); typedef herr_t (*H5E_auto_stack_t)(hid_t estack, void *client_data); @@ -178,7 +189,7 @@ H5_DLL const char * H5Eget_minor(H5E_minor_t min); H5_DLL herr_t H5Epush_stack(hid_t err_stack, const char *file, const char *func, unsigned line, hid_t cls_id, hid_t maj_id, hid_t min_id, const char *msg, ...); H5_DLL herr_t H5Eprint_stack(hid_t err_stack, FILE *stream); -H5_DLL herr_t H5Ewalk_stack(hid_t err_stack, H5E_direction_t direction, H5E_walk_t func, +H5_DLL herr_t H5Ewalk_stack(hid_t err_stack, H5E_direction_t direction, H5E_walk_stack_t func, void *client_data); H5_DLL herr_t H5Eget_auto_stack(hid_t estack_id, H5E_auto_stack_t *func, void **client_data); H5_DLL herr_t H5Eset_auto_stack(hid_t estack_id, H5E_auto_stack_t func, void *client_data); diff --git a/test/error_test.c b/test/error_test.c index ad3dd11..d19738e 100644 --- a/test/error_test.c +++ b/test/error_test.c @@ -76,7 +76,7 @@ hid_t ERR_MIN_GETNUM; #define LONG_DESC_SIZE 8192 -herr_t custom_print_cb(unsigned n, const H5E_error_t *err_desc, void* client_data); +herr_t custom_print_cb(unsigned n, const H5E_error_stack_t *err_desc, void* client_data); /*------------------------------------------------------------------------- @@ -304,7 +304,7 @@ error_stack(void) *------------------------------------------------------------------------- */ static herr_t -long_desc_cb(unsigned UNUSED n, const H5E_error_t *err_desc, void* client_data) +long_desc_cb(unsigned UNUSED n, const H5E_error_stack_t *err_desc, void* client_data) { char *real_desc = (char *)client_data; @@ -430,7 +430,7 @@ dump_error(hid_t estack) *------------------------------------------------------------------------- */ herr_t -custom_print_cb(unsigned n, const H5E_error_t *err_desc, void* client_data) +custom_print_cb(unsigned n, const H5E_error_stack_t *err_desc, void* client_data) { FILE *stream = (FILE *)client_data; char maj[MSG_SIZE]; diff --git a/test/testerror.sh b/test/testerror.sh index 789b86f..fafc05d 100644 --- a/test/testerror.sh +++ b/test/testerror.sh @@ -65,6 +65,7 @@ TEST() { # Extract file name, line number, version and thread IDs because they may be different sed -e 's/thread [0-9]*/thread (IDs)/' -e 's/: .*\.c /: (file name) /' \ -e 's/line [0-9]*/line (number)/' \ + -e 's/v[1-9]*\.[0-9]*\./version (number)\./' \ -e 's/[1-9]*\.[0-9]*\.[0-9]*[^)]*/version (number)/' \ $actual_err > $actual_ext cat $actual_ext >> $actual diff --git a/test/testfiles/err_compat_1 b/test/testfiles/err_compat_1 index dd7578d..032e7bc 100644 --- a/test/testfiles/err_compat_1 +++ b/test/testfiles/err_compat_1 @@ -2,7 +2,7 @@ Expected output for err_compat ############################# Testing error API based on data I/O All error API tests passed. - This program tests the Error API compatible with HDF5 vversion (number) There're supposed to be some error messages + This program tests the Error API compatible with HDF5 version (number). There're supposed to be some error messages ********* Print error stack in HDF5 default way ********* HDF5-DIAG: Error detected in HDF5 (version (number)) thread (IDs): #000: (file name) line (number) in main(): Error test failed |