ERS_NO_DEBUG
macro is defined at compilation time. ERS_NO_DEBUG
macro is defined at compilation time. The message argument of these macros can be any entity, for which the operator<< to the standard C++ output stream is defined. This means that the message can be a single value of a certain type as well as a sequence of output operations of appropriate types. For example: ERS_DEBUG( 1, "test debug output " << 123 << " which shows how to use debug macro" )
> export TDAQ_ERS_VERBOSITY_LEVEL=N
ERS_DECLARE_ISSUE( ers, // namespace name Assertion, // issue name "Assertion (" << condition << ") failed because " << reason, // message ((const char *)condition ) // first attribute ((const char *)reason ) // second attribute )
((attribute_type)attribute_name). All the brackets in this expression are essential. Do not put commas between different attributes. The only requiremnt to the type of issue attributes is that such type must define the output operator to the standard C++ output stream and the input operator from the standard C++ input stream. It is important to note that these operator must unambiguously match each other, i.e. the input operator must be able to unambiguously restore the state of the object from the stream, which has been used to save the object's state using the output operator. Evidently all the standard C++ types satisfy this criteria. The result of the ERS_DECLARE_ISSUE macro expansion will look like: namespace ers { class Assertion : public ers::Issue { template <class> friend class ers::IssueRegistrator; Assertion() { ; } static const char * get_uid() { return "ers::Assertion"; } virtual void raise() const throw( std::exception ) { throw *this; } virtual const char * get_class_name() const { return get_uid(); } virtual ers::Issue * clone() const { return new ers::Assertion( *this ); } public: Assertion( const ers::Context & context , const char * condition , const char * reason ) : ers::Issue( context ) { set_value( "condition", condition ); set_value( "reason", reason ); std::ostringstream out; out << "Assertion (" << condition << ") failed because " << reason; set_message( out.str() ); } Assertion( const ers::Context & context, const std::string & msg , const char * condition , const char * reason ) : ers::Issue( context, msg ) { set_value( "condition", condition ); set_value( "reason", reason ); } Assertion( const ers::Context & context , const char * condition , const char * reason , const std::exception & cause ) : ers::Issue( context, cause ) { set_value( "condition", condition ); set_value( "reason", reason ); std::ostringstream out; out << "Assertion (" << condition << ") failed because " << reason; set_message( out.str() ); } const char * get_condition () { const char * val; get_value( "condition", val ); return val; } const char * get_reason () { const char * val; get_value( "reason", val ); return val; } }; }
ExampleIssues.h The macro ERS_DECLARE_ISSUE_BASE has to be used in case one wants to declare the issue class, which inherits from one of the issue classes declared with either this or ERS_DECLARE_ISSUE macro. For example, the following class inherits from the ers::Assertion class defined above:
ERS_DECLARE_ISSUE_BASE( ers, // namespace name Precondition, // issue name ers::Assertion, // base issue name "Precondition (" << condition << ") located in " << location << " failed because " << reason, // message ((const char *)condition ) ((const char *)reason ), // base class attributes ((const char *)location ) // this class attributes )
namespace ers { class Precondition : public ers::Assertion { template <class> friend class ers::IssueRegistrator; Precondition() { ; } static const bool registered = ers::IssueRegistrator< ers::Precondition >::instance.done; static const char * get_uid() { return "ers::Precondition"; } virtual void raise() const throw( std::exception ) { throw *this; } virtual const char * get_class_name() const { return get_uid(); } virtual ers::Issue * clone() const { return new ers::Precondition( *this ); } public: Precondition( const ers::Context & context , const char * condition , const char * reason, const char * location ) : ers::Assertion( context, condition, reason ) { set_value( "location", location ); std::ostringstream out; out << "Precondition (" << condition << ") located in " << location << ") failed because " << reason; set_message( out.str() ); } Precondition( const ers::Context & context, const std::string & msg , const char * condition , const char * reason, const char * location ) : ers::Assertion( context, msg, condition, reason ) { set_value( "location", location ); } Precondition( const ers::Context & context , const char * condition , const char * reason , const char * location, const std::exception & cause ) : ers::Assertion( context, condition, reason, cause ) { set_value( "location", location ); std::ostringstream out; out << "Precondition (" << condition << ") located in " << location << ") failed because " << reason; set_message( out.str() ); } const char * get_location () { const char * val; get_value( "location", val ); return val; } }; } \section Exception handling Functions, which can throw exceptions must be invoked insize the \c try...catch statement. The following example shows how one can handle ERS exceptions. First of all one has to declare once all the possible exceptions: \see ExampleIssues.h \code #include <ers/ExampleIssues.h> ... try { foo( ); } catch ( ers::PermissionDenied & ex ) { ers::CantOpenFile issue( ERS_HERE, ex.get_file_name(), ex ); ers::warning( issue ); } catch ( ers::FileDoesNotExist & ex ) { ers::CantOpenFile issue( ERS_HERE, ex.get_file_name(), ex ); ers::warning( issue ); } catch ( ers::Issue & ex ) { ERS_DEBUG( 0, "Unknown issue caught: " << ex ) ers::error( ex ); } catch ( std::exception & ex ) { ers::CantOpenFile issue( ERS_HERE, "unknown", ex ); ers::warning( issue ); }
> export TDAQ_ERS_ERROR="stderr,throw"
> export TDAQ_ERS_ERROR="stderr,filter(ipc),throw"
> export TDAQ_ERS_ERROR="stderr,filter(!ipc,!is),throw"