mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-03-25 17:00:45 +08:00
Code Cleanup Description: Changed POSIX function calls to the HD* way of doing things. Checked with checkposix and tested on Linux. Platforms tested: Linux
732 lines
22 KiB
C
732 lines
22 KiB
C
/*
|
||
* Copyright (C) 1998-2001 NCSA HDF
|
||
* All rights reserved.
|
||
*
|
||
* Purpose: Provides error handling in the form of a stack. The
|
||
* FUNC_ENTER() macro clears the error stack whenever an API
|
||
* function is entered. When an error is detected, an entry is
|
||
* pushed onto the stack. As the functions unwind additional
|
||
* entries are pushed onto the stack. The API function will
|
||
* return some indication that an error occurred and the
|
||
* application can print the error stack.
|
||
*
|
||
* Certain API functions in the H5E package (such as H5Eprint())
|
||
* do not clear the error stack. Otherwise, any function which
|
||
* doesn't have an underscore immediately after the package name
|
||
* will clear the error stack. For instance, H5Fopen() clears
|
||
* the error stack while H5F_open() does not.
|
||
*
|
||
* An error stack has a fixed maximum size. If this size is
|
||
* exceeded then the stack will be truncated and only the
|
||
* inner-most functions will have entries on the stack. This is
|
||
* expected to be a rare condition.
|
||
*
|
||
* Each thread has its own error stack, but since
|
||
* multi-threading has not been added to the library yet, this
|
||
* package maintains a single error stack. The error stack is
|
||
* statically allocated to reduce the complexity of handling
|
||
* errors within the H5E package.
|
||
*
|
||
*/
|
||
#include "H5private.h" /* Generic Functions */
|
||
#include "H5Iprivate.h" /* IDs */
|
||
#include "H5Eprivate.h" /* Private error routines */
|
||
#include "H5MMprivate.h" /* Memory management */
|
||
|
||
#define PABLO_MASK H5E_mask
|
||
|
||
static const H5E_major_mesg_t H5E_major_mesg_g[] = {
|
||
{H5E_NONE_MAJOR, "No error"},
|
||
{H5E_ARGS, "Function arguments"},
|
||
{H5E_RESOURCE, "Resource unavailable"},
|
||
{H5E_INTERNAL, "Internal HDF5 error"},
|
||
{H5E_FILE, "File interface"},
|
||
{H5E_IO, "Low-level I/O layer"},
|
||
{H5E_FUNC, "Function entry/exit"},
|
||
{H5E_ATOM, "Atom layer"},
|
||
{H5E_CACHE, "Meta data cache layer"},
|
||
{H5E_BTREE, "B-tree layer"},
|
||
{H5E_SYM, "Symbol table layer"},
|
||
{H5E_HEAP, "Heap layer"},
|
||
{H5E_OHDR, "Object header layer"},
|
||
{H5E_DATATYPE, "Datatype interface"},
|
||
{H5E_DATASPACE, "Dataspace interface"},
|
||
{H5E_DATASET, "Dataset interface"},
|
||
{H5E_STORAGE, "Data storage layer"},
|
||
{H5E_PLIST, "Property list interface"},
|
||
{H5E_ATTR, "Attribute layer"},
|
||
{H5E_PLINE, "Data filters layer"},
|
||
{H5E_EFL, "External file list"},
|
||
{H5E_REFERENCE, "References layer"},
|
||
{H5E_VFL, "Virtual File Layer"},
|
||
{H5E_TBBT, "Threaded, Balanced, Binary Trees"},
|
||
};
|
||
|
||
static const H5E_minor_mesg_t H5E_minor_mesg_g[] = {
|
||
{H5E_NONE_MINOR, "No error"},
|
||
|
||
/* Argument errors */
|
||
{H5E_UNINITIALIZED, "Information is uninitialized"},
|
||
{H5E_UNSUPPORTED, "Feature is unsupported"},
|
||
{H5E_BADTYPE, "Inappropriate type"},
|
||
{H5E_BADRANGE, "Out of range"},
|
||
{H5E_BADVALUE, "Bad value"},
|
||
|
||
/* Resource errors */
|
||
{H5E_NOSPACE, "No space available for allocation"},
|
||
{H5E_CANTCOPY, "Unable to copy object"},
|
||
{H5E_CANTFREE, "Unable to free object"},
|
||
|
||
/* File accessability errors */
|
||
{H5E_FILEEXISTS, "File already exists"},
|
||
{H5E_FILEOPEN, "File already open"},
|
||
{H5E_CANTCREATE, "Unable to create file"},
|
||
{H5E_CANTOPENFILE, "Unable to open file"},
|
||
{H5E_CANTCLOSEFILE, "Unable to close file"},
|
||
{H5E_NOTHDF5, "Not an HDF5 file"},
|
||
{H5E_BADFILE, "Bad file ID accessed"},
|
||
{H5E_TRUNCATED, "File has been truncated"},
|
||
{H5E_MOUNT, "File mount error"},
|
||
|
||
/* Generic low-level file I/O errors */
|
||
{H5E_SEEKERROR, "Seek failed"},
|
||
{H5E_READERROR, "Read failed"},
|
||
{H5E_WRITEERROR, "Write failed"},
|
||
{H5E_CLOSEERROR, "Close failed"},
|
||
{H5E_OVERFLOW, "Address overflowed"},
|
||
|
||
/* Function entry/exit interface errors */
|
||
{H5E_CANTINIT, "Unable to initialize"},
|
||
{H5E_ALREADYINIT, "Object already initialized"},
|
||
|
||
/* Object atom related errors */
|
||
{H5E_BADATOM, "Unable to find atom information (already closed?)"},
|
||
{H5E_CANTREGISTER, "Unable to register new atom"},
|
||
|
||
/* Cache related errors */
|
||
{H5E_CANTFLUSH, "Unable to flush data from cache"},
|
||
{H5E_CANTLOAD, "Unable to load meta data into cache"},
|
||
{H5E_PROTECT, "Protected meta data error"},
|
||
{H5E_NOTCACHED, "Meta data not currently cached"},
|
||
|
||
/* B-tree related errors */
|
||
{H5E_NOTFOUND, "Object not found"},
|
||
{H5E_EXISTS, "Object already exists"},
|
||
{H5E_CANTENCODE, "Unable to encode value"},
|
||
{H5E_CANTDECODE, "Unable to decode value"},
|
||
{H5E_CANTSPLIT, "Unable to split node"},
|
||
{H5E_CANTINSERT, "Unable to insert object"},
|
||
{H5E_CANTLIST, "Unable to list node"},
|
||
|
||
/* Object header related errors */
|
||
{H5E_LINKCOUNT, "Bad object header link count"},
|
||
{H5E_VERSION, "Wrong version number"},
|
||
{H5E_ALIGNMENT, "Alignment error"},
|
||
{H5E_BADMESG, "Unrecognized message"},
|
||
{H5E_CANTDELETE, "Can't delete message"},
|
||
|
||
/* Group related errors */
|
||
{H5E_CANTOPENOBJ, "Can't open object"},
|
||
{H5E_COMPLEN, "Name component is too long"},
|
||
{H5E_CWG, "Problem with current working group"},
|
||
{H5E_LINK, "Link count failure"},
|
||
{H5E_SLINK, "Symbolic link error"},
|
||
|
||
/* Datatype conversion errors */
|
||
{H5E_CANTCONVERT, "Can't convert datatypes"},
|
||
|
||
/* Datatype conversion errors */
|
||
{H5E_MPI, "Some MPI function failed"}
|
||
};
|
||
|
||
/* Interface initialization? */
|
||
static intn interface_initialize_g = 0;
|
||
#define INTERFACE_INIT H5E_init_interface
|
||
static herr_t H5E_init_interface (void);
|
||
const hbool_t H5E_clearable_g = TRUE; /* DO NOT CHANGE */
|
||
|
||
#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 *H5E_get_stack(void);
|
||
#define H5E_get_my_stack() H5E_get_stack()
|
||
#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 H5E_stack_g[1];
|
||
#define H5E_get_my_stack() (H5E_stack_g+0)
|
||
#endif
|
||
|
||
/*
|
||
* Automatic error stack traversal occurs if the traversal callback function
|
||
* is non null and an API function is about to return an error. These should
|
||
* probably be part of the error stack so they're local to a thread.
|
||
*/
|
||
herr_t (*H5E_auto_g)(void*) = (herr_t(*)(void*))H5Eprint;
|
||
void *H5E_auto_data_g = NULL;
|
||
|
||
|
||
#ifdef H5_HAVE_THREADSAFE
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5E_get_stack
|
||
*
|
||
* 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 *H5E_get_stack(void)
|
||
{
|
||
H5E_t *estack = pthread_getspecific(H5TS_errstk_key_g);
|
||
|
||
if (!estack) {
|
||
/* no associated value with current thread - create one */
|
||
estack = (H5E_t *)H5MM_malloc(sizeof(H5E_t));
|
||
pthread_setspecific(H5TS_errstk_key_g, (void *)estack);
|
||
}
|
||
|
||
return estack;
|
||
}
|
||
#endif /* H5_HAVE_THREADSAFE */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5E_init_interface
|
||
*
|
||
* Purpose: Initialize the H5E interface. `stderr' is an extern or
|
||
* function on some systems so we can't initialize
|
||
* H5E_auto_data_g statically.
|
||
*
|
||
* Return: Success: Non-negative
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Friday, June 11, 1999
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5E_init_interface (void)
|
||
{
|
||
FUNC_ENTER(H5E_init_interface, FAIL);
|
||
H5E_auto_data_g = stderr;
|
||
FUNC_LEAVE(SUCCEED);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5Eset_auto
|
||
*
|
||
* Purpose: Turns on or off automatic printing of errors. 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(H5E_auto_t func, void *client_data)
|
||
{
|
||
FUNC_ENTER (H5Eset_auto, FAIL);
|
||
H5TRACE2("e","xx",func,client_data);
|
||
|
||
H5E_auto_g = func;
|
||
H5E_auto_data_g = client_data;
|
||
|
||
FUNC_LEAVE (SUCCEED);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5Eget_auto
|
||
*
|
||
* Purpose: Returns the current settings for the automatic error stack
|
||
* traversal function and its data. Either (or both) arguments
|
||
* may be null in which case the value is not returned.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Saturday, February 28, 1998
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5Eget_auto(H5E_auto_t *func, void **client_data)
|
||
{
|
||
FUNC_ENTER (H5Eget_auto, FAIL);
|
||
H5TRACE2("e","*x*x",func,client_data);
|
||
|
||
if (func) *func = H5E_auto_g;
|
||
if (client_data) *client_data = H5E_auto_data_g;
|
||
|
||
FUNC_LEAVE (SUCCEED);
|
||
}
|
||
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5Eclear
|
||
*
|
||
* Purpose: Clears the error stack for the current thread.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Friday, February 27, 1998
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5Eclear(void)
|
||
{
|
||
FUNC_ENTER (H5Eclear, FAIL);
|
||
H5TRACE0("e","");
|
||
/* FUNC_ENTER() does all the work */
|
||
FUNC_LEAVE (SUCCEED);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5Eprint
|
||
*
|
||
* 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.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5Eprint(FILE *stream)
|
||
{
|
||
H5E_t *estack = H5E_get_my_stack ();
|
||
hbool_t H5E_clearable_g = FALSE; /*override global*/
|
||
herr_t status = FAIL;
|
||
|
||
FUNC_ENTER (H5Eprint, FAIL);
|
||
/*NO TRACE*/
|
||
|
||
if (!stream) stream = stderr;
|
||
fprintf (stream, "HDF5-DIAG: Error detected in ");
|
||
/* 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
|
||
if (estack && estack->nused>0) fprintf (stream, " Back trace follows.");
|
||
HDfputc ('\n', stream);
|
||
status = H5E_walk (H5E_WALK_DOWNWARD, H5Ewalk_cb, (void*)stream);
|
||
|
||
FUNC_LEAVE (status);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5Ewalk
|
||
*
|
||
* 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:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5Ewalk(H5E_direction_t direction, H5E_walk_t func, void *client_data)
|
||
{
|
||
hbool_t H5E_clearable_g = FALSE; /*override global*/
|
||
herr_t status = FAIL;
|
||
|
||
FUNC_ENTER (H5Ewalk, FAIL);
|
||
H5TRACE3("e","Edxx",direction,func,client_data);
|
||
status = H5E_walk (direction, func, client_data);
|
||
FUNC_LEAVE (status);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5Ewalk_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() 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:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5Ewalk_cb(int n, H5E_error_t *err_desc, void *client_data)
|
||
{
|
||
FILE *stream = (FILE *)client_data;
|
||
const char *maj_str = NULL;
|
||
const char *min_str = NULL;
|
||
const int indent = 2;
|
||
|
||
/*NO TRACE*/
|
||
|
||
/* Check arguments */
|
||
assert (err_desc);
|
||
if (!client_data) client_data = stderr;
|
||
|
||
/* Get descriptions for the major and minor error numbers */
|
||
maj_str = H5Eget_major (err_desc->maj_num);
|
||
min_str = H5Eget_minor (err_desc->min_num);
|
||
|
||
/* Print error message */
|
||
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, "%*smajor(%02d): %s\n",
|
||
indent*2, "", err_desc->maj_num, maj_str);
|
||
fprintf (stream, "%*sminor(%02d): %s\n",
|
||
indent*2, "", err_desc->min_num, min_str);
|
||
|
||
return SUCCEED;
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5Eget_major
|
||
*
|
||
* Purpose: Given a major error number return a constant character string
|
||
* that describes the error.
|
||
*
|
||
* Return: Success: Ptr to a character string.
|
||
*
|
||
* Failure: Ptr to "Invalid major error number"
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Friday, February 27, 1998
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
const char *
|
||
H5Eget_major (H5E_major_t n)
|
||
{
|
||
uintn i;
|
||
|
||
/*
|
||
* WARNING: Do not call the FUNC_ENTER() or FUNC_LEAVE() macros since
|
||
* they might interact badly with the error stack. We are
|
||
* probably calling this function during an error stack
|
||
* traversal and adding/removing entries as the result of an
|
||
* error would most likely mess things up.
|
||
*/
|
||
for (i=0; i<NELMTS (H5E_major_mesg_g); i++) {
|
||
if (H5E_major_mesg_g[i].error_code==n) {
|
||
return H5E_major_mesg_g[i].str;
|
||
}
|
||
}
|
||
|
||
return "Invalid major error number";
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5Eget_minor
|
||
*
|
||
* Purpose: Given a minor error number return a constant character string
|
||
* that describes the error.
|
||
*
|
||
* Return: Success: Ptr to a character string.
|
||
*
|
||
* Failure: Ptr to "Invalid minor error number"
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Friday, February 27, 1998
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
const char *
|
||
H5Eget_minor (H5E_minor_t n)
|
||
{
|
||
uintn i;
|
||
|
||
/*
|
||
* WARNING: Do not call the FUNC_ENTER() or FUNC_LEAVE() macros since
|
||
* they might interact badly with the error stack. We are
|
||
* probably calling this function during an error stack
|
||
* traversal and adding/removing entries as the result of an
|
||
* error would most likely mess things up.
|
||
*/
|
||
for (i=0; i<NELMTS (H5E_minor_mesg_g); i++) {
|
||
if (H5E_minor_mesg_g[i].error_code==n) {
|
||
return H5E_minor_mesg_g[i].str;
|
||
}
|
||
}
|
||
|
||
return "Invalid minor error number";
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5E_push
|
||
*
|
||
* Purpose: Pushes a new error record onto error stack for the current
|
||
* thread. The error has major and minor numbers MAJ_NUM and
|
||
* MIN_NUM, the name of a function where the error was detected,
|
||
* the name of the file where the error was detected, the
|
||
* line within that file, and an error description string. The
|
||
* function name, file name, and error description strings must
|
||
* be statically allocated (the FUNC_ENTER() macro takes care of
|
||
* the function name and file name automatically, but the
|
||
* programmer is responsible for the description string).
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Friday, December 12, 1997
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5E_push(H5E_major_t maj_num, H5E_minor_t min_num, const char *function_name,
|
||
const char *file_name, unsigned line, const char *desc)
|
||
{
|
||
H5E_t *estack = H5E_get_my_stack ();
|
||
|
||
/*
|
||
* WARNING: We cannot call HERROR() from within this function or else we
|
||
* could enter infinite recursion. Furthermore, we also cannot
|
||
* call any other HDF5 macro or function which might call
|
||
* HERROR(). HERROR() is called by HRETURN_ERROR() which could
|
||
* be called by FUNC_ENTER().
|
||
*/
|
||
|
||
/*
|
||
* Don't fail if arguments are bad. Instead, substitute some default
|
||
* value.
|
||
*/
|
||
if (!function_name) function_name = "Unknown_Function";
|
||
if (!file_name) file_name = "Unknown_File";
|
||
if (!desc) desc = "No description given";
|
||
|
||
/*
|
||
* Push the error if there's room. Otherwise just forget it.
|
||
*/
|
||
assert (estack);
|
||
if (estack->nused<H5E_NSLOTS) {
|
||
estack->slot[estack->nused].maj_num = maj_num;
|
||
estack->slot[estack->nused].min_num = min_num;
|
||
estack->slot[estack->nused].func_name = function_name;
|
||
estack->slot[estack->nused].file_name = file_name;
|
||
estack->slot[estack->nused].line = line;
|
||
estack->slot[estack->nused].desc = desc;
|
||
estack->nused++;
|
||
}
|
||
|
||
return SUCCEED; /*don't use FUNC_LEAVE() here */
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5Epush
|
||
*
|
||
* Purpose: Pushes a new error record onto error stack for the current
|
||
* thread. The error has major and minor numbers MAJ_NUM and
|
||
* MIN_NUM, the name of a function where the error was detected,
|
||
* the name of the file where the error was detected, the
|
||
* line within that file, and an error description string. The
|
||
* function name, file name, and error description strings must
|
||
* be statically allocated.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Monday, October 18, 1999
|
||
*
|
||
* Notes: Basically a public API wrapper around the H5E_push function.
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5Epush(const char *file, const char *func, unsigned line, H5E_major_t maj,
|
||
H5E_minor_t min, const char *str)
|
||
{
|
||
herr_t ret_value;
|
||
|
||
FUNC_ENTER(H5Epush, FAIL);
|
||
H5TRACE6("e","ssIuEjEns",file,func,line,maj,min,str);
|
||
ret_value = H5E_push(maj, min, func, file, line, str);
|
||
FUNC_LEAVE(ret_value);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5E_clear
|
||
*
|
||
* Purpose: Clears the error stack for the current thread.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Friday, February 27, 1998
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5E_clear(void)
|
||
{
|
||
H5E_t *estack = H5E_get_my_stack ();
|
||
|
||
FUNC_ENTER(H5E_clear, FAIL);
|
||
if (estack) estack->nused = 0;
|
||
FUNC_LEAVE(SUCCEED);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5E_walk
|
||
*
|
||
* Purpose: 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:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5E_walk (H5E_direction_t direction, H5E_walk_t func, void *client_data)
|
||
{
|
||
H5E_t *estack = H5E_get_my_stack ();
|
||
int i;
|
||
herr_t status;
|
||
|
||
FUNC_ENTER(H5E_walk, 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);
|
||
}
|
||
}
|
||
|
||
FUNC_LEAVE(SUCCEED);
|
||
}
|
||
|