proposals for enumeration of interface-specific error codes

Mark Miller miller86 at llnl.gov
Mon Aug 30 19:51:13 CDT 2010


I have to admit, I was confused a bit by the original proposal. On the
one hand, it seems to propose 4 things error codes must satisfy, one of
which is the ability to (efficiently) map a code to a human readable
string via array lookup. Then, it identifies ways to go about this
including foregoing worrying about having to efficiently map codes to
strings via array lookup.

Separately, in looking at the existing codes, I find myself wondering
about a few things...

First, the error code symbol names themselves are pretty explanatory and
can certainly be converted to their string valued equivalents easily
such as the implementation below does. In fact, I see no reason why each
implementation need be burdened with this. Second, these error codes are
defined by the INTERFACE SPECIFICATION itself and NOT really free to the
implementation to define. So, why even permit an implementation to
define them and/or an implementation level detail, like the desire to
decode an error code to a string using an array lookup table, to drive
its 'design'? Third, the current approach does not permit
implementations to define error codes apart from the specification's
error codes. I know Tim has mentioned a need for this in the past and
there is no reason we couldn't define the specification such that it
permits this by designing the numerical values of the error codes to be
separated into high-order (spec.) and low-order (impl.) bit-fields. The
spec. defines high order values (say upper 16 bits) while the
implementation can, at its option, define low order values (lower 16
bits) with the exception of iBase_SUCCESS and iBase_FAILURE where the
implementation MAY NOT define optional low-order parts (e.g. the low
order part is always zero). Instead of '==' comparison of returned error
values, callers would be required to use some sort of macro/function to
split out the high order part (the spec's part) of the error code from
the implementation's part. So, for example, instead of

    'if (err == iBase_NIL_ARRAY)'

we have

    'if (func1(err) == iBase_NIL_ARRAY)'

or

    'if (func2(err, iBase_NIL_ARRAY))'

where func1 strips off low-order (impl) part or func2 replaces the work
of the '==' operator.

But, a call to i*_getDescription() can return BOTH a description of the
spec's error code "iBase_NIL_ARRAY" AS WELL AS an implementation details
the implementation chose to define. For example, instead of returning
"FILE_READ_ERROR", MOAB could also return "unable to open CGM file
because the implementation of MOAB was not configured with CGM support."


A VERY SIMPLE example implementation to map error codes to strings...

#define IBASE_DECODE(ERRCOD)                      \
    if (err == ERRCOD)                            \
    {                                             \
        if (len < strlen(#ERRCOD))                \
            *err = iBase_BAD_ARRAY_SIZE;          \
        else                                      \
            snprintf(desc, len, "%s", #ERRCOD);   \
        return;                                   \
    }

iMesh_getDescription_default(iMesh_Instance,
    char *desc, int *err, int len)
{
    *err = iBase_SUCCESS;
    IBASE_DECODE(iBase_SUCCESS)
    IBASE_DECODE(iBase_MESH_ALREADY_LOADED)
    IBASE_DECODE(iBase_NO_MESH_DATA)
    IBASE_DECODE(iBase_FILE_NOT_FOUND)
    IBASE_DECODE(iBase_FILE_WRITE_ERROR)
    IBASE_DECODE(iBase_NIL_ARRAY)
    IBASE_DECODE(iBase_BAD_ARRAY_SIZE)
    IBASE_DECODE(iBase_BAD_ARRAY_DIMENSION)
    IBASE_DECODE(iBase_INVALID_ENTITY_HANDLE)
    IBASE_DECODE(iBase_INVALID_ENTITY_COUNT)
    IBASE_DECODE(iBase_INVALID_ENTITY_TYPE)
    IBASE_DECODE(iBase_INVALID_ENTITY_TOPOLOGY)
    IBASE_DECODE(iBase_BAD_TYPE_AND_TOPO)
    IBASE_DECODE(iBase_ENTITY_CREATION_ERROR)
    IBASE_DECODE(iBase_INVALID_TAG_HANDLE)
    IBASE_DECODE(iBase_TAG_NOT_FOUND)
    IBASE_DECODE(iBase_TAG_ALREADY_EXISTS)
    IBASE_DECODE(iBase_TAG_IN_USE)
    IBASE_DECODE(iBase_INVALID_ENTITYSET_HANDLE)
    IBASE_DECODE(iBase_INVALID_ITERATOR_HANDLE)
    IBASE_DECODE(iBase_INVALID_ARGUMENT)
    IBASE_DECODE(iBase_MEMORY_ALLOCATION_FAILED)
    IBASE_DECODE(iBase_NOT_SUPPORTED)
    IBASE_DECODE(iBase_FAILURE)
}




On Mon, 2010-08-30 at 13:55, Tim Tautges wrote:
> Note that I have no objection to option 1 below, aside from being sensitive to others' feelings on the issue.
> 
> - tim
> 
> On 08/24/2010 12:31 PM, Jason Kraftcheck wrote:
> > The need for interface-specific error codes was discussed during the
> > boot camp. The following items were agreed upon:
> >
> > o New error codes should be set to the list for review.
> > o All error codes should be included in the iBase_ErrorType enumeration
> > (defined in iBase.h)
> > o Interface-specific error codes should be prefixed with the name of the
> > interface that they are specific to in place of the iBase prefix. For
> > example: iMeshP_NO_PARTITION rather than iBase_NO_PARTITION.
> > o The error codes should be enumerated such that adding a new error code
> > does not break implementations of different interfaces that use an
> > array of strings to implement i*_getDescription. For example, adding
> > a new iMeshP_* error code should not break iRel_* implementations.
> >
> > Below I will propose three alternate schemes for addressing the last
> > point (only).
> >
> > All of these schemes have the additional beneficial property that things
> > will not break if interface-specific error codes are added to the list
> > for an interface for which there were no specific error codes,
> > effectively changing the ordering of the blocks of interface-specific
> > codes.
> >
> > --------------------------------- 1 ----------------------------------
> >
> > My first, and most controversial suggestion, is to ignore the issue.
> > Getting an error string from an error code should not be a
> > performance-sensitive issue. There is no reason not to use a switch
> > statement to obtain the string for an error code rather than indexing
> > into an array, and such a solution does not break in difficult to catch
> > ways when the list of error codes changes.
> >
> > --------------------------------- 2 ----------------------------------
> >
> > The second solution is to do the array based indexing using relative
> > values. Similar to my first proposed solution, this solution requires
> > nothing special be done in the iBase_ErrorType definition.
> >
> > The index into the array of interface-specific error codes can be
> > determined by subtracting the first interface-specific error code from
> > the passed error code. For example:
> >
> > Given:
> >
> > enum iBase_ErrorType {
> > iBase_SUCCESS,
> > iBase_MESH_ALREADY_LOADED,
> > iBase_NO_MESH_DATA,
> > ...
> > iBase_FAILURE,
> >
> > iRel_NO_RELATION,
> > ...
> > iRel_NO_SETS,
> >
> > iMeshP_NO_PARTITION,
> > iMeshP_NO_PART,
> > };
> >
> > Do something like:
> >
> > const iBase_ErrorType first_irel_error = iRel_NO_RELATION;
> > if (error_code >= first_irel_error)
> > return iRel_error_strings[error_code - first_irel_error];
> >
> >
> > ---------------------------------- 3 ---------------------------------
> >
> > The final suggestion is to use explicit fixed offsets. This is probably
> > most like what the those in the group who expressed a need for this
> > requirement expected. However, it also results in a fairly sparse array.
> > That makes the use of a single common function to for all
> > implementations that indexes into a single array more difficult.
> >
> > Move this enumeration from the iRel.h header to iBase.h (this should
> > probably be done anyway):
> >
> > enum IfaceType
> > {iRel_IBASE_IFACE = 0,
> > iRel_IGEOM_IFACE,
> > iRel_IMESH_IFACE,
> > iRel_IFIELD_IFACE,
> > iRel_IREL_IFACE};
> >
> > and change it to be the following:
> > enum iBase_IfaceType
> > {
> > iBase_IBASE_IFACE = 0,
> > iBase_IGEOM_IFACE,
> > iBase_IMESH_IFACE,
> > iBase_IMESHP_IFACE,
> > iBase_IFIELD_IFACE,
> > iBase_IREL_IFACE
> > };
> >
> > Now explicitly define the first interface-specific error code for each
> > interface to be 100 times the corresponding value in the IfaceType
> > enumeration.
> >
> > For example:
> >
> >
> > enum iBase_ErrorType {
> > iBase_SUCCESS = 100*iBase_IBASE_IFACE,
> > iBase_MESH_ALREADY_LOADED,
> > iBase_NO_MESH_DATA,
> > ...
> > iBase_FAILURE,
> >
> > iRel_NO_RELATION = 100*iBase_IREL_IFACE,
> > ...
> > iRel_NO_SETS,
> >
> > iMeshP_NO_PARTITION = 100*iBase_IMESHP_IFACE,
> > iMeshP_NO_PART,
> > };
> >
> >
> >
-- 
Mark C. Miller, Lawrence Livermore National Laboratory
================!!LLNL BUSINESS ONLY!!================
miller86 at llnl.gov      urgent: miller86 at pager.llnl.gov
T:8-6 (925)-423-5901    M/W/Th:7-12,2-7 (530)-753-8511



More information about the tstt-interface mailing list