From 5415d3924934fc19b33e3b325141bb32c18fedfe Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Tue, 20 Jan 1998 21:42:46 +0000 Subject: [PATCH] New errlog facility. Replaces old epicsPrintf stuff --- src/libCom/Makefile.Host | 8 +- src/libCom/Makefile.Vx | 8 +- src/libCom/epicsPrint.h | 37 +-- src/libCom/errMdef.h | 15 +- src/libCom/errlog.h | 95 +++++++ src/libCom/errlog.html | 152 +++++++++++ src/libCom/errlogUNIX.c | 174 ++++++++++++ src/libCom/errlogVX.c | 479 ++++++++++++++++++++++++++++++++++ src/libCom/error/epicsPrint.h | 37 +-- src/libCom/error/errMdef.h | 15 +- src/libCom/error/errlog.c | 479 ++++++++++++++++++++++++++++++++++ src/libCom/error/errlog.h | 95 +++++++ 12 files changed, 1502 insertions(+), 92 deletions(-) create mode 100644 src/libCom/errlog.h create mode 100644 src/libCom/errlog.html create mode 100644 src/libCom/errlogUNIX.c create mode 100644 src/libCom/errlogVX.c create mode 100644 src/libCom/error/errlog.c create mode 100644 src/libCom/error/errlog.h diff --git a/src/libCom/Makefile.Host b/src/libCom/Makefile.Host index f6bd85f41..b972adc6f 100644 --- a/src/libCom/Makefile.Host +++ b/src/libCom/Makefile.Host @@ -14,6 +14,7 @@ INC += cvtFast.h INC += ellLib.h INC += envDefs.h INC += epicsAssert.h +INC += errlog.h INC += epicsPrint.h INC += errMdef.h INC += error.h @@ -28,12 +29,12 @@ INC += fdManager.h INC += osiTime.h INC += osiTimer.h INC += macLib.h -INC += impLib.h INC += sigPipeIgnore.h INC += dbmf.h INC += ipAddrToA.h INC += epicsString.h INC += truncateFile.h +INC += adjustment.h # For WIN32 we supply getopt as part of libCom: INC_WIN32 := getopt.h @@ -50,7 +51,7 @@ LIBSRCS += cvtFast.c LIBSRCS += ellLib.c LIBSRCS += envSubr.c LIBSRCS += envData.c -LIBSRCS += errPrintfUNIX.c +LIBSRCS += errlogUNIX.c LIBSRCS += errSymLib.c LIBSRCS += errSymTbl.c LIBSRCS += fdmgr.c @@ -62,7 +63,6 @@ LIBSRCS += postfix.c LIBSRCS += realpath.c LIBSRCS += tsSubr.c LIBSRCS += assertUNIX.c -LIBSRCS += impLib.c LIBSRCS += macCore.c LIBSRCS += macUtil.c LIBSRCS += sigPipeIgnore.c @@ -71,6 +71,7 @@ LIBSRCS += ipAddrToA.c LIBSRCS += epicsString.c LIBSRCS += truncateFile.c LIBSRCS += aToIPAddr.c +LIBSRCS += adjustment.c # # if CPLUSPLUS isnt empty then include C++ src codes @@ -103,7 +104,6 @@ PROD_LIBS = Com #TESTPROD=tsTest #TESTPROD=envtest #TESTPROD=osiTimeTest fdManagerTest -PROD = impExpand MAN3 = gpHash.3 freeList.3 diff --git a/src/libCom/Makefile.Vx b/src/libCom/Makefile.Vx index 2346eef94..475fb0a7c 100644 --- a/src/libCom/Makefile.Vx +++ b/src/libCom/Makefile.Vx @@ -21,7 +21,7 @@ SRCS.c += ../tsSubr.c SRCS.c += ../pal.c SRCS.c += ../paldef.c SRCS.c += errSymTbl.c -SRCS.c += ../errPrintfVX.c +SRCS.c += ../errlogVX.c SRCS.c += ../assertVX.c SRCS.c += ../macCore.c SRCS.c += ../macUtil.c @@ -29,10 +29,10 @@ SRCS.c += ../macUtil.c #SRCS.c += ../os/vxWorks/osdTime.cc SRCS.c += ../os/vxWorks/ipAddrToA.c SRCS.c += ../os/vxWorks/sigPipeIgnore.c -SRCS.c += ../impLib.c SRCS.c += ../dbmf.c SRCS.c += ../epicsString.c SRCS.c += ../aToIPAddr.c +SRCS.c += ../adjustment.c LIBOBJS += calcPerform.o LIBOBJS += cvtFast.o @@ -49,7 +49,7 @@ LIBOBJS += gpHashLib.o LIBOBJS += freeListLib.o LIBOBJS += pal.o LIBOBJS += paldef.o -LIBOBJS += errPrintfVX.o +LIBOBJS += errlogVX.o LIBOBJS += assertVX.o LIBOBJS += macCore.o LIBOBJS += macUtil.o @@ -57,10 +57,10 @@ LIBOBJS += macUtil.o #LIBOBJS += osdTime.o LIBOBJS += ipAddrToA.o LIBOBJS += sigPipeIgnore.o -LIBOBJS += impLib.o LIBOBJS += dbmf.o LIBOBJS += epicsString.o LIBOBJS += aToIPAddr.o +LIBOBJS += adjustment.o LIBNAME = libCom diff --git a/src/libCom/epicsPrint.h b/src/libCom/epicsPrint.h index 01f77aa3b..3f66530ce 100644 --- a/src/libCom/epicsPrint.h +++ b/src/libCom/epicsPrint.h @@ -1,34 +1,9 @@ +/*epicsPrint.h */ -#ifdef __cplusplus -extern "C" { -#define epicsPrintUseProtoANSI -#endif +/*This is now obsolete. Remlaced by errlog.h */ +#ifndef INCepicsPrintH +#define INCepicsPrintH -#ifdef __STDC__ -#ifndef epicsPrintUseProtoANSI -#define epicsPrintUseProtoANSI -#endif -#endif - -#ifdef vxWorks -# ifdef epicsPrintUseProtoANSI -# include - int epicsPrintf(const char *pFormat, ...); - int epicsVprintf (const char *pFormat, va_list pvar); - int iocLogVPrintf(const char *pFormat, va_list pvar); - int iocLogPrintf(const char *pFormat, ...); -# else /* not epicsPrintUseProtoANSI */ - int epicsPrintf(); - int epicsVprintf (); - int iocLogVPrintf(); - int iocLogPrintf(); -# endif /* ifdef epicsPrintUseProtoANSI */ -#else /* not vxWorks */ -# define epicsPrintf printf -# define epicsVprintf vprintf -#endif /* ifdef vxWorks */ - -#ifdef __cplusplus -} -#endif +#include "errlog.h" +#endif /*INCepicsPrintH*/ diff --git a/src/libCom/errMdef.h b/src/libCom/errMdef.h index 2d565513d..901f25b7c 100644 --- a/src/libCom/errMdef.h +++ b/src/libCom/errMdef.h @@ -61,6 +61,10 @@ extern "C" { #include "ellLib.h" #include "shareLib.h" +/*The following is only included because before 3.13.0beta12 errMessage */ +/*and errPrintf were defined here */ +#include "errlog.h" + #define RTN_SUCCESS(STATUS) ((STATUS)==0) #define M_dbAccess (501 <<16) /*Database Access Routines */ @@ -88,13 +92,6 @@ extern "C" { #define M_bucket (525 <<16) /*Bucket Hash*/ #define M_gddFuncTbl (526 <<16) /*gdd jump table*/ -/* - * redefine errMessage with a macro so we can print - * the file and line number - */ -#define errMessage(S, PM) \ - errPrintf(S, __FILE__, __LINE__, PM) - #ifdef errMDefUseProtoANSI epicsShareFunc int epicsShareAPI errSymFind(long status, char *name); epicsShareFunc int epicsShareAPI UnixSymFind(long status, char *name, long *value); @@ -103,11 +100,8 @@ epicsShareFunc void epicsShareAPI errSymTest(unsigned short modnum, unsigned sho epicsShareFunc void epicsShareAPI errSymTestPrint(long errNum); epicsShareFunc int epicsShareAPI errSymBld(); epicsShareFunc int epicsShareAPI errSymbolAdd (long errNum,char *name); -epicsShareFunc void epicsShareAPI errPrintf(long status, const char *pFileName, - int lineno, const char *pformat, ...); epicsShareFunc void epicsShareAPI errSymDump(); epicsShareFunc void epicsShareAPI tstErrSymFind(); -epicsShareFunc void epicsShareAPI errInit(void); #else /* errMDefUseProtoANSI */ @@ -118,7 +112,6 @@ epicsShareFunc int epicsShareAPI ModSymFind(); epicsShareFunc void epicsShareAPI errSymTestPrint(); epicsShareFunc int epicsShareAPI errSymBld(); epicsShareFunc int epicsShareAPI errSymbolAdd(); -epicsShareFunc void epicsShareAPI errPrintf(); epicsShareFunc void epicsShareAPI errSymDump(); epicsShareFunc void epicsShareAPI tstErrSymFind(); #endif /* errMDefUseProtoANSI */ diff --git a/src/libCom/errlog.h b/src/libCom/errlog.h new file mode 100644 index 000000000..1232386db --- /dev/null +++ b/src/libCom/errlog.h @@ -0,0 +1,95 @@ +/* src/libCom/errlog.h */ +/***************************************************************** + COPYRIGHT NOTIFICATION +***************************************************************** + +(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO + +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +**********************************************************************/ + +#ifndef INCerrlogh +#define INCerrlogh + +#include + +#ifdef __cplusplus +extern "C" { +#define epicsPrintUseProtoANSI +#endif + +#ifdef __STDC__ +#ifndef epicsPrintUseProtoANSI +#define epicsPrintUseProtoANSI +#endif +#endif + + +/* define errMessage with a macro so we can print the file and line number*/ +#define errMessage(S, PM) \ + errPrintf(S, __FILE__, __LINE__, PM) +/* epicsPrintf and epicsVprintf old versions of errlog routines*/ +#define epicsPrintf errlogPrintf +#define epicsVprintf errlogVprintf + +typedef void(*errlogListener) (const char *message); +typedef enum {errlogInfo,errlogMinor,errlogMajor,errlogFatal} errlogSevEnum; +extern char * errlogSevEnumString[]; +#ifdef ERRLOG_INIT +char * errlogSevEnumString[] = {"info","minor","major","fatal"}; +#endif + +#ifdef epicsPrintUseProtoANSI + +epicsShareFunc int epicsShareAPI errlogPrintf( + const char *pformat, ...); +epicsShareFunc int epicsShareAPI errlogVprintf( + const char *pformat,va_list pvar); +epicsShareFunc int epicsShareAPI errlogSevPrintf( + const errlogSevEnum severity,const char *pformat, ...); +epicsShareFunc int epicsShareAPI errlogSevVprintf( + const errlogSevEnum severity,const char *pformat,va_list pvar); +epicsShareFunc int epicsShareAPI errlogMessage( + const char *message); + +epicsShareFunc char * epicsShareAPI errlogGetSevEnumString( + const errlogSevEnum severity); +epicsShareFunc void epicsShareAPI errlogSetSevToLog( + const errlogSevEnum severity ); +epicsShareFunc errlogSevEnum epicsShareAPI errlogGetSevToLog(void); + +epicsShareFunc void epicsShareAPI errlogAddListener( + errlogListener listener); +epicsShareFunc void epicsShareAPI errlogRemoveListener( + errlogListener listener); + +epicsShareFunc void epicsShareAPI eltc(int yesno); +epicsShareFunc void epicsShareAPI errlogInit(int bufsize); + +/*other routines that write to log file*/ +epicsShareFunc void epicsShareAPI errPrintf(long status, const char *pFileName, + int lineno, const char *pformat, ...); + +#else /* not epicsPrintUseProtoANSI */ +epicsShareFunc int epicsShareAPI errlogPrintf(); +epicsShareFunc int epicsShareAPI errlogVprintf(); +epicsShareFunc int epicsShareAPI errlogSevPrintf(); +epicsShareFunc int epicsShareAPI errlogSevVprintf(); +epicsShareFunc int epicsShareAPI errlogMessage(); +epicsShareFunc char * epicsShareAPI errlogGetSevEnumString(); +epicsShareFunc void epicsShareAPI errlogSetSevToLog(); +epicsShareFunc errlogSevEnum epicsShareAPI errlogGetSevToLog(); +epicsShareFunc void epicsShareAPI errlogAddListener(); +epicsShareFunc void epicsShareAPI errlogRemoveListener(); +epicsShareFunc void epicsShareAPI eltc(); +epicsShareFunc void epicsShareAPI errlogInit(); +epicsShareFunc void epicsShareAPI errPrintf(); +#endif /* ifdef epicsPrintUseProtoANSI */ + +#ifdef __cplusplus +} +#endif + +#endif /*INCerrlogh*/ diff --git a/src/libCom/errlog.html b/src/libCom/errlog.html new file mode 100644 index 000000000..1afee206f --- /dev/null +++ b/src/libCom/errlog.html @@ -0,0 +1,152 @@ + + + + + + + +

