Allow adding error symbols after early initialization

This was acomplished by making errSymbolAdd add the error symbol directly
into the global hash table and removing errnumlist which is not needed
anymore.

Unit tests were added for checking the following cases:
- Adding a valid symbol and checking that it exists (fixed by this change)
- Getting an existing error symbol
- Getting a non existing error symbol
- Adding an invalid error symbol (fixed by this change)
- Adding an error symbol with a code that already
  exists (fixed by this change)

Therefore, issue #268 was fixed
This commit is contained in:
Emilio Perez
2023-03-08 14:48:02 +00:00
committed by Dirk Zimoch
parent 485ac85fa5
commit 0cd56fa40b
5 changed files with 83 additions and 35 deletions

View File

@@ -26,6 +26,7 @@ ERR_S_FILES += $(LIBCOM)/as/asLib.h
ERR_S_FILES += $(LIBCOM)/misc/epicsStdlib.h
ERR_S_FILES += $(LIBCOM)/pool/epicsThreadPool.h
ERR_S_FILES += $(LIBCOM)/error/errMdef.h
ERR_S_FILES += $(LIBCOM)/error/errSymTbl.h
ERR_S_FILES += $(TOP)/modules/database/src/ioc/db/dbAccessDefs.h
ERR_S_FILES += $(TOP)/modules/database/src/ioc/dbStatic/dbStaticLib.h

View File

@@ -32,6 +32,7 @@
#define M_stdlib (504 << 16) /* EPICS Standard library */
#define M_pool (505 << 16) /* Thread pool */
#define M_time (506 << 16) /* epicsTime */
#define M_err (507 << 16) /* Error */
/* ioc */
#define M_dbAccess (511 << 16) /* Database Access Routines */

View File

