TOC PREV NEXT INDEX

Put your logo here!


4.7 ERROR HANDLING

4.7.1 Procedural Interface

A procedure shall always have the interface:

ccsCOMPL_STAT func1 (par1, par2,.....,&error)

The ccsCOMPL_STAT shall indicate if the function has succeeded or failed. The error structure of type ccsERROR contains the error context as reported by the function.

4.7.2 Error context handling

· In case of success, the error structure of type ccsERROR shall not be modified by the function.
· Only in case of failure the function should fill in, using the errAdd function, the error structure.
· The returned error number and message shall be clear enough to understand what happened and where it happened.
· Error messages are accessed by mean of an error mnemonic referencing a message. Both error mnemonic, and error message shall be defined in the error definition files. The errEditor tool facilitates these definitions.
· Since every layer of software adds its own error context to the error stack, programmers shall take care to avoid redundant error messages in the different layers.

4.7.3 Repeated errors

Particular attention should be brought to avoid flooding the error log file with repeated error messages. Tasks and procedures should be programmed to recognize these situations, and react to them.

A possible action consists in logging with a reduced frequency that the same error occurred so many times in a given time interval or reducing the log rate with time as long as the error remains.

A counter would be needed to keep track during which number of the loop the log should or should not be done, see also EXAMPLE 7.

Another possibility is to use a counter in the fast loop and log the error in a slow background loop using the information of the counter.

Background tasks should also be programmed to stop looping on the same error.

LCC provides a filtering mechanism of error logs and of events. It is possible to configure lcc in such a way that if the same error occurs during a defined time interval, then it is discarded and at the end of the time interval the number of discarded error logs are logged. The same is possible for events. See [2] for more details.

4.7.4 Programming: Rules and Examples

This section contains general remarks on the use of the error system routines.

· Refer to an error number by its mnemonic
· Refer to the module identifier through a `#define' statement.
· Use the pre-compiler symbol __FILE__ to indicate for the location parameter in errAdd() and errSysAdd().
· Parameter `format' in errAdd and errSysAdd is not used, so use an empty string ("") instead. It is there for compatibility with LCC.
· Use the defined symbols modRTAP, modUNIX and modVXWORKS to identify parameter sysModule of routine errSysAdd to identify the RTAP, UNIX or VxWorks systems respectively.

This section contain examples of use of the error system routines with the following conventions:

· <mod> represents a generic name for a module
· Only the code related to the handling of errors is shown
· Comments between the lines of the code are shown in italic

EXAMPLE 1 : Shows which are the error functions to be used in the application's main and for which purposes.



#include "db.h"
#include "log.h"
#include "err.h"

int main (int argc, char *argv[])
{

ccsInit(argv[0],0,NULL,NULL,&error) /* This routine contains a call to errResetStack() */

...

if ( <mod>Funct1( ... , &error) == FAILURE )
{

The error cannot be recovered and there is no need to notify the user.

The errCloseStack() functions logs the whole error stack and then resets the error structure.


errCloseStack(&error);
}

if ( <mod>Funct1( ... , &error) == FAILURE )
{

The error cannot be recovered and the user should be notified.

The application waits the user's acknowledgment before continuing.

The errDisplay() functions pops up the error dialog box showing the description of the last error in the stack


errDisplay(&error,ccsTRUE);
}

if ( <mod>Funct1( ... , &error) == FAILURE )
{
if (error.errorNumber == <mod>ERR_xxx)
{
errCloseStack(&error); /* Error cannot be recovered */
}
else if (error.errorNumber == <mod>ERR_yyy)
{

The error can be recovered : the errResetStack function clears the error structure.


errResetStack(&error);
insert code to recover the error ...; /* Error can be recovered */
}
}

ccsExit(&error);
exit(2);

}

EXAMPLE 2 : Shows how to process error conditions in a function : routine <mod>Funct1 calls another routine of the same module.


ccsCOMPL_STAT ccsFunct1 (.... , ccsERROR *error);
{

if (ccsFunct2(... ,error) == FAILURE)
{
if (error can be recovered)
{

The error can be recovered : the errResetStack() function clears the error structure.


errResetStack(error);
}
else
{

The error cannot be recovered and the error must be returned back to the calling functions.

The errAdd() function sets the error context to the new error condition and adds the current error to the error stack.


errAdd(error,ccsMSG,ccsERR_MSG_SEND,__FILE__,"",p2);
return(FAILURE);
}
}

return(SUCCESS);
}




EXAMPLE 3 : Shows how to process error conditions generated by a UNIX function.

Routine <mod>Funct2 makes a call to a UNIX routine and to a CCS routine. The errors generated by the UNIX routine is handled by errSysAdd which logs the generated UNIX error and sets the returned error structure error context to the associated error of module <mod>


ccsCOMPL_STAT <mod>Funct2(... , ccsERROR *error)
{

...

if ((fileHandle = open(filename,O_RDWR)) == -1)
{

The UNIX error is stored in the stack and the error context is set to the description given by the error mnemonic specified in the errSysAdd() function.


errSysAdd(error,<mod>,<mod>ERR_OPEN_FILE,__FILE__,"", modUNIX,filename);
return(FAILURE);
}

if (dbReadSymbolic(...) == FAILURE)
{
errAdd(error,<mod>,<mod>ERR_READ,__FILE__,"",pointName);
return(FAILURE);
}

...

return(SUCCESS);
}

