SPRAAK
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
Macros | Typedefs | Enumerations | Functions | Variables
msg.c File Reference

Message and error processing. More...

Macros

#define SPR_MSG_ID(var, name)
 
#define SPR_SET_THREAD_ID(thread_name)
 
#define spr_error(routine,...)
 Send an error message. More...
 
#define spr_warning(routine,...)
 Send a warning message. More...
 
#define spr_info(routine,...)
 Send an info message. More...
 
#define spr_msg_long_start(lvl, routine,...)
 Send a long debug message at a given level lvl. More...
 
#define spr_msg_async_start(lvl, routine,...)
 
#define spr_assert1(routine__, tst__)
 
#define spr_assert2(routine__, tst__)
 
#define spr_assert3(routine__, tst__)
 

Typedefs

typedef void(* SprMsgCatchFunc )(int lvl, const char *thread, const char *routine, const char *format, va_list *list)
 

Enumerations

enum  { SPR_ERROR, SPR_WARNING, SPR_INFO }
 Predefined message levels for error, warning and info messages. More...
 
enum  { SPR_MSG_SET, SPR_MSG_RM, SPR_MSG_ADD }
 

Functions

int spr_msg (int lvl, SprMsgId *routine, const char *fmt,...)
 
int spr_msg_check (int lvl, SprMsgId *routine)
 
int spr_set_thread_id (const char *name)
 
