Re: Request for Comment: Callable CRM114 Classifiers (libcrm114) --> OOBC

"Ger Hobbelt" <[email protected]>
Newsgroups gmane.mail.spam.crm114
Message-ID <[email protected]>
On Sat, Oct 4, 2008 at 10:11 PM, Eugene Crosser <[email protected]> wrote:
> Ger Hobbelt wrote:
>
>> Verbosity cannot be done through 'printf()' et al
> ...
>> --> error reporting hooks are required elements of the interface.
>
> Openssl style stack of error messages maybe?
>
> I'd suggest not to over-engineer debugging (/trace) interface for now. I
> have an impression that it could divert effort from more important things.


Nothing overengineered: the code is currently littered with stuff like this:

----------------------------
    if (internal_trace)
        fprintf(stderr, "executing a LEARN\n");
----------------------------

which I'd rather see turn into this:

----------------------------
    this->trace_callback(this, CRM_DBG_INTERNAL, "executing a LEARN\n");
----------------------------

so that all std I/O gets thrown to the wolves *outside* libcrm114 on a
/purpose/ basis (tracing, error reporting, etc.): you don't have
stdout/stderr in GUI and embedded environs anyway. The above would
then be completed with an interface bit a la:

----------------------------
typedef void crm_trace_callback_t(crm_config_t *obj, int level, const
char *fmt_msg, ...);
----------------------------
(which, incidentally, you can augment in GCC (without hurting
portability to other compilers) to tell GCC he should check this
callback interface as if it were a regular printf() style formatted
vararg, so you'd get nice warnings when screwing up your %d, %s, etc.
elements)


plus the extra hook in the crm class object:
----------------------------
typedef struct
{
    crm_trace_callback_t *trace_callback;
} crm_config_t;
----------------------------


and a /user defined/ function for a console app:
----------------------------
void my_crm_trace(crm_config_t *obj, int level, const char *fmt, ...)
{
    va_list args;
    my_own_custom_state_object_t *cfg;

    va_start(args, fmt);
    // get my own state object back (functor!)
    cfg = (my_own_custom_state_object_t *)obj->propagator;
    if ((cfg->internal_trace && level == CRM_DBG_INTERNAL)
        || (cfg->internal_trace && level == CRM_DBG_INTERNAL))
    {
        vfprintf(stderr, fmt, args);
    }
    va_end(args);
}
----------------------------
(Note: GUI app writers and embedded folk would copy&paste that, but
replace the vfprintf() with a GUI message or syslog() call or other.
Given this callback architecture, that's finally doable!)

plus 'registration' code somewhere at the start of your run:
----------------------------
crm_config_t *obj = ...;

....
obj->trace_callback = my_crm_trace;

...

// call libcrm114 methods:
result = obj->learn(.......);
....
/// and more using libcrm114...
--------------------------------


Which is nothing spectacular, just basic stuff for professional
software engineers. ;-)
And a direct replacement, no frills, for the current code (as shown at top).


Folks might recognize this as a Visitor Pattern (Gamma et al) done in
'C'. (Who said you couldn't do OO in 'C', eh? cfront did it. So can
we. ... I might be joking. ;-) )



EXTRA:
---------

The only thing in there that I'd like to see 'improved' regarding the
trace stuff is an 'improved' use of that 'level' argument there, which
can be easily done using a few platinum blonde macros, so that one can
filter messages not only at USER vs. INTERNAL, but per function/code
section within libcrm114: this would mean I'd introduce a 'code
section' ID code and mix that in with the 'severity level'
INTERNAL/USER/... so things would look like this in Bill's:

----------------------------
    this->trace_callback(this, CRM_TRACE_LEVEL(CRM_DBG_INTERNAL,
CRM_S_LEARN_SETUP), "executing a LEARN\n");
----------------------------

which would of course be shortened to (with help of a little wrap macro):
----------------------------
    this->trace_callback(this, CRM_TRACE_INTERNAL(CRM_S_LEARN_SETUP),
"executing a LEARN\n");
----------------------------


where you'd have definitions like these to go with that in your .h:
----------------------------
// trace 'severity' levels:
#define CRM_DBG_USER        1
#define CRM_DBG_INTERNAL  2

// code section ID's
...
#define CRM_S_LEARN_SETUP      42
#define CRM_S_VT_CORE             43
#define CRM_S_LEARN_FEATURES   44
#define CRM_S_LEARN_FINALIZE  45
...

// and here's the macro stuff to go with that:
#define CRM_TRACE_LEVEL(severity, section)  (((severity) << 24) ||
((section) & 0xFFF))
#define CRM_GET_TRACE_SECTION(code)  ((code) & 0xFFF)
#define CRM_GET_TRACE_SEVERITY(code)  ((code) >> 24)
----------------------------





Error Handlers in libcrm114:
-----------------------------------------

For error handlers, I had the idea to do exactly the same for them,
using an error_callback hook + VMS severity levels a la the above, but
your suggestion for using a OpenSSL-like error /stack/ is much nicer
and does not preclude that: right now, nonfatalerror()+fatalerror()s
get obscured by subsequent ones within the same statement, and using
an error /stack/ would resolve that. C# and other folks would
recognize that stuff as a stack trace / exception trace equivalent,
which is _very_ handy for diagnosing trouble.

However, I'd be OK with it if I had to 'do' that error stack 'on the
outside': what I want for bare metal minimum is an error/warning/fatal
abort-retry-panic callback like the above.


Besides, talking about resources: I'd rather [help to] create this
code then having to pick up some well meaning but sad code all over
again, you know. (And yes, I still have to start work on that
libcrm114 demo I was talking about last week, thanks to delays due to
spurious failures -- well, you've probably seen my trails on the
general and dev ML the last week; I moved off to dev because I felt it
was really getting out of hand for 'general')



-- 
Met vriendelijke groeten / Best regards,

Ger Hobbelt

--------------------------------------------------
web: http://www.hobbelt.com/
 http://www.hebbut.net/
mail: [email protected]
mobile: +31-6-11 120 978
--------------------------------------------------

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.