#include <w.h> #include <w_error.h> class w_rc_t; class w_error_t; class w_error_info_t;
These classes are used internally by
class w_rc_t;This manual page is of interest only to writers of value-added servers, and then only those who need to generate their own sets of error codes.
Error codes are unsigned integers, returned from Shore methods in the form of a w_rc_t (see rc(fc) ). Each error code has associated metadata, which consists of a descriptive string and a name (either by way of an enumeration, or by a C-preprocessor-defined name) (which could be considered meta-metadata, perhaps).
The integer values associated with error code names,
the descriptive strings, the enumerations, and the
#define
Error codes are grouped into modules, so that all the error codes for a software module and their metadata are kept together. Each module is given a mask, which is folded into the values assigned to the errorcodes. This keeps the error codes for different software modules distinct.
The software that manages error codes keeps a (global) list of all the modules of error codes. Each software layer that uses the error codes must invoke a method to `install' its module in the global list. The method is generated by the Perl script.
The data structure w_error_info_t stores the error codes and their associated metadata. This data structure is generated by the Perl script.
The data structure w_error_t holds an error code, line number and file name, and its instances can be linked to form stack traces. The application programmer does not directly manipulate them, however; the application programming interface for returning and interpreting errors is the class w_rc_t.
The Perl script tools/errors.pl, in the Shore source tree, generates error codes from an input file that is best described with an example. The following example is taken from the Shore storage manager.
The script takes one of two mutually exclusive options, and a file name. One or the other of the options (-d, -e) is required:
$(SHORE_SOURCES)/tools/errors.pl -d <input-file> // or $(SHORE_SOURCES)/tools/errors.pl -e <input-file>
In the first case (-d) the named constants are generated as C preprocessor defined constants. The prefix of the generated names is capitalized and separated from the rest of the name by an underscore character (in concert with Paleozoic convention).
In the second case (-e) the named constants are generated as members of an anonymous enumeration. The prefix of the generated names is taken, case unchanged, from the input file.
e = 0x00080000 "Storage Manager" smlevel_0 { ASSERT Assertion failed USERABORT User initiated abort ..skip the rest -- it's too long for a man page! }The input is parsed as follows. On the first line:
Blank lines may appear anywhere. Lines beginning with `#' are comments.
The next three lines define error codes:
enum { eASSERT = 0x80000, ... };
The Perl script generates a set of files. The names of the files have the prefix given on the first line of a module's input. In the above example, the output files are:
w_error_info_t smlevel_0 ::error_info[] = { { eASSERT , "Assertion failed" }, ... };
<em> If a class name did not appear in the input file, the name of the data structure will be `_error_info' prepended with the name of the module. </em> In this case, it would be
w_error_info_t e_error_info[] = { { eASSERT , "Assertion failed" }, ... };
Second is the full definition of a method
void smlevel_0 ::init_errorcodes()that your code can call to `install' the module of error codes in a global list of all the error codes in the running program. This method is generated only if the input for the module contains a class name.
enum { eASSERT = 0x80000, eUSERABORT = 0x80001, ... eLOGICALIDOVERFLOW = 0x80041, eTRANSITTIMEOUT = 0x80042, }; enum { eERRMIN = 0x80000, eERRMAX = 0x80042 };
#define E_OK 0 #define E_ASSERT 0x80000 #define E_USERABORT 0x80001 .. #define E_LOGICALIDOVERFLOW 0x80041 #define E_TRANSITTIMEOUT 0x80042 #define E_ERRMIN 0x80000 #define E_ERRMAX 0x80042
static char *e_errmsg[] = { /* eASSERT */ "Assertion failed", /* eUSERABORT */ "User initiated abort", ... }; const e_msg_size = 66;Of course, the strings are in the proper order so the array can be indexed by the error code (after subtracting the module's mask).
Your program must `install' your modules by calling init_errorcodes() or, if you did not use a class name for your module, by explicitly installing the set:
w_rc_t rc = w_error_t::insert( "Storage Manager", // name of the module e_error_info, // the error_info list eERRMAX - eERRMIN + 1 // number of items in the // error_info list. ); ...
If you want to write code that returns one of your error codes, you use the manifest constants to build w_rc_t structures, which can be printed directly. See rc(fc) for details.