EXAMPLE 4 : Shows how to process error conditions generated by a Rtap function.


Routine dbReadSymbolic calls a RTAP routine. The errors generated by the RTAP routine are handled by errSysAdd which logs the generated RTAP error and sets the returned error structure error context to the CCS error.


ccsCOMPL_STAT dbReadSymbolic( ... , ccsERROR *error)
{
vltINT16 ccsErrNumber;

...

if (rtReadDatabase(dbHandle,&readInfo) == FAILURE)
{
*actual = 0;
*recordCnt = 0;

errConvRtapErr(&ccsErrNumber); /* Convert the RTAP error number */
/* into CCS error number */

switch(ccsErrNumber)
{
case ccsERR_DB_INV_POINT:
case ccsERR_DB_INV_NAME:
case ccsERR_DB_INV_ALIAS:
errSysAdd(error,ccsDB,ccsERR_DB_INV_NAME,__FILE__,"", modRTAP,fullName);
break;

default:
errSysAdd(error,ccsDB,ccsERR_DB_READ,__FILE__,"", modRTAP,fullName);
break;
}

return(FAILURE);
}

...

return(SUCCESS);
}

EXAMPLE 5 : Shows how to propagate an error reply to the upper layers by using the built-in features of msgParseMsg().

ccsCOMPL_STAT <mod>Funct3 ( ... , ccsERROR *error)
{
/* send, for example, a message to an LCU */
/* Wait for the message reply */

if (msgRecvMsg(... , error) == FAILURE)
{
/* Process error condition ...*/
return(FAILURE);
}

The name of the local error structure and the name of the structure containing the error reply is the same.

In this case the routine errParseMsg() automatically merges the two stacks.


if (msgParseMsg(... , error, error) == FAILURE)
{
/* Process error condition ... */
return(FAILURE);
}

if (msgType == msgTYPE_ERROR_REPLY) {
{

Parameter `error' now containes the merging of local error structure and the reply error.

The errAdd() function sets the error context to the new error condition and adds the current error to the error stack.


errAdd(error,ccsMSG,ccsERR_MSG_SEND,__FILE__,"",p2);
return(FAILURE);
}
else
{
/* Process other cases ... */
}

return(SUCCESS);
}


EXAMPLE 6 : Shows how to merge two error stacks.



ccsCOMPL_STAT <mod>Funct3 ( ... , ccsERROR *error)
{
ccsERROR err1
errResetStack(&err1);

if (<mod>Funct4(... , &err1) == FAILURE)
{
errMergeStack(error,&err1,errBOTTOM);

The errAdd() function sets the error context to the new error condition and adds the current error to the error stack.

errAdd(error,<mod>,<mod>ERR_XXX,,__FILE__,"",...);
return(FAILURE);
}

return(SUCCESS);
}


EXAMPLE 7 : Shows a simple way how to avoid too may logs in a fast loop.

The loop recovers the error.



ccsCOMPL_STAT <mod>Funct3 ( ... , ccsERROR *error)
{
ccsERROR err1
errResetStack(&err1);
static int errCount = 0;
int i;

for (i=0;i<MAX_COUNT;i++)
{
if (<mod>Funct4(... , &err1) == FAILURE)
{
if (errCount == 0)
{
errAdd(&err1,<mod>,<mod>ERR_XXX,,__FILE__,"",...);
errCloseStack(&err1);
}
else
{
errCount++;
}
if (errCount >= MAX_ERR_COUNT)
{
errCount = 0;
}
)
else
{
errCount = 0;
}
}

return(SUCCESS);
}


4.7.5 General Remarks

Error Mnemonics

CCS already provides detailed information on the error conditions regarding operations such as: send a message, access the database, etc..

Therefore applications built on top of CCS should use error mnemonics addressing the functionality of the application rather than logging too detailed error description.

Here is an example of error stack generated by CCS showing that the first logs of the stack contain the detailed information on the reason why an operation failed. (For clarity only the text of the logs are reported).

rtE_DB_INV_POINT: Invalid Point in address REASON> Unresolved relative point name ``point1''

rtE_DB_INV_POINT: Invalid Point in address REASON> input::point1.attrName

rtE_DB_INV_POINT: Invalid Point in address REASON> :point1.attrName

ccsERR_DB_INV_NAME: Illegal DB name ( :point1.attrName)

ccsERR_SCAN_NEGOTIATION : Negotiation failed.

4.8 LOGGING

Log messages should be predefined, just like error messages, into log definition files, and accessed later on from within applications by reference to their identifier.

Whenever possible, the log messages shall use the FITS keywords defined in the Data Interface Control Document[28]. In such a case, the log type in the <mod>_LOGS file shall be F for FITS.

In addition the 4 categories of Logs defined in this document shall be identified in the logging system through their logId

· Operations log (logId in the range 101-150)
· Configuration log (logId in the range 151-200)
· Conditions log (logId in the range 201-230)
· Reduction log (logId in the range 231-255)

The use of FITS keywords is mandatory for all relevant hardware related actions.

Particular attention shall be brought to avoid flooding the log files with repeated logs. For example, only start and stop of cyclical activities should be logged.



Quadralay Corporation
http://www.webworks.com
Voice: (512) 719-3399
Fax: (512) 719-3606
sales@webworks.com
TOC PREV NEXT INDEX