@@ -33,14 +33,12 @@
static epicsUInt16 errhash(long errNum);
typedef struct errnumnode {
ELLNODE node;
long errNum;
struct errnumnode *hashnode;
const char *message;
long pad;
} ERRNUMNODE;
static ELLLIST errnumlist = ELLLIST_INIT;
static ERRNUMNODE **hashtable;
static int initialized = 0;
extern ERRSYMTAB_ID errSymTbl;
@@ -56,44 +54,20 @@ extern ERRSYMTAB_ID errSymTbl;
int errSymBld(void)
{
ERRSYMBOL *errArray = errSymTbl->symbols;
ERRNUMNODE *perrNumNode = NULL;
ERRNUMNODE *pNextNode = NULL;
ERRNUMNODE **phashnode = NULL;
int i;
int modnum;
if (initialized)
return(0);
hashtable = (ERRNUMNODE**)callocMustSucceed
(NHASH, sizeof(ERRNUMNODE*),"errSymBld");
for (i = 0; i < errSymTbl->nsymbols; i++, errArray++) {
modnum = errArray->errNum >> 16;
if (modnum < 501) {
fprintf(stderr, "errSymBld: ERROR - Module number in errSymTbl < 501 was Module=%lx Name=%s\n",
errArray->errNum, errArray->name);
continue;
}
if ((errSymbolAdd(errArray->errNum, errArray->name)) < 0) {
fprintf(stderr, "errSymBld: ERROR - errSymbolAdd() failed \n");
continue;
}
}
perrNumNode = (ERRNUMNODE *) ellFirst(&errnumlist);
while (perrNumNode) {
/* hash each perrNumNode->errNum */
epicsUInt16 hashInd = errhash(perrNumNode->errNum);
phashnode = (ERRNUMNODE**)&hashtable[hashInd];
pNextNode = (ERRNUMNODE*) *phashnode;
/* search for last node (NULL) of hashnode linked list */
while (pNextNode) {
phashnode = &pNextNode->hashnode;
pNextNode = *phashnode;
for (i = 0; i < errSymTbl->nsymbols; i++, errArray++) {
if (errSymbolAdd(errArray->errNum, errArray->name)) {
fprintf(stderr, "errSymBld: ERROR - errSymbolAdd() failed \n");
}
*phashnode = perrNumNode;
perrNumNode = (ERRNUMNODE *) ellNext((ELLNODE *) perrNumNode);
}
initialized = 1;
return(0);
}
@@ -114,16 +88,38 @@ static epicsUInt16 errhash(long errNum)
/****************************************************************
* ERRSYMBOLADD
* adds symbols to the master errnumlist as compiled from errSymTbl.c
* adds symbols to the global error symbol hash table
***************************************************************/
int errSymbolAdd(long errNum, const char *name)
{
ERRNUMNODE *pNew = (ERRNUMNODE*) callocMustSucceed(1,
sizeof(ERRNUMNODE), "errSymbolAdd");
ERRNUMNODE *pNextNode = NULL;
ERRNUMNODE **phashnode = NULL;
ERRNUMNODE *pNew = NULL;
int modnum = (epicsUInt16) (errNum >> 16);
if (modnum < 501)
return S_err_invCode;
epicsUInt16 hashInd = errhash(errNum);
phashnode = (ERRNUMNODE**)&hashtable[hashInd];
pNextNode = (ERRNUMNODE*) *phashnode;
/* search for last node (NULL) of hashnode linked list */
while (pNextNode) {
if (pNextNode->errNum == errNum) {
return S_err_codeExists;
}
phashnode = &pNextNode->hashnode;
pNextNode = *phashnode;
}
pNew = (ERRNUMNODE*) callocMustSucceed(
1, sizeof(ERRNUMNODE), "errSymbolAdd");
pNew->errNum = errNum;
pNew->message = name;
ellAdd(&errnumlist, (ELLNODE*)pNew);
*phashnode = pNew;
return 0;
}

View File

@@ -16,6 +16,9 @@
#include "libComAPI.h"
#include "epicsTypes.h"
#define S_err_invCode (M_err | 1) /* Invalid error symbol code */
#define S_err_codeExists (M_err | 2) /* Error code already exists */
/* ERRSYMBOL - entry in symbol table */
typedef struct {
long errNum; /* errMessage symbol number */

View File

@@ -29,6 +29,7 @@
#include "osiSock.h"
#include "fdmgr.h"
#include "epicsString.h"
#include "errSymTbl.h"
/* private between errlog.c and this test */
LIBCOM_API
@@ -197,13 +198,53 @@ void testANSIStrip(void)
#undef testEscape
}
static void testErrorMessageMatches(long status, const char *expected)
{
const char *msg = errSymMsg(status);
testOk(strcmp(msg, expected) == 0,
"Error code %ld returns \"%s\", expected message \"%s\"", status,
msg, expected
);
}
static void testGettingExistingErrorSymbol()
{
testErrorMessageMatches(S_err_invCode, "Invalid error symbol code");
}
static void testGettingNonExistingErrorSymbol()
{
long invented_code = (0x7999 << 16) | 0x9998;
testErrorMessageMatches(invented_code, "<Unknown code>");
}
static void testAddingErrorSymbol()
{
long invented_code = (0x7999 << 16) | 0x9999;
errSymbolAdd(invented_code, "Invented Error Message");
testErrorMessageMatches(invented_code, "Invented Error Message");
}
static void testAddingInvalidErrorSymbol()
{
long invented_code = (500 << 16) | 0x1;
testOk(errSymbolAdd(invented_code, "No matter"),
"Adding error symbol with module code < 501 should fail");
}
static void testAddingExistingErrorSymbol()
{
testOk(errSymbolAdd(S_err_invCode, "Duplicate"),
"Adding an error symbol with an existing error code should fail");
}
MAIN(epicsErrlogTest)
{
size_t mlen, i, N;
char msg[256];
clientPvt pvt, pvt2;
testPlan(48);
testPlan(53);
testANSIStrip();
@@ -414,6 +455,12 @@ MAIN(epicsErrlogTest)
testLogPrefix();
osiSockRelease();
testGettingExistingErrorSymbol();
testGettingNonExistingErrorSymbol();
testAddingErrorSymbol();
testAddingInvalidErrorSymbol();
testAddingExistingErrorSymbol();
return testDone();
}
/*