+Error Logging System

+The error logging system provides: +
    +
  • +Error message routines that can be called by  ioc code.
  • + +
  • +Provision for multiple system wide error loggers..
  • + +
  • +A task (errlog) that handles the messages generated by the client routines. +It displays messages on the target console and also gives them to any registered +system wide error loggers.
  • + +
  • +iocLog: A system wide error logger that writes all error message to a file.
  • +
+ +

+Overview

+ +
    +
  • +The error message routines can be called by any non-interrupt level code.
  • + +
  • +Task errlog manages the messages. Messages are placed in a message queue, +which is read by the errlog task. The message queue uses a fixed block +of memory to hold all messages. When the message queue is full additional +messages are rejected but a count of missed messages is kept. The next +time the message queue empties an extra message about the missed messages +is generated.
  • + +
  • +The maximum message size  is 256  characters. If a message is +longer, the message is truncated and a message explaining that it was truncated +is appended. There is a chance that long messages corrupt memory. This  +only happens if client code is defective. Long messages most likely result +from "%s" formats with a bad string argument.
  • + +
  • +The error message routines are partially implemented on the host. The host +version just calls fprintf or vfprintf instead of using a separate task +and a message queue. Thus host messages are NOT sent to a system wide error +logger.
  • +
+ +

+Client Routines

