Apart from the dce_svc_printf( ) routine for writing production serviceability messages, the interface provides several macros that can be used for debug messaging in a server. The advantages in using these macros in debugging are the following:
· All the debug messaging code can easily be compiled in or out of the executable by changing the value of a compilation switch.
· Nine levels of debug messaging are provided for; the active level of debug messaging can be controlled through the remote serviceability interface or by a value passed to the server at startup.
· One of the macros allows message text to be specified in the call itself, rather than extracting it by message ID from the message table.
The debug serviceability messaging routines are the following:
· DCE_SVC_LOG( )
Outputs a message specified by the message ID. The main differences between using this routine and using dce_svc_printf( ) to write a message are 1) that DCE_SVC_LOG( ) generates records in binary format only, and 2) the macro can be compiled out of the executable by turning off debugging.
Suppose the following message had been defined in the hel.sams file for the example application in Defining the Message:
start
code hel_s_debug_message_1
subcomponent hel_s_main
attributes "svc_c_debug3 | svc_c_route_stderr"
text "This is a level 1 test debug message"
explanation "Debug level 3 test"
action "None required."
end
The following call in hello_svc.c would have written this message as a binary record to the specified route, provided that debug level 3 had been activated:
DCE_SVC_LOG((HEL_S_DEBUG_MESSAGE_1_MSG));
Note the use of the double parentheses. This is made necessary by the fact that it is a macro that takes a variable number of arguments. Note also the use of the convenience macro form of the message. A full form of the call, with all arguments explicitly specified, would have been as follows:
DCE_SVC_LOG((DCE_SVC(hel_svc_handle, ""), \
hel_s_main, svc_c_debug3, hel_s_debug_message_1));
/* | | | */
/* table_index | | */
/* debug level | */
/* message ID */
Debug messages, like normal serviceability messages, can also contain format specifiers and argument lists.
· DCE_SVC_DEBUG( )
Outputs a message whose text is specified in the call. For example, the following call could have appeared in hello_svc.c:
DCE_SVC_DEBUG((hel_svc_handle, \
/* | */
/* handle */
/* */
hel_s_main, svc_c_debug2, "A Debug Level %d message", 2));
/* | | | | */
/* table_index | | | */
/* debug level | | */
/* message text | */
/* argument */
Note here too the use of the double parentheses.
Note also that DCE_SVC_DEBUG cannot be used with the convenience macro forms of serviceability messages.
· DCE_SVC_DEBUG_ATLEAST( )
Tests the active debug level for a subcomponent. Returns TRUE if the debug level (set by calling dce_svc_debug_set_levels( ); see Setting Debug Levels) is not less than the specified level; otherwise returns FALSE. For example, the following call would return TRUE if the debug level for the hel_s_main subcomponent of the hello_svc application had been set to svc_c_debug2 or any higher value:
DCE_SVC_DEBUG_ATLEAST(hel_svc_handle, hel_s_main, svc_c_debug2);
This macro can be used to test the active debug level and avoid calling a debug output routine if the level of its message is disabled at the time of the call (disabling the level does not stop any routines from being executed; it only suppresses the output messages at that level). See Performance Costs of Serviceability Debugging for more information.
· DCE_SVC_DEBUG_IS( )
Tests the active debug level for a subcomponent. Returns TRUE if the debug level is the same as that specified in the call; otherwise returns FALSE. For example, the following call would return TRUE only if the debug level for hel_s_main had been set to svc_c_debug2:
DCE_SVC_DEBUG_IS(hel_svc_handle, hel_s_main, svc_c_debug2);
· dce_assert( )
Evaluates an int expression passed to it and, if the expression evaluates to 0 (that is, if the expression is false), automatically calls dce_svc_printf( ) with parameters that will cause a message with a severity level of svc_c_sev_fatal (that is, fatal) and an action attribute of svc_c_action_abort to be printed that will identify the following:
- The expression
- The source file in which the assertion failed
- The line at which the assertion failed
For example, the following call will cause the failed expression (namely, the string) to be printed and the program to be aborted.
dce_assert(hel_svc_handle, ("Test diagnostic message" == NULL))
A NULL can be substituted for the serviceability handle as the first argument.
It is very important that debug messages not be used for errors that can occur during ordinary operation. This is because the debug messaging code can be omitted when compiling for production.
More: