Report problems to ATLAS LXR Team (with time and IP address indicated)

The LXR Cross Referencer

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Architecture: linux ]
Version: head ] [ nightly ] [ GaudiDev ]
  Links to LXR source navigation pages for stable releases [ 12.*.* ]   [ 13.*.* ]   [ 14.*.* ] 

001 From pcanal@fndaub  Thu Jul 10 13:02:56 1997
002 Received: from FNAL.FNAL.Gov by fncrd8.fnal.gov via ESMTP (950413.SGI.8.6.12/911001.SGI)
003         for <mf@fncrd8.fnal.gov> id MAA09837; Thu, 10 Jul 1997 12:58:14 -0500
004 Received: from fndaub.fnal.gov ("port 1913"@fndaub.fnal.gov)
005  by FNAL.FNAL.GOV (PMDF V5.0-8 #3998) id <01IL2MCCY2N6000NXX@FNAL.FNAL.GOV> for
006  mf@FNAL.FNAL.GOV; Thu, 10 Jul 1997 12:58:14 -0600
007 Received: from localhost by fndaub.fnal.gov via SMTP
008  (951211.SGI.8.6.12.PATCH1042/911001.SGI) id MAA25542; Thu,
009  10 Jul 1997 12:58:13 -0500
010 Date: Thu, 10 Jul 1997 12:58:13 -0500 (CDT)
011 From: Philippe Canal <pcanal@fndaub>
012 Subject: exception design
013 To: pcanal@fndaub, mf@FNAL.GOV
014 Message-id: <199707101758.MAA25542@fndaub.fnal.gov>
015 MIME-version: 1.0
016 X-Mailer: exmh version 1.6.6 3/24/96
017 Content-type: text/plain; charset=us-ascii
018 Content-transfer-encoding: 7BIT
019 Status: RO
020 
021 
022 
023                 ZOOM Exception Mechanism Design
024                 -------------------------------
025 
026 The Zoom exception mechanism is intended to be the tools used by ZOOM modules
027 to handle exceptions in a useful way and provide the user with interfaces to
028 control how to react to problems.  It is not (at this time) intended to be a
029 mechanism for the user to hook into to define his own exceptions, although that
030 may come later.  Frankly, successful implementation and use by ZOOM modules
031 will
032 be necessary to sell this structure to our users as potentially useful, anyway.
033 
034 We need the mechanism "now" because we are trying to deliver at least two
035 packages which will have to be re-instrumented when the mechanism is finally
036 adopted.
037 
038 This is not a "signal handler" mechanism, which could be used to establish
039 behavior for segment violations, arthmetic exceptions, and so forth.  It
040 would be nice to have this but C++ does not provide generic support for
041 those activities.  A **later** possibility will be to provide this support for
042 POSIX-compliant operating systems, and coordinate it with the exception
043 mechanism.
044 
045 
046 We need to be able to cope with the following realities:
047 - --------------------------------------------------------
048 
049 1 - Users will not, in every case, imbed calls into a try block.
050 
051 2 - Frameworks will incorporate code from multiple users and in some
052     circumstances cannot afford to abort the entire job if some rare path
053     in one user's code blows up.  To the extent we can help with this, we must.
054 
055 3 - Framework creators CAN be expected to imbed portions in try blocks, or
056     set up behaviors for various exceptions, assuming we give them the
057 necessary
058     tools.
059 
060     In the remainder of this document, the "user" who sets things up is assmued
061     to be such a framework manager.
062 
063 4 - There is need for coordinated logging and related behavior.
064 
065 
066 To be able to satisfy this, the goal is to allow:
067 - -------------------------------------------------
068 
069 1 - The user should be able to specify, for a given sort of exception, whether
070     she wants to:
071 
072     a - Throw the exception via the C++ mechanism, thus aborting unless she
073         in the framework or a lower-level user responsible catchs the problem.
074 
075     b - Invoke a user-written handler when the exception occurs, which may
076         itself determine it is necessary to throw the exception.
077 
078     c - Ignore the exception RETURNING TO THE SPOT IN THE ZOOM MODULE
079         THAT DETECTED THE PROBLEM.  This can happen with or without a handler
080         being invoked.  Typically, the module will then return some approriate
081         pseudo-value to the user.
082 
083 2 - In cases where exceptions are to be handled or ignored, there should be
084     a well-known way to get information about the existance of a problem,
085     analogous to the errno mechanism in C.
086 
087 3 - Explanatory strings should be associated with the problem at the point
088     of origin.
089 
090 4 - The exceptions are organized in a hierarchical manner, which uniformly
091     applies one simple category philosophy that the users can understand,
092     across the various ZOOM packages.
093 
094 
095 With this in mind, our mechanism has the following structure:
096 - -------------------------------------------------------------
097 
098 
099 1 - Upon detecting a problem for which it would like to (potential) throw an
100     exception, the module code will instead invoke the ZMthrow macro.
101 
102 2 - ZMthrow takes as its argument a ZMexception object constructor, which
103     has as ITS first argument a const char*.  The intent is for the
104 ZMexception
105     object actually do be derived from the base ZMexception class, and for
106     the char* first argument to contain an explanatory message.  Particular
107     ZMexceptions can also have construction forms taking a second string, or
108     whatever.
109     For example,
110         ZMthrow ( HepTuple::ZMxCapture( "Column not found", name ) );
111 
112 3 - The ZMthrow macro appends __LINE__, __FILE__ and calls ZMexcept.
113 
114 4 - ZMexcept has signature
115 
116         template<class Exception> void ZMexcept ( Exception x, int line,char file[]);
117 
118     It does the following:
119 
120     a - Places a copy of the exception object x into a circular buffer
121 ZMerrno.
122         More about ZMerrno later.
123 
124     b - Determines for this exception what sort of logging is enabled, and logs
125         it.  Note that derived exceptions must modify the general logging
126         method if they wish to include information beyond the message and
127         file/line/time stamp.
128 
129     c - Determines whether the exception needs to be ignored, if so return
130 
131     d- Determines whether the exception a handler has been established, and
132         if so invokes it.
133         The handler will be passed the exception object, and can be set up to
134         also take the line/file/time arguments.  The handler returns a bool
135         which if true will say to throw the exception.
136 
137     d - Determines (after any handler has been invoked) whether to ignore the
138         exception.  It will do either
139                 throw x;
140         or
141                 return;
142 
143 5 - ZMerrno is analogous to the C/Unix errno mechanism, but allows viewing a
144     history of the last N problems detected.  We anticipate using it like
145 errno,
146     via exception id, but we copies of place the whole exception object onto
147     ZMerrno to provide more info if desired.  The interface is:
148 
149     a - ((creation somehow, specifying N))
150 
151     b - ZMerrno.write (ZMexcption* x);    // copy an exception onto ZMerrno
152 
153     The user would not use a and b but would use:
154 
155     c - string ZMerrno.read ();       // read the last id value on ZMerrno
156         string ZMerrno.read (int k);  // read the last-but-k id value on ZMerrno
157 
158     d - void ZMerrno.clear();      // put a zero (indicating no current error)
159                                    // on ZMerrno.
160 
161     e - void ZMerrno.pop();        // remove an entry setting the top to the
162                                    // previous entry.  For instance, if you
163                                    // have a loop in which some known ignorable
164                                    // happening places a value on ZMerrno, you
165                                    // can pop each one so as not to wipe out
166                                    // the history for others.
167 
168     f - ZMexception* ZMerrno.get()      // Return pointer to the last or
169         ZMexception* ZMerrno.get(int k) // last-but-k exception on ZMerrno.
170                                         // Allows perusal of things like the
171                                         // message and the logger and handler
172                                         // used when the exception was
173                                         // encountered.
174 
175     Thus after the start, or after ZMerrno.clear(), the user can always find
176     out whether any ignored exceptions had occured by doing
177         if (!ZMerrno.read().empty()) { ... then something has happened }
178 
179     If we later incorporate signal handling, this ZMerrno stack is where the
180     user can find out whether he has had his arithmetic error since the last
181     clear.
182 
183     ZMerrno is pronounced "oops."
184 
185 6 - The id empty string indicates no error.  The id is a string representing
186     the unique name of the exception class.
187 
188     Each ZMexception object class has its own error id which is established
189     (hardwired) at construction.
190 
191 7 - When a ZMexcept is thrown it does a ZMerrno.write(x).  Thus
192     ZMerrno tracks these exceptions even if they are explicitly thrown and
193     caught by the user outside the ZMthrow/ZMexception mechanism.
194 
195 8 - Logging is discussed separately.
196 
197 
198 The user interface to control exception behavior is:
199 - -----------------------------------------------------
200 
201 By the way, this is an interface for the framework manager to use; the lower
202 level user would generally never establish handlers or ignores, and would
203 only use the ZMerrno.read() and .clear().
204 
205 1 - To establish a handler for a particular exception type, say for
206     ZMexceptCapture:
207 
208         HepTuple::ZMxCapture.setHandler ( new ZMhandler(myhandler) );
209 
210         The handlerName string gives a convenient way to tell about the
211         handling in log messages ("... was handled by mySuperHandler").
212 
213     The signature of the handler must be:
214         bool myhandler ( ZMexception *x );
215 
216     We will have a ZMhandler class to contain that and the handlerName.
217 
218     Note that the handler has access to the fields of x including for all
219     ZMexception objects:
220                 char* message;
221                 int line;
222                 char* sourceFileName;
223                 int serialNumber;
224                 ZMhandler* handler;
225                 ZMlogger* logger;
226                 // and class-wide data:
227                 static int id;
228                 static char* messagePreamble;
229                 static int count;
230     and, for particular derived ZMexception objects, any secondary messages
231     or other information provided to the constructor and kept in the object.
232 
233     The handler should return false to ignore the exception and return to
234     the user code (from ZMexcept), or true to throw the exception after
235     the handler returns.  The user can also throw an exception explicitly
236     in the handler.
237 
238 2 - You may establish a handler for an entire base class, which applies to any
239     ZMexceptions derived from in that class for which no specific handler is
240     established.  For example, HepTuple::ZMxNewColumn is derived
241     from HepTuple::ZMxGeneral so
242 
243         HepTuple::ZMxGeneral.setHandler ( myDefaultHandler );
244 
245     will apply to HepTuple::ZMxNewColumn if that is ever ZMthrown.
246 
247 3 - Note that if a handler is established for a subclass it takes precedence
248     over that for the base class.  If you instead wish to call the base class
249     handler after executing the specific handler, you must invoke it
250 explicitly.
251     Only if no handler has been established will the exception check for and
252     invoke a handler in its base class automatically.
253 
254 4 - Four default handler types are provides:
255        ZMignore
256        ZMthrow
257        ZMparentHandler
258        ZMingnoreCount
259     ZMparentHandler is the default handler.  The default for the top most
260     exception class is ZMparentHandler
261 
262 4a- At times you may wish to prevent the calling of the base class handler yet
263     have no need for explicit handling.  In which case you would set the
264 handler
265     for this class to ZMignore or ZMthrow.
266 
267 4b- The user can tell the system to whether or not to ignore an unhandled
268     ZMexception:
269 
270         HepTuple::ZMxCapture.ignore()
271         HepTuple::ZMxCapture.dontIgnore()
272         HepTuple::ZMxCapture.default()
273 
274     The default is don't ignore -- meaning throw the exception unless a handler
275     is invoked and comes back false.  The same rules for inheritance apply as
276     in the handler case:  If you haven't specifically said anything about a
277     subclass, then what you have said about the parent class will apply.  Thus
278     calling dontIgnore() is NOT the same as not calling ignore().  In analogy
279     with handling, we need a way to say "pretend I never said ignore or dont;
280     use the parent class decision".  This is:
281 
282         HepTuple::ZMxCapture.setHandler(new ZMparentHandler)
283 
284 5 - Sometimes you may want to ignore an exception the first N times and then
285     react differently.  The handler can have a static count variable to
286     implement this behavior.  Alternatively, there is a call to establish this
287     behavior even if no handler is used:
288         HepTuple::ZMxCapture.setHandler(new ZMignoreCount(N))
289 
290 
291 
292 
293 The part of the interface seen by non-framework-manager users is simpler:
294 - --------------------------------------------------------------------------
295 
296 1 - The ZMerrno methods may be used to see if (ignored) exceptions have
297     happened.  Typically, the user used to Unix exceptions would call
298     ZNerrno.read() and maybe ZMerrno.clear().
299 
300 2 - The ordinary user can try, and catch, these ZMexceptions.  We ask that
301     usrs not throw ZMexceptions that the ZOOM modules throw.  Later we may
302     extend support to include user-defined subclasses of ZMexception.
303 
304 3 - When an exception occurs and is not ignored, the user will know the
305     message given for the exception, as well as the and line number where the
306     ZMthrow macro was invoked.  This is inside ZOOM code.  By doing
307     debug core <usersource> the user can get a traceback into the user
308     routines to find which line of his code encountered the problem.
309 
310 4 - The status of what was set up for ignoring and handling may be probed, so
311     temporary control behavior can be set and then put back to what it was:
312 
313         handler() returns the established handler.
314         logger()  returns the established logger.
315                                                                 
316 
317 Logging is handled as follows:
318 - ------------------------------
319 
320 0 - The connection between a class of ZMexceptions and logging that is through
321 a
322     ZMlogger.  The (framework) user may create her own logger but typically
323 will
324     use our provided class ZMlog, which has is a ZMlogger and has a
325 constructor
326     taking a file name.  Any actions taken by the logger we describe below
327     will refer to how ZMlog behaves.
328 
329 1 - Every individual ZMexception object can have a method for creating
330     (from the other arguments aside from messge) a string to put into a log.
331     (Of course, it may be inherited from its base class.)  But the message
332     as well as time, line, id, and so forth is not to be handled by each;
333     instead, ZMthrow handles this.
334 
335     The method to create the string is logMessage().
336 
337     ZMexcept will at various points call the logThis() method of the
338 established
339     logger when it wants to log information.
340 
341 1a- The user assgns a ZMlogger to an exception class by
342         ZMexception::setLogger(ZMlogger*).
343     For example,
344 
345         ZMlog* mylog ("logfilename.txt");
346         ZMxCapture::setLogger(mylog);
347 
348     The pointer returned should be checked.  In the case of ZMlog, it can be
349     NULL for two reasons:  The file cannot be opened for append, or the file
350     is already open for some other purpose.  (If it is already opened for
351     logging, that is fine; this logger will also cause logging of messages
352     there).
353 
354 2 - ZMexception has a method setLogger(ZMlogger) which will open a log using
355     that logger for that type of exception.
356 
357     This will establish this logger to be used for exceptions of this class.
358     In the case of ZMlog, that means it will establish the file which was
359     provided when the logger was constructed, as a logging point for
360 exceptions
361     of this class.  (This is class static information.)
362 
363 2a- The ZMlog object will log to a file:  its constructor will open a log to
364     that file for that type of exception.
365 
366     A user can provide a different logger which, for example, ties into the
367     CDF or D0 general logging mechanism instead of writing to a file.
368 
369 3 - If no logging is specified for a class the file defaults to the base class.
370     Thus HepTuple::ZMxCapture might log to the file for HepTuple::ZMxGeneral,
371     or if no logging is established there, for ZMexception.  It is possible
372 (the
373     default) that no logging is established anywhere.
374 
375 4 - You may log to multiple files; each ZMexception (sub)class has a class
376     static linked list of log files.
377 
378 5 - Aside from single files, you can also establish a "rolling log" pair of
379     files:
380         ZMrollingLog* mylog (const char filename1[], const char filename2[],
381                                 int n );
382         bool ZMexception::setLogger(mylog);
383 
384     The way this works is that the first file is opened (still for append),
385     and up to n exception instances are logged into it, at which point
386     it is closed, renamed to the second file, and re-created (empty) for
387     more logging.  A script can detect when this has happended and archive
388     the second file if desired.
389 
390 6 - If you wish to cease logging a particular exception type in general or
391     to a particular log file, you may:
392         HepTuple::ZMxCapture.stopLog();
393     If no exceptions are logging to a particular log anymore, that file will
394     be closed.
395 
396 7 - To be able to temporarily modify logging behavior for an exception, you
397     may call
398        ZMlog* oldLog = logger(),
399     and later call
400        setLogger(oldLog)
401 
402 
403 The following usage recommendations pertain to writers of ZOOM code:
404 - --------------------------------------------------------------------
405 
406 As shown in the examples, place your definitions of the exception objects
407 inside the class definition for the class.  That way, methods within this
408 class can simply call the shorter name -- ZMxCapture rather than
409 ZMxHepTupleCapture.
410 
411 Don't create too many types of exceptions.  The error codes appearing on the
412 ZMerrno stack are defined per each type, but unless you envision the user
413 needing to AUTOMATICALLY distinguish between one problem and another in
414 the same submodule via ZMerrno, don't define them as two separate exception
415 types.
416 
417 In cases where the user interface promises a routine will not throw an
418 exception (but might return false if something goes awry) the ZOOM code
419 itself should enclose any possible ZMthrows in try blocks, to catch the problem
420 in case the user has not specified ignoring the exception.
421 
422 Note that the argument to the constructor of the ZMexception in ZMthrow can
423 (and often will) be a string formed by concatenating some fixed informatory
424 message with some variable information, as in
425         ZMthrow ( ZMxCapture( "Column not found", name ) );
426 To do this, one should have a constructor for that sort of ZMexceptoin object
427 with the extra argument in its signature, as well as the one with just a
428 const char[].  One could alternatively do someting like
429         ZMthrow ( ZMxCapture( strcat("Column not found", name) ) );
430 but if you use the exception in more than one place, the recommended second
431 constructor is less work.
432 
433 When returning a pointer, in circumstances where things have gone wrong, the
434 usual action is to return a null pointer.  In many cases this is appropriate,
435 especially if the user interface defines it.  However, the sloppy user might
436 cause an (uncatchable) bus error if he does not check for null pointer.
437 Consider returning a pointer to a braindead object (whose methods throw
438 ignorable ZMthrows) rather than NULL -- then the job might not abort.
439 
440 
441 Documentation should be layered:
442 
443 1 - How the user interacts with the mechanism (VERY brief).
444 
445 2 - How the framework manager user interacts (settting up handlers, logs,
446     ignores).
447 
448 3 - How to define a ZMx class.
449 
450 4 - Usage recommendations for writers of ZOOM code.
451 
452 

source navigation ] diff markup ] identifier search ] general search ]

Due to the LXR bug, the updates fail sometimes to remove references to deleted files. The Saturday's full rebuilds fix these problems
This page was automatically generated by the LXR engine. Valid HTML 4.01!