+Basic Routines +
    +
    typedef enum {
    +    errlogInfo,errlogMinor,errlogMajor,errlogFatal
    +}errlogSevEnum;
    +
    +int errlogPrintf(const char *pformat, ...);
    +int errlogVprintf(const char *pformat,va_list pvar);
    +
    +int errlogSevPrintf(const errlogSevEnum severity,
    +    const char *pformat, ...);
    +int errlogSevVprintf(const errlogSevEnum severity,
    +    const char *pformat,va_list pvar);
    +
    +int errlogMessage( const char *message);
    +
    +char * errlogGetSevEnumString(const errlogSevEnum severity);
    +
    +void errlogSetSevToLog(const errlogSevEnum severity );
    +errlogSevEnum errlogGetSevToLog(void);
    +These are the basic client routines. + +

    errlogPrintf and errlogVprintf act just like printf and vprintf. + +

    errlogSevPrintf and errlogSevVprintf are similar except that they also +add the severity to the beginning of the message in the form "sevr=<value>" +where value is on of "info, minor, major, fatal". Also the message is suppressed +if  severity is less than the current severity to suppress. + +

    errlogMessage just logs message. + +

    errlogGetSevEnumString gets the string value of severity. + +

    errlogSetSevToLog sets the severity to log. errlogGetSevToLog gets the +current severity to log.

+Status Routines +
  +
    +
    void errMessage(long status, char *message);
    + +
    void errPrintf(long status, const char *pFileName,
    +    int lineno, const char *pformat, ...);
    +errMessage is just a macro that calls errPrintf. errPrintf is meant to +be called as follows: +
     errPrintf(status,__FILE__, __LINE__,"<format>",...)
    + The argument status is described in the Application Developer's guide. +The arguments __FILE__ and  __LINE__ are standard C preprocessor variables. +
     
+Obsolete Routines +
    +
    int epicsPrintf(const char *pformat, ...);
    +int epicsVprintf(const char *pformat,va_list pvar);
    +These are exactly like errlogPrintf and errlogVprintf. They are provided +because a lot of existing code calls them,. 
+Add and Remove Log Listener +
    +
    typedef void(*errlogListener) (const char *message);
    +void errlogAddListener(errlogListener listener);
    +void errlogRemoveListener(errlogListener listener);
    +These routines add/remove a callback that receives each error message. +
     
+target console routines +
    +
    void eltc(int yesno); /* error log to console (0 or 1) */
    +void errlogInit(int bufsize);
    +
+eltc determines if errlog task writes message to the console. If error +messages storms are occuring the command can be used to suppress the messages. +A argument of 0 suppresses the messages and any other value lets the message +go to the console. + +

errlogInit can be used to initialize the error logging system with a +larger buffer. The default is 1280 bytes. An extra MAX_MESSAGE_SIZE (currently +256) bytes are allocated but never used. This is a small extra protection +against long error messages. +

+iocLog

+This consists of two modules: iocLogServer and iocLogClient. The client +code runs on each ioc and listens for the messages generated by the errlog +system. It also reports the messages from  vxWorks logMsg. +

+iocLogServer

+This runs on a host. It receives messages for all enabled iocLogClients +in the local area network. The messages are written to a file. Epics base +provides a startup file "base/src/util/rc2.logServer", which is a shell +script to start the server. Consult this script for details. +

+iocLogClient