void spr_msg_modif_lvl (int lvl)
 Set the global message filter level to lvl, i.e. only messages with a level equal to or lower than lvl will be output (unless routine or thread specific levels are defined. More...
 
int spr_msg_get_lvl (void)
 
int spr_msg_modif_in (const char *filter_desc, int action)
 
int spr_msg_modif_from (const char *filter_desc, int action)
 
SprDynStr spr_msg_get_in (void)
 
SprDynStr spr_msg_get_from (void)
 
int spr_msg_modif_stream (SprStream *restrict stream, const char *restrict fname)
 
void spr_msg_set_timeout (int sec)
 
void spr_msg_modif_catch_func (SprMsgCatchFunc handler)
 
int spr_msg_ini_time (SprMsgId *prog)
 

Variables

SprStreamspr_msg_stream
 

Detailed Description

Message and error processing.

This module provides a system for message and error reporting/accounting.

The main properties of the system are:

On the program level, configuration of the message system is done by means of the following global options:

–debug_stream
Specify the file (stream) where the messages must be written to. This option corresponds directly to the spr_msg_modif_stream() function.
–debug_lvl
Specify the global info level. This option corresponds directly to the spr_msg_modif_lvl() function.
–debug_in
Specify routine and thread specific message filters. This option corresponds directly to the spr_msg_modif_in() function.
–debug_from
Specify routine and thread specific message triggers for starting the message system. This option corresponds directly to the spr_msg_modif_from() function.

When just using the library, the same effect can be obtained using the environment variables 'SPR_DEBUG_STREAM', 'SPR_DEBUG_LVL', 'SPR_DEBUG_IN', and 'SPR_DEBUG_FROM'.

The message system is used to signal errors, warnings, info messages and even debug information. The severity of the message is indicated by a level. The following levels are predefined:

SPR_ERROR (-3)
The requested operation cannot be performed for some reason.
Examples: files that cannot be opened, invalid arguments, out-of-memory conditions
SPR_WARNING (-2)
A condition that is not fatal to the requested operation but indicates nevertheless that the results may not be as expected.
Examples: empty files, illogical combinations of settings, abnormal values such as gaussians with 0 variance, settings that may lead to extremely slow or borderline stable behaviour
SPR_INFO (-1)
Some useful summary concering a lengthy or memory hogging operation.
Examples: global statistics about the loaded LM, acoustic model, lexicon

The remaining positive levels are used for debugging. The level is typically proportional to the amount of output generated. Some rules of thumb about which level to use where are:

1
Extended information, i.e. thing that could have been equally well of SPR_INFO level, but are judged to be too lengthy, only relevant for the experts, ...
2..3
Program level information, i.e. information on things that will happen only once during the program run.
Examples: The decoded program arguments, the final statics of the program run
4..7
Inform the user about events in the main loop of the program.
8..11
File level information.
Examples: info on each file in the corpus file that is being processed.
12..15
Part-of-file level information.
Examples: processing segments in a file
16..19
Frame level information.
20..23
Sub-frame level information.
Examples: the different steps in an iterative algorithms that process frames.
30
Core events that are expected to be bug/problem free and that could have been used anywhere.

Messages (error, warning, info or debug) can be either short or long.\ Short messages are sent as a single printf() command, are no longer than 1023 characters, and if they consist of multiple lines, all extra lines must start with a tab ('\t'). Multiple short messages can be sent concurrently. Long messages are not concurrent (although short messages can still be sent concurrently). Sending a long message consist of a message start and stop command pair with in between a set of writes to the stream 'spr_msg_stream'. The intermediate output can be free formatted, but must end with a new-line ('\n') character.

Warnings and errors must inform the user on both the problem at hand and the cause of the problem. Errors should, as a rule of thumb, only be reported in the routine where they occur. Rehashing the same error message in the calling routine(s) should be avoided.
Example: if a file fails to open, the spr_fopen() routine will give detailed information. If the main purpuse of the calling routine was opening that file, nothing more needs to be reported. If opening that file was only one step in a more complex operation, a short message indicating that the complex operation failed can be given (but details on the cause are not needed since spr_fopen() already gave the details).

Errors and warnings cannot be blocked. Info and debug messages can be filtered either by a global threshold level or by routine and thread specific threshold levels. Info and debug messages can also be suppressed until a certain trigger is activated. See the routines spr_msg_modif_lvl(), spr_msg_modif_in() and spr_msg_modif_from() for more information.

In order to use the debug system in your code, each routine (or group of routines) must be tagged with a unique id as follows:

int my_function(...)
{SPR_MSG_ID(routine,"name_of_my_function");
...
}

The name of the current function is (in C99) also available using the macro __func__.

Threads must also be tagged with an unique id as follows:

void *thread_start_routine(void *arg)
{SPR_SET_THREAD_ID("name_of_this_thread");
...
}

It is allowed to make dynamic names for threads (e.g. aux_thread00 ... aux_thread99), but this will leak memory (a few bytes per thread started) and is fairly slow, so use this only for coarse grained threading. This can be done as follows:

void *thread_start_routine(void *arg)
{char temp_buffer[16];
sprintf(temp_buffer,"aux_thread%02i",arg->helper_nr);
if(spr_set_thread_id(temp_buffer) == -1)
goto LBL_ERROR;
...
}
Note
The message system is multi-threading safe in the sense that no dead-locks or memory faults will occur when changing the message level, the filters or the triggers. However, during changes the system may exhibit mixed behaviour between the old and the new state.
Author
Kris Demuynck
Date
13/09/2007
Revision History:
30/10/1993 - Frank Schoeters
Creation of the first version
16/06/1999 - Kris Demuynck
Completely rewritten functions
13/09/2007 - Kris Demuynck
Completely rewritten to make MT-safe
Environment variables:

SPR_DEBUG_STREAM
identical to the option –debug_stream

SPR_DEBUG_LVL
identical to the option –debug_lvl

SPR_DEBUG_IN
identical to the option –debug_in

SPR_DEBUG_FROM
identical to the option –debug_drom

Bug:

The message system assumes that names are static strings. See the examples on how to assure this.

Changing the filters (spr_msg_modif_in()) or triggers (spr_msg_modif_from()) while there are multiple threads running may result in some transitional abnormalities (no crashes, just too many or too less messages).

The amount of concurrency the msg-system can handle is limited. Typically 16 threads can send simultanious messages in a non blocking fashion if the destination stream can keep up.

Unamed threads may result in undefined behaviour in combination with nested messages.