[mod.computers.apollo] Handling of status codes -- the inside scoop

krowitz@mitlns.BITNET ("DAVID_M_KROWITZ") (08/28/86)

I recently had a informative talk with Robert Stanzel of Apollo
about the proper way to handle status codes on the Apollo (as a
result of one of my numerous UCR's). He sent me a copy of this memo
on the current method which is used to handle status codes which
I thought might be useful to other people who are trying to write
code which does fancy error-recovery so I have passed it along.

					-- David Krowitz


This is the memo I mentioned on the phone.  It's not directly relevant,
but mentions some of the recognized problems with our status handling.


On the use of "status_$t" OUT parameters in Streams
===================================================

A general philosophy concerning status codes is that clients (callers)
of subsystems (collection of procedures) should explicitly test ONLY for
statuses that are defined to be returned by the subsystem.  Further,
any statuses that are NOT defined by the subsystem are not guaranteed
to be stable across software releases.

For example, the following is OK:

    stream_$get_rec( id, ..., st );
    if ( status.subsys = stream_$subs ) and 
       ( status.all = stream_$end_of_file ) 
    then
        ...

and both of the following are NOT OK:

    stream_$get_rec( id, ..., st );
    if status.all = network_$xmit_failed then
        ...

            -----

    stream_$get_rec( id, ..., st );
    st.fail := false;
    if status.all = network_$xmit_failed then
        ...

because the Streams subsystem includes "stream_$end_of_file" among its
defined statuses but doesn't include "network_$xmit_failed".  

We recognize that documentation concerning status codes has been inadequate
and that exactly what statuses are defined by a subsystem has been
ill-defined.  In particular, for some subsystems, the defined statuses
are exactly those that appear in the subsystem's insert file; but for
other subsystems, the defined statuses are those PLUS some other,
ill-specified set.  For example, "gpr_$open_bitmap_file" can return
"gpr_$..." errors AND certain "name_$..." errors (e.g. "name_$not_found").

Another area of confusion has been the "fail" field in the "status_$t"
record.  The intent of is that if a returned status has the fail field
set to "true", then all bets are off -- the subsystem is reporting that
it got an unexpected error and the client is not allowed to make any
inferences about the nature of the failure.  Further, it is quite likely
that the returned status will change across releases.

As far as the Streams subsystem is concerned, our intent is that the
defined Streams return statuses are exactly those codes defined in
"streams.ins.pas".  Checking for non-"stream_$" return statuses from
"stream_$" calls is liable to produce unpredictable results across
releases.

Unfortunately, between sr8 and sr9, Streams' status behavior changed
some.  At sr8, "stream_$create" could return "name_$insufficient_rights"
if you tried to create a file in a directory for which you didn't have
"a" rights.  At sr9, "stream_$create" returns that same status code BUT
with the fail field set to "true".  The change was a side-effect of
Streams' being more careful to turn on the fail field in case it was
returning a non-Streams status.  The sr9 behavior is more correct than
the sr8 behavior, but the truly correct behavior is for "stream_$create"
to return "stream_$insufficient_rights" (with the fail field "false")
in this case since it is a perfectly normal and expected event that clients
might want to check for.

To get around this problem and to avoid user's needing to change their
code at the next release, callers of "stream_$create" should check the
returned status in the following way:

    stream_$create( ..., st );
    if ( ( st.subsys = stream_$subs ) and 
         ( st.code = stream_$insufficient_rights ) ) or
       ( st.all = 16#800E0014 )     { name_$insufficient_rights + "fail" }
    then
        ...

                
-------
------