You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

357 lines
15 KiB

//Copyright 2020 Siemens Digital Industries Software
//==================================================
//Copyright $2010.
//Siemens Product Lifecycle Management Software Inc.
//All Rights Reserved.
//==================================================
//Copyright 2020 Siemens Digital Industries Software
/**
@file ErrorStoreBase.hxx
This file contains the declarations of the ErrorStoreBase class in module libbase_utils.
ErrorStoreBase is the keeper of error codes raised by ERROR_raise() in libsyss.
ErrorStoreBase is a singleton, which can be accessed through the static function Teamcenter::ErrorStoreBase::getInstance().
The system (Teamcenter) needs to do the following in order to fully initialise ErrorStore functionality:
<ol>
<li>implement a decoder function that translates an error code into an internationalized error message (something like EMH_get_err_string())
<li>this decoder function must set its return value and success/failure flag via @c libbase_utils Teamcenter::ErrorStoreBase::set_error_string()
<li>register this decoder function once per session via @c libbase_utils Teamcenter::ErrorStoreBase::set_decoder_function(...) (e.g. in ERROR_store_init_table())
<li>register this decoder function for various error code ranges via @c libsyss ERROR_register_decoder_fn() (e.g. in ERROR_store_init_table())
</ol>
*/
#ifndef BASE_UTILS_ERROR_STORE_HXX
#define BASE_UTILS_ERROR_STORE_HXX
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <unidefs.h>
#include <vector>
#include <base_utils/libbase_utils_exports.h>
namespace Teamcenter
{
class BASE_UTILS_API ErrorStoreBase
{
public:
typedef int ERROR_severity_t;
typedef char * (*ERROR_decode_function_t) (int ifail, void * data);
typedef void (*ERROR_decode_free_function_t) (void * decoded_text);
typedef void (*ERROR_journal_comment_function_t)( const char * );
typedef void (*ERROR_journal_flush_function_t)( void );
static const ERROR_severity_t ERRORSTORE_SEVERITY_INFORMATION = 1; // EMH_severity_information
static const ERROR_severity_t ERRORSTORE_SEVERITY_WARNING = 2; // EMH_severity_warning
static const ERROR_severity_t ERRORSTORE_SEVERITY_ERROR = 3; // EMH_severity_error
static const ERROR_severity_t ERRORSTORE_SEVERITY_USER_ERROR = 4; // EMH_severity_user_error
static const ERROR_severity_t ERRORSTORE_SEVERITY_PROTECT_MARK = 100;
static ErrorStoreBase & getInstance();
/**
Returns the top-most error message from the error stack.
<br/>If the error stack is empty, return "".
*/
static std::string getTopErrorMessage( int presumed_top_ifail );
/**
Adds the given error to the store.
@note The parameters @p s1 to @p s7 will be substituted into the parameterized error message
to form the localized error message.
<br/>Parameters show as @c "%n$" in the parameterized error message, where @c n is the n-th argument to substitute.
@note If @p ifail is zero, the first string is taken as the total error message.
@returns The provided @p ifail.
*/
int store( ERROR_severity_t severity, int ifail,
const char *s1=0, const char *s2=0, const char *s3=0, const char *s4=0, const char *s5=0, const char *s6=0, const char *s7=0);
/**
Clears the error stack and adds the given error.
@note It might complain indignantly if the error store was not empty anyway (i.e. you ignored an error).
@returns The provided @p ifail.
*/
int store_initial_error( ERROR_severity_t severity, int ifail,
const char *s1=0, const char *s2=0, const char *s3=0, const char *s4=0, const char *s5=0, const char *s6=0, const char *s7=0);
/**
Stores the given error as the last-but-one error.
@returns The provided @p ifail.
*/
int store_before_latest( ERROR_severity_t severity, int ifail,
const char *s1=0, const char *s2=0, const char *s3=0, const char *s4=0, const char *s5=0, const char *s6=0, const char *s7=0);
/**
Stores the given error, but replaces its normal error message with a provided message.
@note It might complain indignantly if the error store was not empty anyway (i.e. you ignored an error).
@returns The provided @p ifail.
*/
int store_substituted( ERROR_severity_t severity, int ifail, const char *s);
/**
Forgets the last-stored error.
*/
void forget_last_error (int ifail_to_forget);
/**
Forgets all errors on the error stack.
*/
void clear();
/**
Forgets all errors with a given severity.
*/
void clear(
ERROR_severity_t level /**<(I) The severity level. */
);
/**
Forgets the first error with the given number found starting from the top of the error stack.
*/
void clear_topmost_ifail( int ifail_to_be_cleared );
/**
Protects the current errors from any call to call to ErrorStoreBase::clear (either method).
*/
void set_protect_mark( int * mark, const char * fileName, int lineNumber );
/**
Removes the protection mark set through ErrorStoreBase::set_protect_mark.
*/
void clear_protect_mark( int mark );
/**
Watches for an error of the given value to be added to the error stack.
<br/>If such an error is added, the call stack is printed in the syslog file.
*/
void catch_this_ifail(
int ifail /**< (I) The ifail to watch for.
<br/>If the value is a multiple of @c 1000 (i.e. an error base),
all errors from this error base and @c 999 are watched.
<br/>If the value is @c -42, all the errors are being watched. */
);
/**
Returns the error currently being watched.
*/
int ask_catching_ifail( void ) const;
/**
A potential ERROR_internal call
*/
void assert_empty( void ) const;
/**
Returns the last error added to the error stack.
*/
int ask_last_ifail( void ) const;
/**
Retrieves the translated error message corresponding to the last error.
@returns A static pointer valid until the next ERROR store operation.
<br/>A pointer to an empty string will be returned if
the error stack is empty or the last entry is a protect mark.
*/
const char * ask_last_message( int presumed_top_ifail ) const;
/**
Retrieves all stored errors.
@returns Static pointers that are valid until the next ERROR store operation
<br/>Messages are in historical order (message zero is the oldest).
<br/>Tracebacks will only be set if a) it is non-null and b) CHECKING is on
*/
void ask( int * count, const ERROR_severity_t ** severities, const int ** ifails, const char *const ** messages, const char *const ** tracebacks = 0) const;
/**
Checks through the error stack down to the top protect mark, if a given error is in the error stack.
@returns @c true if this particular error is in the error stack.
*/
logical ask_had_error( int ifail ) const;
/**
Checks through the error stack down to the top protect mark, if a given error (of severity warning) is in the error stack.
@return true if found.
*/
logical ask_had_warning() const;
/**
Prints the error store.
*/
void print( FILE *fp = 0 ) const;
/**
Returns a mini-traceback that is SM allocated (@c UGII_CHECKING_LEVEL must be set to 2).
*/
char* traceback_as_string() const;
/**
Function to provide a string giving the interesting bits of a traceback.
Used by the TC_USAGE tool.
@param ignore_first_n The number of entries in the stack trace to ignore.
@returns The SM_allocated string for writing to the TC_USAGE table.
*/
char * traceback_as_string_for_usage (
int ignore_first_n /**< (I) The number of rows in the traceback to skip before gathering the stack trace information. */
);
/**
The inital error is stored the first time ERROR_raise is called since the
last call to clear_initial_traceback
the returned integer was the failure code, if non-zero then it may be interesting to ask_initial_traceback()
*/
static int ask_initial_error();
/**
The initial trace back is stored the first time ERROR_raise is called until the last call to ErrorStoreBase::clear_initial_traceback.
@returns The first error raised since the last call ot ErrorStoreBase::clear_initial_traceback
<br/>If it is non-zero, the traceback string may be of interest.
*/
static int ask_initial_traceback( const char *separator, /**< (I) The separator used in @p traceback in between different errors. */
char ** traceback /**< (OF) The traceback information. */
);
/**
The inital trace back is stored the first time ERROR_raise is called since the
last call to clear_initial_traceback
*/
static void clear_initial_traceback();
/**
A check to allow us to be confident that ERROR_decode did or did not use
the decode function registered with ERROR_register_decoder_fn.
<br/>Functions registered with ERROR_register_decoder_fn should call ErrorStoreBase::set_last_decoded_error_string so to:
<ol>
<li>Enable ErrorStorebase to use the right function to free memory
<li>Enable ErrorStorebase to determine whether ERROR_decode did or did not use the registered function
</ol>
@note Refer to ErrorStoreBase::ask_last_decoded_error_string
*/
void set_last_decoded_error_string( const char * decoded_error_string, /**< (I) The decoded I18n error message, e.g. "CXPOM_wrong_class: given %1$ when expecting %2$"
or "CXPOM_wrong_class: %1$ vorhanden, wenn %2$ erwartet". */
logical translation_found, /**< (I) Whether or not the message represents a successfully internationalized error message,
e.g. use "false" for the fallback error message "error_7023". */
ERROR_decode_free_function_t remover /**< (I) The function to use in order to free the memory pointed to by 'decoded_error_string'. */
);
/**
Allows to find out whether ERROR_decode did or did not use
the decode function registered with ERROR_register_decoder_fn.
<br/>The function registered with ERROR_register_decoder_fn should call ErrorStoreBase::set_last_decoded_error_string so to enable ErrorStorebase to:
<ol>
<li>Use the right function to free memory
<li>Determine whether ERROR_decode did or did not use the registered function
</ol>
The function returns NULL if the decoded error message (e.g. "CXPOM_wrong_class: given %1$ when expecting %2$")
has already been substituted (e.g. "CXPOM_wrong_class: given WorkspaceObject when expecting Item").
@note Refer to ErrorStoreBase::set_last_decoded_error_string
*/
void ask_last_decoded_error_string( const char ** error_string, /**< (O) The last known decoded error message whose placeholder have not yet been substituted,
something like "CXPOM_wrong_class: given %1$ when expecting %2$" or "CXPOM_wrong_class: %1$ vorhanden, wenn %2$ erwartet". */
logical * translation_found, /**< (O) Whether or not the message represents a successfully internationalized error message,
e.g. "false" for the fallback error message "error_7023". */
ERROR_decode_free_function_t * remover /**< (O) The function to use in order to free the memory pointed to by 'decoded_error_string'. */
) const;
/**
Returns the error decoding function, which is the function used to decode an error number into its associated error string (with placeholders for I18n).
*/
ERROR_decode_function_t ask_decoder_function() const;
/**
Sets the error decoding function, which is the function used to decode an error number into its associated error string (with placeholders for I18n).
*/
void set_decoder_function( ERROR_decode_function_t decode_function );
/**
Registers specific error codes that should trigger the following call:
@code
ERROR_note( ERROR_line, "internal programming error %d", ifail );
@endcode
*/
void register_internal_error( int ifail );
/**
Unregisters the error codes (i.e. stop triggering a call to ERROR_note).
*/
void unregister_internal_error( int ifail );
/**
Returns the registered error codes (i.e. the ones that trigger a call to ERROR_note).
*/
const std::set< int > & ask_registered_internal_errors() const;
/**
Sets the journal comment function, which is the function that records a comment into the journal file.
*/
void set_journal_comment_function( ERROR_journal_comment_function_t journal_comment_function );
/**
Sets the journal flush function, which is the function that flushes the journal.
*/
void set_journal_flush_function( ERROR_journal_flush_function_t journal_flush_function );
/**
Frees the memory associated with an error message returned from ERROR_decode.
*/
void free_error_decode_message( const char *error_decode_message );
private:
ErrorStoreBase();
virtual ~ErrorStoreBase();
int * ifail_store;
const char ** message_store;
ERROR_severity_t * severity_store;
const char ** substitutions_store;
const char ** tracebacks_store;
std::set< int > registered_internal_errors; // specific internal error codes that should trigger a ERROR_note( ERROR_line, "internal programming error %d", ifail );
int store_size;
int store_allocated;
int ifail_to_catch;
logical record_error_protect_calls;
ERROR_decode_function_t decode_function;
const char * decoded_error_string;
logical decoded_error_translated;
ERROR_decode_free_function_t decoded_error_remover;
ERROR_journal_comment_function_t journal_comment_function;
ERROR_journal_flush_function_t journal_flush_function;
void increment_store_size();
void delete_top_error();
void delete_given_error( int where_ );
void internal_store_error( ERROR_severity_t severity, int ifail, const char *s1, const char *s2, const char *s3, const char *s4, const char *s5, const char *s6, const char *s7);
void record_error_protect_call( int mark, const char * fileName, int lineNumber );
void ensure_errors_translated();
void print_error_n( FILE * fp, int entry, int max_message_length ) const;
};
} // namespace Teamcenter
#include <base_utils/libbase_utils_undef.h>
#endif // BASE_UTILS_ERROR_STORE_HXX