Message Processing
Let's see how program messages are handled. In general, when either the application program or a shell library function need to produce a message, they call the
csaPrintMsg CSA primitive. Messages are identified by a
message number (the "1000" of the
Hello World example), an associated explanatory text, and some of them can be passed optional arguments (the
$CSA_PGM in said example). Message numbers are always a four-digit code. Codes beginning with "0" (0000, 0001, ... 0999) are reserved for basic CSA messages. They can be used by both CSA library functions and application programs, and refer to generic error or informational conditions (such as errors reading/writing files, generic error messages, generic positive completion messages, etc.). Messages from 1000 to 9999 are available to application programmers, and can be re-defined differently for each specific CSA application. Messages are organized in flat-file tables, composed by fields (or
columns) which are separated from each other by an horizontal TAB character. This is an example entry for message 0008:
0008<TAB>ERR_SYSTEM<TAB>could not read from file '%s' In the example I have represented with "<TAB>" the otherwise non-printable horizontal TAB character. The message code uniquely identifies the message table entry, and further down I'll explain the meaning of the ERR_SYSTEM field. The sample message shown takes one parameter, the name of the file that the program failed to read, so to actually use the message a program would do:
csaPrintMsg 0008 /path/to/my/file The ERR_SYSTEM field in the message table is the
message group identifier. This is a symbolic string, all upper-case, that identifies the
class of messages that a particular message belongs to.
The class string is actually made up by two substrings, separated by an underscore: class_subclass. The class part can be one of:
- CSA (reserved for CSA use)
- ERR
- INFO
- WARN
The
CSA class is reserved for CSA use, and MUST NOT be used by application-defined messages. The subclass part can be one of:
- ARGS
- AUTH
- CREATED
- DATABASE
- DENIED
- INPUT
- LOCAL (reserved for use by the application)
- MOVED
- NOTFOUND
- OK
- PEER
- PROMPT
- REFUSED
- SYSTEM (reserved for CSA use)
The generic SYSTEM subclass is reserved for CSA use, and MUST NOT be used by application-defined messages. If an application needs to define a general subclass, it can use the LOCAL one.
Therefore, a message group of ERR_REFUSED belongs to the ERR class, and its subclass (REFUSED) indicates that it is related to something that the issuer refused to do, for some reason. An ERR_SYSTEM string means that an error occured in a generic component of the CSA stack, while ERR_LOCAL indicates a generic error at the application level. To get an idea of how message groups are used, have a look at
$CSA_INSTALL/message.d/0/en_US.data .
The purpose of this classification scheme is to identify, in a machine-readable format, the general condition that caused a message to be issued.
If an application program wants to issue a certain message, but it is not satisfied with the default message group associated with that message, it may override that value by passing the new group name to
csaPrintMsg . For instance, the default group associated with message 0008 is ERR_SYSTEM, since it is usually an indication that an error occurred and that the program SHOULD stop. However, a particular application may consider that condition just a warning, and continue processing. In that case it SHOULD override the original message group with a new value indicating a less severe condition, like WARN_SYSTEM, for example. Choosing the appropriate message group is not mandatory, but will help when reading message logs and debugging applications.
Back to the previous example, to issue message 0008 with a message group of WARN_SYSTEM instead of the default ERR_SYSTEM, an application would do:
csaPrintMsg 0008 WARN_SYSTEM /path/to/my/file As previously shown, message 0008 takes a string argument '%s'. Messages are processed with the
printf(1) shell utility, so please refer to the relevant man page for more on the parameter substitution rules.
For the complete list of CSA pre-defined messages
0xxx , see the relevant tables in the CSA installation directory, usually
/usr/local/csa/message.d/ . In the directory there are one message file for each message language supported by CSA. To date, only
en_US (US-English) and
it (Italian) are provided, but others may follow in the future. The language selection can be done by setting the
$CSA_LANG_DEFAULT variable to the desired language code in the
$CSA_ROOT/csa.rc application profile. If unset, this variable defaults to en_US. Application programs may specify a different language code through variable
$CSA_LANG . The language code is used to identify not only the correct message table, but also the associated template subdirectory of
forms/ . For instance, response templates for the
en_US language are expected to be in
forms/en_US/ . The language code is also used by CSA library routines that handle date values, which will represent dates consistently with the code used (DD/MM/YYYY, MM/DD/YYYY, and so on).
Beside CSA predefined messages, each application will usually need to define its own. Those can be assigned any code between 1000 and 9999, MUST be organized in language-code files as already explained, and are expected to be found in
$CSA_ROOT/message.d/ . Each message MUST be given a suitable message group, in the form of the symbolic labels previously explained.
You only need to provide message files for those languages that your application actually uses. The message issued by
example.hello-world has code 1000, meaning that it is an application-defined message, and it can be found in
$CSA_ROOT/message.d/ . Beside being grouped into language code tables, messages are further grouped into sub-directories according to the first digit of the message code. The complete path to the file containing our sample message (1000) will therefore be
$CSA_ROOT/message.d/1/en_US.data . The reason why I further classified messages in this way was to allow different programmers, working at different parts of an application, to handle their own messages without interefering with each-other. This may or may not be a problem, depending on whether you use other cooperative development tools, like the Concurrent Versioning System (CVS), to coordinate your development team. But anyway the facility is there and, even if you don't need it, it will not hurt. See the concept of Path-Based Clustering, in
Data Tables, for more details on this table-record grouping scheme, as it applies also to other CSA data tables, not just to messages.
Provided that both CSA- and application-defined messages are organized in directories and files as shown, the
csaPrintMessage primitive will be able to fetch and process them transparently, removing the associated hassle from the application program.
Whenever
csaPrintMsg is called with the proper arguments it does the following main things:
- Fetches the message from the proper message table, according to the specified message code and the language which is in effect.
- Makes parameter substitutions on the message text if necessary.
- Sets the global variable
$CSA_MSG_NUM to the message code.
- Sets the global variable
$CSA_MSG_GRP to the symbolic message group name.
- Sets the global variable
$CSA_MSG_TEXT to the message text (after substitutions).
- Logs the message to
$CSA_ROOT/var/message.log .
Since
csaPrintMsg writes log entries to
$CSA_ROOT/var/message.log , that file will eventually grow in size, and on a busy server it will need to be rotated at regular intervals (for instance daily, or weekly), by properly configuring your local logfile rotation facility. On
Debian GNU/Linux see
/etc/logrotate.conf . Other
Linux distributions may provide different rotation facilities.
Trackbacks (0) |
New trackback |
Print
|