+This runs on each ioc. It is started by default when iocInit runs. The +global variable iocLogDisable can be used to enable/disable the messages +from being sent to the server. Setting this variable to (0,1) (enables,disables) +the messages generation. If iocLogDisable is set to 1 immediately +after iocCore is loaded then iocLogClient will not even initialize itself. + + diff --git a/src/libCom/errlogUNIX.c b/src/libCom/errlogUNIX.c new file mode 100644 index 000000000..e5850e3f8 --- /dev/null +++ b/src/libCom/errlogUNIX.c @@ -0,0 +1,174 @@ +/* $Id$ + * errPrintfUNIX.c + * Author: Marty Kraimer + * Date: 02-16-95 + * + * Experimental Physics and Industrial Control System (EPICS) + * + * Copyright 1991, the Regents of the University of California, + * and the University of Chicago Board of Governors. + * + * This software was produced under U.S. Government contracts: + * (W-7405-ENG-36) at the Los Alamos National Laboratory, + * and (W-31-109-ENG-38) at Argonne National Laboratory. + * + * Initial development by: + * The Controls and Automation Group (AT-8) + * Ground Test Accelerator + * Accelerator Technology Division + * Los Alamos National Laboratory + * + * Co-developed with + * The Controls and Computing Group + * Accelerator Systems Division + * Advanced Photon Source + * Argonne National Laboratory + * + * Modification Log: errPrintfUNIX.c + * ----------------- + * .01 02-16-95 mrk Extracted from errSymLib.c + *************************************************************************** + * This must ultimately be replaced by a facility that allows remote + * nodes access to the error messages. A message handling communication + * task should be written that allows multiple remote nodes to request + * notification of all error messages. + * For now lets just call fprintf and vfprintf + *************************************************************************** + */ + +#include +#include +#include +#include + +#include "epicsAssert.h" +#define epicsExportSharedSymbols +#define ERRLOG_INIT +#include "errlog.h" +#undef ERRLOG_INIT +#undef epicsExportSharedSymbols + +#include "errMdef.h" +#include "error.h" + + +static int sevToLog=0; + + +epicsShareFunc int epicsShareAPI errlogPrintf(const char *pformat, ...) +{ + va_list pvar; + int nchar; + + va_start(pvar,pformat); + nchar = errlogVprintf(pformat,pvar); + va_end (pvar); + return(nchar); +} + +epicsShareFunc int epicsShareAPI errlogVprintf( + const char *pformat, va_list pvar) +{ + return(vfprintf(stderr,pformat,pvar)); +} + +epicsShareFunc int epicsShareAPI errlogMessage(const char *message) +{ + fprintf(stderr,"%s\n",message); + return(0); +} + +epicsShareFunc int epicsShareAPI errlogSevPrintf( + const errlogSevEnum severity,const char *pformat, ...) +{ + va_list pvar; + int nchar; + + if(sevToLog>severity) return(0); + va_start(pvar, pformat); + nchar = errlogSevVprintf(severity,pformat,pvar); + va_end (pvar); + return(nchar); +} + +epicsShareFunc int epicsShareAPI errlogSevVprintf( + const errlogSevEnum severity,const char *pformat,va_list pvar) +{ + char *pnext; + int nchar; + int totalChar=0; + + if(sevToLog>severity) return(0); + fprintf(stderr,"sevr=%s ",errlogGetSevEnumString(severity)); + nchar = vfprintf(stderr,pformat,pvar); + fprintf(stderr,"\n"); + return(nchar+1); +} + +epicsShareFunc char * epicsShareAPI errlogGetSevEnumString( + const errlogSevEnum severity) +{ + static char unknown[] = "unknown"; + + if(severity<0 || severity>3) return(unknown); + return(errlogSevEnumString[severity]); +} + + +epicsShareFunc void epicsShareAPI errlogSetSevToLog( + const errlogSevEnum severity ) +{ + sevToLog = severity; +} + +epicsShareFunc errlogSevEnum epicsShareAPI errlogGetSevToLog() +{ + return(sevToLog); +} + +epicsShareFunc void epicsShareAPI errlogAddListener( + errlogListener listener) +{ + fprintf(stderr,"errlogAddListener not implemented\n"); + return; +} + +epicsShareFunc void epicsShareAPI errlogRemoveListener( + errlogListener listener) +{ + fprintf(stderr,"errlogRemoveListener not implemented\n"); + return; +} + + +epicsShareFunc void epicsShareAPI errPrintf(long status, const char *pFileName, + int lineno, const char *pformat, ...) +{ + va_list pvar; + + va_start(pvar, pformat); + if(pFileName && errVerbose){ + fprintf(stderr,"filename=\"%s\" line number=%d\n", pFileName, lineno); + } + if(status==0) status = errno; + if(status>0) { + int rtnval; + char name[256]; + + rtnval = errSymFind(status,name); + if(rtnval) { + unsigned short modnum,errnum; + + modnum = (unsigned short) (status >> 16); + errnum = (unsigned short) (status & 0xffff); + fprintf(stderr, "status (%hu,%hu) not in symbol table", + modnum, errnum); + } else { + fprintf(stderr,"%s ",name); + } + } + if (pformat) { + vfprintf(stderr,pformat,pvar); + } + fprintf(stderr,"\n"); +} diff --git a/src/libCom/errlogVX.c b/src/libCom/errlogVX.c new file mode 100644 index 000000000..7ae187b3f --- /dev/null +++ b/src/libCom/errlogVX.c @@ -0,0 +1,479 @@ +/***************************************************************** + COPYRIGHT NOTIFICATION +***************************************************************** + +(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO + +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +**********************************************************************/ +/* + * Author: Marty Kraimer and Jeff Hill + * Date: 07JAN1998 + * NOTE: Original version is adaptation of old version of errPrintfVX.c +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "epicsAssert.h" +#define epicsExportSharedSymbols +#define ERRLOG_INIT +#include "errlog.h" +#undef ERRLOG_INIT +#undef epicsExportSharedSymbols +#include "errMdef.h" +#include "ellLib.h" +#include "error.h" +#include "task_params.h" + +#ifndef LOCAL +#define LOCAL static +#endif /* LOCAL */ + +#define BUFFER_SIZE 1280 +#define MAX_MESSAGE_SIZE 256 +#define TRUNCATE_SIZE 80 +#define MAX_ALIGNMENT 8 + +LOCAL void errlogTask(void); + +LOCAL char *msgbufGetFree(void); +LOCAL void msgbufSetSize(int size); +LOCAL char * msgbufGetSend(void); +LOCAL void msgbufFreeSend(void); + +LOCAL void *pvtCalloc(size_t count,size_t size); +LOCAL void pvtSemTake(SEM_ID semid); + +typedef struct listenerNode{ + ELLNODE node; + errlogListener listener; +}listenerNode; + +/*each message consists of a msgNode immediately followed by the message */ +typedef struct msgNode { + ELLNODE node; + char *message; + int length; +} msgNode; + +LOCAL struct { + SEM_ID errlogTaskWaitForWork; + SEM_ID msgQueueLock; + SEM_ID listenerLock; + ELLLIST listenerList; + ELLLIST msgQueue; + msgNode *pnextSend; + int buffersize; + int sevToLog; + int toConsole; + int missedMessages; + void *pbuffer; +}pvtData; + +epicsShareFunc int epicsShareAPI errlogPrintf( const char *pFormat, ...) +{ + va_list pvar; + int nchar; + + if(INT_CONTEXT()) { + logMsg("errlogPrintf called from interrupt level\n",0,0,0,0,0,0); + return 0; + } + errlogInit(0); + va_start(pvar, pFormat); + nchar = errlogVprintf(pFormat,pvar); + va_end (pvar); + return(nchar); +} + +epicsShareFunc int epicsShareAPI errlogVprintf( + const char *pFormat,va_list pvar) +{ + int nchar; + char *pbuffer; + + if(INT_CONTEXT()) { + logMsg("errlogVprintf called from interrupt level\n",0,0,0,0,0,0); + return 0; + } + errlogInit(0); + pbuffer = msgbufGetFree(); + if(!pbuffer) return(0); + nchar = vsprintf(pbuffer,pFormat,pvar); + msgbufSetSize(nchar+1);/*include the \0*/ + return nchar; +} + +epicsShareFunc int epicsShareAPI errlogMessage(const char *message) +{ + int status; + char *pbuffer; + + if(INT_CONTEXT()) { + status = logMsg ("errlogMessage called from interrupt level %s", + message,0,0,0,0,0); + return 0; + } + errlogInit(0); + pbuffer = msgbufGetFree(); + if(!pbuffer) return(0); + strcpy(pbuffer,message); + msgbufSetSize(strlen(message) +1); + return 0; +} + +epicsShareFunc int epicsShareAPI errlogSevPrintf( + const errlogSevEnum severity,const char *pFormat, ...) +{ + va_list pvar; + int nchar; + + if(INT_CONTEXT()) { + logMsg("errlogSevPrintf called from interrupt level\n",0,0,0,0,0,0); + return 0; + } + errlogInit(0); + if(pvtData.sevToLog>severity) return(0); + va_start(pvar, pFormat); + nchar = errlogSevVprintf(severity,pFormat,pvar); + va_end (pvar); + return(nchar); +} + +epicsShareFunc int epicsShareAPI errlogSevVprintf( + const errlogSevEnum severity,const char *pFormat,va_list pvar) +{ + char *pnext; + int nchar; + int totalChar=0; + + if(pvtData.sevToLog>severity) return(0); + if(INT_CONTEXT()) { + logMsg("errlogSevVprintf called from interrupt level\n",0,0,0,0,0,0); + return 0; + } + errlogInit(0); + pnext = msgbufGetFree(); + if(!pnext) return(0); + nchar = sprintf(pnext,"sevr=%s ",errlogGetSevEnumString(severity)); + pnext += nchar; totalChar += nchar; + nchar = vsprintf(pnext,pFormat,pvar); + pnext += nchar; totalChar += nchar; + sprintf(pnext,"\n"); + totalChar += 2; /*include \n and \0*/ + msgbufSetSize(totalChar); + return(nchar); +} + +epicsShareFunc char * epicsShareAPI errlogGetSevEnumString( + const errlogSevEnum severity) +{ + static char unknown[] = "unknown"; + + errlogInit(0); + if(severity<0 || severity>3) return(unknown); + return(errlogSevEnumString[severity]); +} + +epicsShareFunc void epicsShareAPI errlogSetSevToLog( + const errlogSevEnum severity ) +{ + errlogInit(0); + pvtData.sevToLog = severity; +} + +epicsShareFunc errlogSevEnum epicsShareAPI errlogGetSevToLog() +{ + errlogInit(0); + return(pvtData.sevToLog); +} + +epicsShareFunc void epicsShareAPI errlogAddListener( + errlogListener listener) +{ + listenerNode *plistenerNode; + + errlogInit(0); + plistenerNode = pvtCalloc(1,sizeof(listenerNode)); + pvtSemTake(pvtData.listenerLock); + plistenerNode->listener = listener; + ellAdd(&pvtData.listenerList,&plistenerNode->node); + semGive(pvtData.listenerLock); +} + +epicsShareFunc void epicsShareAPI errlogRemoveListener( + errlogListener listener) +{ + listenerNode *plistenerNode; + + errlogInit(0); + pvtSemTake(pvtData.listenerLock); + plistenerNode = (listenerNode *)ellFirst(&pvtData.listenerList); + while(plistenerNode) { + if(plistenerNode->listener==listener) { + ellDelete(&pvtData.listenerList,&plistenerNode->node); + free((void *)plistenerNode); + break; + } + plistenerNode = (listenerNode *)ellNext(&plistenerNode->node); + } + semGive(pvtData.listenerLock); + if(!plistenerNode) printf("errlogRemoveListener did not find listener\n"); +} + +epicsShareFunc void epicsShareAPI eltc(int yesno) +{ + errlogInit(0); + pvtData.toConsole = yesno; +} + +epicsShareFunc void epicsShareAPI errPrintf(long status, const char *pFileName, + int lineno, const char *pformat, ...) +{ + va_list pvar; + char *pnext; + int nchar; + int totalChar=0; + + if(INT_CONTEXT()) { + logMsg("errPrintf called from interrupt level\n",0,0,0,0,0,0); + return; + } + errlogInit(0); + pnext = msgbufGetFree(); + if(!pnext) return; + if(pFileName){ + nchar = sprintf(pnext,"filename=\"%s\" line number=%d\n", + pFileName, lineno); + pnext += nchar; totalChar += nchar; + } + if(status==0) status = MYERRNO; + if(status>0) { + int rtnval; + char name[256]; + + rtnval = errSymFind(status,name); + if(rtnval) { + unsigned short modnum,errnum; + + modnum = status >> 16; errnum = status & 0xffff; + nchar = sprintf(pnext, "status (%hu,%hu) not in symbol table ", + modnum, errnum); + } else { + nchar = sprintf(pnext,"%s ",name); + } + pnext += nchar; totalChar += nchar; + } + va_start (pvar, pformat); + nchar = vsprintf(pnext,pformat,pvar); + va_end (pvar); + if(nchar>0) { + pnext += nchar; + totalChar += nchar; + } + sprintf(pnext,"\n"); + totalChar += 2; /*include the \n and the \0*/ + msgbufSetSize(totalChar); +} + +#define optionsSemM SEM_Q_PRIORITY|SEM_DELETE_SAFE|SEM_INVERSION_SAFE +epicsShareFunc void epicsShareAPI errlogInit(int bufsize) +{ + static int errlogInitFlag=0; + void *pbuffer;; + + if(!vxTas(&errlogInitFlag)) return; + if(bufsizelistener)(pmessage); + plistenerNode = (listenerNode *)ellNext(&plistenerNode->node); + } + semGive(pvtData.listenerLock); + msgbufFreeSend(); + } + } +} + +LOCAL msgNode *msgbufGetNode() +{ + char *pbuffer = (char *)pvtData.pbuffer; + msgNode *pnextSend = 0; + + if(ellCount(&pvtData.msgQueue) == 0 ) { + pnextSend = (msgNode *)pbuffer; + } else { + int needed; + int remaining; + msgNode *plast; + + plast = (msgNode *)ellLast(&pvtData.msgQueue); + needed = MAX_MESSAGE_SIZE + sizeof(msgNode) + MAX_ALIGNMENT; + remaining = pvtData.buffersize + - ((plast->message - pbuffer) + plast->length); + if(needed < remaining) { + int length,adjust; + + length = plast->length; + /*Make length a multiple of MAX_ALIGNMENT*/ + adjust = length%MAX_ALIGNMENT; + if(adjust) length += (MAX_ALIGNMENT-adjust); + pnextSend = (msgNode *)(plast->message + length); + } + } + if(!pnextSend) return(0); + pnextSend->message = (char *)pnextSend + sizeof(msgNode); + pnextSend->length = 0; + return(pnextSend); +} + +LOCAL char *msgbufGetFree() +{ + msgNode *pnextSend; + + pvtSemTake(pvtData.msgQueueLock); + if((ellCount(&pvtData.msgQueue) == 0) && pvtData.missedMessages) { + int nchar; + + pnextSend = msgbufGetNode(); + nchar = sprintf(pnextSend->message,"errlog = %d messages were discarded\n", + pvtData.missedMessages); + pnextSend->length = nchar + 1; + pvtData.missedMessages = 0; + ellAdd(&pvtData.msgQueue,&pnextSend->node); + } + pvtData.pnextSend = pnextSend = msgbufGetNode(); + if(pnextSend) return(pnextSend->message); + ++pvtData.missedMessages; + semGive(pvtData.msgQueueLock); + return(0); +} + +LOCAL void msgbufSetSize(int size) +{ + char *pbuffer = (char *)pvtData.pbuffer; + msgNode *pnextSend = pvtData.pnextSend; + char *message = pnextSend->message; + + if(size>MAX_MESSAGE_SIZE) { + int excess; + int nchar; + + excess = size - (pvtData.buffersize -(message - pbuffer)); + message[TRUNCATE_SIZE] = 0; + if(excess> 0) { + printf("errlog: A message overran buffer by %d. This is VERY bad\n", + excess); + nchar = sprintf(&message[TRUNCATE_SIZE], + "\nerrlog = previous message overran buffer. It was truncated." + " size = %d excess = %d\n", size,excess); + } else { + nchar = sprintf(&message[TRUNCATE_SIZE], + "\nerrlog = previous message too long. It was truncated." + " size=%d It was truncated\n",size); + } + pnextSend->length = TRUNCATE_SIZE + nchar +1; + } else { + pnextSend->length = size+1; + } + ellAdd(&pvtData.msgQueue,&pnextSend->node); + semGive(pvtData.msgQueueLock); + semGive(pvtData.errlogTaskWaitForWork); +} + +/*errlogTask is the only task that calls msgbufGetSend and msgbufFreeSend*/ +/*Thus errlogTask is the ONLY task that removes messages from msgQueue */ +/*This is why each can lock and unlock msgQueue */ +/*This is necessary to prevent other tasks from waiting for errlogTask */ +LOCAL char * msgbufGetSend() +{ + msgNode *pnextSend; + + pvtSemTake(pvtData.msgQueueLock); + pnextSend = (msgNode *)ellFirst(&pvtData.msgQueue); + semGive(pvtData.msgQueueLock); + if(!pnextSend) return(0); + return(pnextSend->message); +} + +LOCAL void msgbufFreeSend() +{ + msgNode *pnextSend; + + pvtSemTake(pvtData.msgQueueLock); + pnextSend = (msgNode *)ellFirst(&pvtData.msgQueue); + if(!pnextSend) { + printf("errlog: msgbufFreeSend logic error\n"); + taskSuspend(0); + } + ellDelete(&pvtData.msgQueue,&pnextSend->node); + semGive(pvtData.msgQueueLock); +} + +LOCAL void *pvtCalloc(size_t count,size_t size) +{ + size_t *pmem; + + pmem = calloc(count,size); + if(!pmem) { + printf("calloc failed in errlog\n"); + taskSuspend(0); + } + return(pmem); +} + +LOCAL void pvtSemTake(SEM_ID semid) +{ + if(semTake(semid,WAIT_FOREVER)!=OK) { + logMsg("epicsPrint: semTake returned error\n",0,0,0,0,0,0); + taskSuspend(0); + } +} diff --git a/src/libCom/error/epicsPrint.h b/src/libCom/error/epicsPrint.h index 01f77aa3b..3f66530ce 100644 --- a/src/libCom/error/epicsPrint.h +++ b/src/libCom/error/epicsPrint.h @@ -1,34 +1,9 @@ +/*epicsPrint.h */ -#ifdef __cplusplus -extern "C" { -#define epicsPrintUseProtoANSI -#endif +/*This is now obsolete. Remlaced by errlog.h */ +#ifndef INCepicsPrintH +#define INCepicsPrintH -#ifdef __STDC__ -#ifndef epicsPrintUseProtoANSI -#define epicsPrintUseProtoANSI -#endif -#endif - -#ifdef vxWorks -# ifdef epicsPrintUseProtoANSI -# include - int epicsPrintf(const char *pFormat, ...); - int epicsVprintf (const char *pFormat, va_list pvar); - int iocLogVPrintf(const char *pFormat, va_list pvar); - int iocLogPrintf(const char *pFormat, ...); -# else /* not epicsPrintUseProtoANSI */ - int epicsPrintf(); - int epicsVprintf (); - int iocLogVPrintf(); - int iocLogPrintf(); -# endif /* ifdef epicsPrintUseProtoANSI */ -#else /* not vxWorks */ -# define epicsPrintf printf -# define epicsVprintf vprintf -#endif /* ifdef vxWorks */ - -#ifdef __cplusplus -} -#endif +#include "errlog.h" +#endif /*INCepicsPrintH*/ diff --git a/src/libCom/error/errMdef.h b/src/libCom/error/errMdef.h index 2d565513d..901f25b7c 100644 --- a/src/libCom/error/errMdef.h +++ b/src/libCom/error/errMdef.h @@ -61,6 +61,10 @@ extern "C" { #include "ellLib.h" #include "shareLib.h" +/*The following is only included because before 3.13.0beta12 errMessage */ +/*and errPrintf were defined here */ +#include "errlog.h" + #define RTN_SUCCESS(STATUS) ((STATUS)==0) #define M_dbAccess (501 <<16) /*Database Access Routines */ @@ -88,13 +92,6 @@ extern "C" { #define M_bucket (525 <<16) /*Bucket Hash*/ #define M_gddFuncTbl (526 <<16) /*gdd jump table*/ -/* - * redefine errMessage with a macro so we can print - * the file and line number - */ -#define errMessage(S, PM) \ - errPrintf(S, __FILE__, __LINE__, PM) - #ifdef errMDefUseProtoANSI epicsShareFunc int epicsShareAPI errSymFind(long status, char *name); epicsShareFunc int epicsShareAPI UnixSymFind(long status, char *name, long *value); @@ -103,11 +100,8 @@ epicsShareFunc void epicsShareAPI errSymTest(unsigned short modnum, unsigned sho epicsShareFunc void epicsShareAPI errSymTestPrint(long errNum); epicsShareFunc int epicsShareAPI errSymBld(); epicsShareFunc int epicsShareAPI errSymbolAdd (long errNum,char *name); -epicsShareFunc void epicsShareAPI errPrintf(long status, const char *pFileName, - int lineno, const char *pformat, ...); epicsShareFunc void epicsShareAPI errSymDump(); epicsShareFunc void epicsShareAPI tstErrSymFind(); -epicsShareFunc void epicsShareAPI errInit(void); #else /* errMDefUseProtoANSI */ @@ -118,7 +112,6 @@ epicsShareFunc int epicsShareAPI ModSymFind(); epicsShareFunc void epicsShareAPI errSymTestPrint(); epicsShareFunc int epicsShareAPI errSymBld(); epicsShareFunc int epicsShareAPI errSymbolAdd(); -epicsShareFunc void epicsShareAPI errPrintf(); epicsShareFunc void epicsShareAPI errSymDump(); epicsShareFunc void epicsShareAPI tstErrSymFind(); #endif /* errMDefUseProtoANSI */ diff --git a/src/libCom/error/errlog.c b/src/libCom/error/errlog.c new file mode 100644 index 000000000..7ae187b3f --- /dev/null +++ b/src/libCom/error/errlog.c @@ -0,0 +1,479 @@ +/***************************************************************** + COPYRIGHT NOTIFICATION +***************************************************************** + +(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO + +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +**********************************************************************/ +/* + * Author: Marty Kraimer and Jeff Hill + * Date: 07JAN1998 + * NOTE: Original version is adaptation of old version of errPrintfVX.c +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "epicsAssert.h" +#define epicsExportSharedSymbols +#define ERRLOG_INIT +#include "errlog.h" +#undef ERRLOG_INIT +#undef epicsExportSharedSymbols +#include "errMdef.h" +#include "ellLib.h" +#include "error.h" +#include "task_params.h" + +#ifndef LOCAL +#define LOCAL static +#endif /* LOCAL */ + +#define BUFFER_SIZE 1280 +#define MAX_MESSAGE_SIZE 256 +#define TRUNCATE_SIZE 80 +#define MAX_ALIGNMENT 8 + +LOCAL void errlogTask(void); + +LOCAL char *msgbufGetFree(void); +LOCAL void msgbufSetSize(int size); +LOCAL char * msgbufGetSend(void); +LOCAL void msgbufFreeSend(void); + +LOCAL void *pvtCalloc(size_t count,size_t size); +LOCAL void pvtSemTake(SEM_ID semid); + +typedef struct listenerNode{ + ELLNODE node; + errlogListener listener; +}listenerNode; + +/*each message consists of a msgNode immediately followed by the message */ +typedef struct msgNode { + ELLNODE node; + char *message; + int length; +} msgNode; + +LOCAL struct { + SEM_ID errlogTaskWaitForWork; + SEM_ID msgQueueLock; + SEM_ID listenerLock; + ELLLIST listenerList; + ELLLIST msgQueue; + msgNode *pnextSend; + int buffersize; + int sevToLog; + int toConsole; + int missedMessages; + void *pbuffer; +}pvtData; + +epicsShareFunc int epicsShareAPI errlogPrintf( const char *pFormat, ...) +{ + va_list pvar; + int nchar; + + if(INT_CONTEXT()) { + logMsg("errlogPrintf called from interrupt level\n",0,0,0,0,0,0); + return 0; + } + errlogInit(0); + va_start(pvar, pFormat); + nchar = errlogVprintf(pFormat,pvar); + va_end (pvar); + return(nchar); +} + +epicsShareFunc int epicsShareAPI errlogVprintf( + const char *pFormat,va_list pvar) +{ + int nchar; + char *pbuffer; + + if(INT_CONTEXT()) { + logMsg("errlogVprintf called from interrupt level\n",0,0,0,0,0,0); + return 0; + } + errlogInit(0); + pbuffer = msgbufGetFree(); + if(!pbuffer) return(0); + nchar = vsprintf(pbuffer,pFormat,pvar); + msgbufSetSize(nchar+1);/*include the \0*/ + return nchar; +} + +epicsShareFunc int epicsShareAPI errlogMessage(const char *message) +{ + int status; + char *pbuffer; + + if(INT_CONTEXT()) { + status = logMsg ("errlogMessage called from interrupt level %s", + message,0,0,0,0,0); + return 0; + } + errlogInit(0); + pbuffer = msgbufGetFree(); + if(!pbuffer) return(0); + strcpy(pbuffer,message); + msgbufSetSize(strlen(message) +1); + return 0; +} + +epicsShareFunc int epicsShareAPI errlogSevPrintf( + const errlogSevEnum severity,const char *pFormat, ...) +{ + va_list pvar; + int nchar; + + if(INT_CONTEXT()) { + logMsg("errlogSevPrintf called from interrupt level\n",0,0,0,0,0,0); + return 0; + } + errlogInit(0); + if(pvtData.sevToLog>severity) return(0); + va_start(pvar, pFormat); + nchar = errlogSevVprintf(severity,pFormat,pvar); + va_end (pvar); + return(nchar); +} + +epicsShareFunc int epicsShareAPI errlogSevVprintf( + const errlogSevEnum severity,const char *pFormat,va_list pvar) +{ + char *pnext; + int nchar; + int totalChar=0; + + if(pvtData.sevToLog>severity) return(0); + if(INT_CONTEXT()) { + logMsg("errlogSevVprintf called from interrupt level\n",0,0,0,0,0,0); + return 0; + } + errlogInit(0); + pnext = msgbufGetFree(); + if(!pnext) return(0); + nchar = sprintf(pnext,"sevr=%s ",errlogGetSevEnumString(severity)); + pnext += nchar; totalChar += nchar; + nchar = vsprintf(pnext,pFormat,pvar); + pnext += nchar; totalChar += nchar; + sprintf(pnext,"\n"); + totalChar += 2; /*include \n and \0*/ + msgbufSetSize(totalChar); + return(nchar); +} + +epicsShareFunc char * epicsShareAPI errlogGetSevEnumString( + const errlogSevEnum severity) +{ + static char unknown[] = "unknown"; + + errlogInit(0); + if(severity<0 || severity>3) return(unknown); + return(errlogSevEnumString[severity]); +} + +epicsShareFunc void epicsShareAPI errlogSetSevToLog( + const errlogSevEnum severity ) +{ + errlogInit(0); + pvtData.sevToLog = severity; +} + +epicsShareFunc errlogSevEnum epicsShareAPI errlogGetSevToLog() +{ + errlogInit(0); + return(pvtData.sevToLog); +} + +epicsShareFunc void epicsShareAPI errlogAddListener( + errlogListener listener) +{ + listenerNode *plistenerNode; + + errlogInit(0); + plistenerNode = pvtCalloc(1,sizeof(listenerNode)); + pvtSemTake(pvtData.listenerLock); + plistenerNode->listener = listener; + ellAdd(&pvtData.listenerList,&plistenerNode->node); + semGive(pvtData.listenerLock); +} + +epicsShareFunc void epicsShareAPI errlogRemoveListener( + errlogListener listener) +{ + listenerNode *plistenerNode; + + errlogInit(0); + pvtSemTake(pvtData.listenerLock); + plistenerNode = (listenerNode *)ellFirst(&pvtData.listenerList); + while(plistenerNode) { + if(plistenerNode->listener==listener) { + ellDelete(&pvtData.listenerList,&plistenerNode->node); + free((void *)plistenerNode); + break; + } + plistenerNode = (listenerNode *)ellNext(&plistenerNode->node); + } + semGive(pvtData.listenerLock); + if(!plistenerNode) printf("errlogRemoveListener did not find listener\n"); +} + +epicsShareFunc void epicsShareAPI eltc(int yesno) +{ + errlogInit(0); + pvtData.toConsole = yesno; +} + +epicsShareFunc void epicsShareAPI errPrintf(long status, const char *pFileName, + int lineno, const char *pformat, ...) +{ + va_list pvar; + char *pnext; + int nchar; + int totalChar=0; + + if(INT_CONTEXT()) { + logMsg("errPrintf called from interrupt level\n",0,0,0,0,0,0); + return; + } + errlogInit(0); + pnext = msgbufGetFree(); + if(!pnext) return; + if(pFileName){ + nchar = sprintf(pnext,"filename=\"%s\" line number=%d\n", + pFileName, lineno); + pnext += nchar; totalChar += nchar; + } + if(status==0) status = MYERRNO; + if(status>0) { + int rtnval; + char name[256]; + + rtnval = errSymFind(status,name); + if(rtnval) { + unsigned short modnum,errnum; + + modnum = status >> 16; errnum = status & 0xffff; + nchar = sprintf(pnext, "status (%hu,%hu) not in symbol table ", + modnum, errnum); + } else { + nchar = sprintf(pnext,"%s ",name); + } + pnext += nchar; totalChar += nchar; + } + va_start (pvar, pformat); + nchar = vsprintf(pnext,pformat,pvar); + va_end (pvar); + if(nchar>0) { + pnext += nchar; + totalChar += nchar; + } + sprintf(pnext,"\n"); + totalChar += 2; /*include the \n and the \0*/ + msgbufSetSize(totalChar); +} + +#define optionsSemM SEM_Q_PRIORITY|SEM_DELETE_SAFE|SEM_INVERSION_SAFE +epicsShareFunc void epicsShareAPI errlogInit(int bufsize) +{ + static int errlogInitFlag=0; + void *pbuffer;; + + if(!vxTas(&errlogInitFlag)) return; + if(bufsizelistener)(pmessage); + plistenerNode = (listenerNode *)ellNext(&plistenerNode->node); + } + semGive(pvtData.listenerLock); + msgbufFreeSend(); + } + } +} + +LOCAL msgNode *msgbufGetNode() +{ + char *pbuffer = (char *)pvtData.pbuffer; + msgNode *pnextSend = 0; + + if(ellCount(&pvtData.msgQueue) == 0 ) { + pnextSend = (msgNode *)pbuffer; + } else { + int needed; + int remaining; + msgNode *plast; + + plast = (msgNode *)ellLast(&pvtData.msgQueue); + needed = MAX_MESSAGE_SIZE + sizeof(msgNode) + MAX_ALIGNMENT; + remaining = pvtData.buffersize + - ((plast->message - pbuffer) + plast->length); + if(needed < remaining) { + int length,adjust; + + length = plast->length; + /*Make length a multiple of MAX_ALIGNMENT*/ + adjust = length%MAX_ALIGNMENT; + if(adjust) length += (MAX_ALIGNMENT-adjust); + pnextSend = (msgNode *)(plast->message + length); + } + } + if(!pnextSend) return(0); + pnextSend->message = (char *)pnextSend + sizeof(msgNode); + pnextSend->length = 0; + return(pnextSend); +} + +LOCAL char *msgbufGetFree() +{ + msgNode *pnextSend; + + pvtSemTake(pvtData.msgQueueLock); + if((ellCount(&pvtData.msgQueue) == 0) && pvtData.missedMessages) { + int nchar; + + pnextSend = msgbufGetNode(); + nchar = sprintf(pnextSend->message,"errlog = %d messages were discarded\n", + pvtData.missedMessages); + pnextSend->length = nchar + 1; + pvtData.missedMessages = 0; + ellAdd(&pvtData.msgQueue,&pnextSend->node); + } + pvtData.pnextSend = pnextSend = msgbufGetNode(); + if(pnextSend) return(pnextSend->message); + ++pvtData.missedMessages; + semGive(pvtData.msgQueueLock); + return(0); +} + +LOCAL void msgbufSetSize(int size) +{ + char *pbuffer = (char *)pvtData.pbuffer; + msgNode *pnextSend = pvtData.pnextSend; + char *message = pnextSend->message; + + if(size>MAX_MESSAGE_SIZE) { + int excess; + int nchar; + + excess = size - (pvtData.buffersize -(message - pbuffer)); + message[TRUNCATE_SIZE] = 0; + if(excess> 0) { + printf("errlog: A message overran buffer by %d. This is VERY bad\n", + excess); + nchar = sprintf(&message[TRUNCATE_SIZE], + "\nerrlog = previous message overran buffer. It was truncated." + " size = %d excess = %d\n", size,excess); + } else { + nchar = sprintf(&message[TRUNCATE_SIZE], + "\nerrlog = previous message too long. It was truncated." + " size=%d It was truncated\n",size); + } + pnextSend->length = TRUNCATE_SIZE + nchar +1; + } else { + pnextSend->length = size+1; + } + ellAdd(&pvtData.msgQueue,&pnextSend->node); + semGive(pvtData.msgQueueLock); + semGive(pvtData.errlogTaskWaitForWork); +} + +/*errlogTask is the only task that calls msgbufGetSend and msgbufFreeSend*/ +/*Thus errlogTask is the ONLY task that removes messages from msgQueue */ +/*This is why each can lock and unlock msgQueue */ +/*This is necessary to prevent other tasks from waiting for errlogTask */ +LOCAL char * msgbufGetSend() +{ + msgNode *pnextSend; + + pvtSemTake(pvtData.msgQueueLock); + pnextSend = (msgNode *)ellFirst(&pvtData.msgQueue); + semGive(pvtData.msgQueueLock); + if(!pnextSend) return(0); + return(pnextSend->message); +} + +LOCAL void msgbufFreeSend() +{ + msgNode *pnextSend; + + pvtSemTake(pvtData.msgQueueLock); + pnextSend = (msgNode *)ellFirst(&pvtData.msgQueue); + if(!pnextSend) { + printf("errlog: msgbufFreeSend logic error\n"); + taskSuspend(0); + } + ellDelete(&pvtData.msgQueue,&pnextSend->node); + semGive(pvtData.msgQueueLock); +} + +LOCAL void *pvtCalloc(size_t count,size_t size) +{ + size_t *pmem; + + pmem = calloc(count,size); + if(!pmem) { + printf("calloc failed in errlog\n"); + taskSuspend(0); + } + return(pmem); +} + +LOCAL void pvtSemTake(SEM_ID semid) +{ + if(semTake(semid,WAIT_FOREVER)!=OK) { + logMsg("epicsPrint: semTake returned error\n",0,0,0,0,0,0); + taskSuspend(0); + } +} diff --git a/src/libCom/error/errlog.h b/src/libCom/error/errlog.h new file mode 100644 index 000000000..1232386db --- /dev/null +++ b/src/libCom/error/errlog.h @@ -0,0 +1,95 @@ +/* src/libCom/errlog.h */ +/***************************************************************** + COPYRIGHT NOTIFICATION +***************************************************************** + +(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO + +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +**********************************************************************/ + +#ifndef INCerrlogh +#define INCerrlogh + +#include + +#ifdef __cplusplus +extern "C" { +#define epicsPrintUseProtoANSI +#endif + +#ifdef __STDC__ +#ifndef epicsPrintUseProtoANSI +#define epicsPrintUseProtoANSI +#endif +#endif + + +/* define errMessage with a macro so we can print the file and line number*/ +#define errMessage(S, PM) \ + errPrintf(S, __FILE__, __LINE__, PM) +/* epicsPrintf and epicsVprintf old versions of errlog routines*/ +#define epicsPrintf errlogPrintf +#define epicsVprintf errlogVprintf + +typedef void(*errlogListener) (const char *message); +typedef enum {errlogInfo,errlogMinor,errlogMajor,errlogFatal} errlogSevEnum; +extern char * errlogSevEnumString[]; +#ifdef ERRLOG_INIT +char * errlogSevEnumString[] = {"info","minor","major","fatal"}; +#endif + +#ifdef epicsPrintUseProtoANSI + +epicsShareFunc int epicsShareAPI errlogPrintf( + const char *pformat, ...); +epicsShareFunc int epicsShareAPI errlogVprintf( + const char *pformat,va_list pvar); +epicsShareFunc int epicsShareAPI errlogSevPrintf( + const errlogSevEnum severity,const char *pformat, ...); +epicsShareFunc int epicsShareAPI errlogSevVprintf( + const errlogSevEnum severity,const char *pformat,va_list pvar); +epicsShareFunc int epicsShareAPI errlogMessage( + const char *message); + +epicsShareFunc char * epicsShareAPI errlogGetSevEnumString( + const errlogSevEnum severity); +epicsShareFunc void epicsShareAPI errlogSetSevToLog( + const errlogSevEnum severity ); +epicsShareFunc errlogSevEnum epicsShareAPI errlogGetSevToLog(void); + +epicsShareFunc void epicsShareAPI errlogAddListener( + errlogListener listener); +epicsShareFunc void epicsShareAPI errlogRemoveListener( + errlogListener listener); + +epicsShareFunc void epicsShareAPI eltc(int yesno); +epicsShareFunc void epicsShareAPI errlogInit(int bufsize); + +/*other routines that write to log file*/ +epicsShareFunc void epicsShareAPI errPrintf(long status, const char *pFileName, + int lineno, const char *pformat, ...); + +#else /* not epicsPrintUseProtoANSI */ +epicsShareFunc int epicsShareAPI errlogPrintf(); +epicsShareFunc int epicsShareAPI errlogVprintf(); +epicsShareFunc int epicsShareAPI errlogSevPrintf(); +epicsShareFunc int epicsShareAPI errlogSevVprintf(); +epicsShareFunc int epicsShareAPI errlogMessage(); +epicsShareFunc char * epicsShareAPI errlogGetSevEnumString(); +epicsShareFunc void epicsShareAPI errlogSetSevToLog(); +epicsShareFunc errlogSevEnum epicsShareAPI errlogGetSevToLog(); +epicsShareFunc void epicsShareAPI errlogAddListener(); +epicsShareFunc void epicsShareAPI errlogRemoveListener(); +epicsShareFunc void epicsShareAPI eltc(); +epicsShareFunc void epicsShareAPI errlogInit(); +epicsShareFunc void epicsShareAPI errPrintf(); +#endif /* ifdef epicsPrintUseProtoANSI */ + +#ifdef __cplusplus +} +#endif + +#endif /*INCerrlogh*/