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:
@@ -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
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user