From 51e492fbb184fe92b9d8873cd541b6bc7138f819 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Fri, 9 Feb 2018 14:37:45 +0100 Subject: [PATCH 01/12] Fix numeric events: any number from 0 up to less than 256 is theated as an integer event. Event 0 is no event. --- src/ioc/db/dbScan.c | 84 +++++++++++++++++++++++++-------------------- src/ioc/db/dbScan.h | 2 +- 2 files changed, 47 insertions(+), 39 deletions(-) diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c index e0c48d4c3..78c098281 100644 --- a/src/ioc/db/dbScan.c +++ b/src/ioc/db/dbScan.c @@ -111,8 +111,8 @@ static char *priorityName[NUM_CALLBACK_PRIORITIES] = { typedef struct event_list { CALLBACK callback[NUM_CALLBACK_PRIORITIES]; scan_list scan_list[NUM_CALLBACK_PRIORITIES]; - struct event_list *next; - char event_name[MAX_STRING_SIZE]; + struct event_list *next; + char eventname[1]; /* actually arbitrary size */ } event_list; static event_list * volatile pevent_list[256]; static epicsMutexId event_lock; @@ -249,11 +249,6 @@ void scanAdd(struct dbCommon *precord) event_list *pel; eventname = precord->evnt; - if (strlen(eventname) >= MAX_STRING_SIZE) { - recGblRecordError(S_db_badField, (void *)precord, - "scanAdd: too long EVNT value"); - return; - } prio = precord->prio; if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) { recGblRecordError(-1, (void *)precord, @@ -317,24 +312,17 @@ void scanDelete(struct dbCommon *precord) recGblRecordError(-1, (void *)precord, "scanDelete detected illegal SCAN value"); } else if (scan == menuScanEvent) { - char* eventname; int prio; event_list *pel; scan_list *psl = 0; - eventname = precord->evnt; prio = precord->prio; if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) { recGblRecordError(-1, (void *)precord, "scanDelete detected illegal PRIO field"); return; } - do /* multithreading: make sure pel is consistent */ - pel = pevent_list[0]; - while (pel != pevent_list[0]); - for (; pel; pel=pel->next) { - if (strcmp(pel->event_name, eventname) == 0) break; - } + pel = eventNameToHandle(precord->evnt); if (pel && (psl = &pel->scan_list[prio])) deleteFromList(precord, psl); } else if (scan == menuScanI_O_Intr) { @@ -422,14 +410,12 @@ int scanpel(const char* eventname) /* print event list */ int prio; event_list *pel; - do /* multithreading: make sure pel is consistent */ - pel = pevent_list[0]; - while (pel != pevent_list[0]); - for (; pel; pel = pel->next) { - if (!eventname || strcmp(pel->event_name, eventname) == 0) { + for (pel = pevent_list[0]; pel; pel = pel->next) { + if (!eventname || epicsStrGlobMatch(pel->eventname, eventname) == 0) { for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { if (ellCount(&pel->scan_list[prio].list) == 0) continue; - sprintf(message, "Event \"%s\" Priority %s", pel->event_name, priorityName[prio]); + sprintf(message, "Event \"%.*s\" Priority %s", + sizeof(message)-25, pel->eventname, priorityName[prio]); printList(&pel->scan_list[prio], message); } } @@ -480,18 +466,50 @@ event_list *eventNameToHandle(const char *eventname) int prio; event_list *pel; static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT; + char* p; + double eventnumber; + size_t namelength; - if (!eventname || eventname[0] == 0) - return NULL; + if (!eventname) return NULL; + while (isblank(eventname[0])) eventname++; + if (!eventname[0]) return NULL; + namelength = strlen(eventname); + while (isblank(eventname[namelength-1])) namelength--; + + /* Backward compatibility with numeric events: + Treat any string that represents a double with an + integer part between 0 and 255 the same as the integer + because it is most probably a conversion from double + like from a calc record. + */ + if (epicsParseDouble(eventname, &eventnumber, &p) == 0 && + eventnumber >= 0 && eventnumber < 256 && *p == 0) + { + if (eventnumber < 1) + return NULL; /* 0 is no event */ + if ((pel = pevent_list[(int)eventnumber]) != NULL) + return pel; + } + else + eventnumber = 0; /* not a numeric event */ epicsThreadOnce(&onceId, eventOnce, NULL); epicsMutexMustLock(event_lock); for (pel = pevent_list[0]; pel; pel=pel->next) { - if (strcmp(pel->event_name, eventname) == 0) break; + if (strncmp(pel->eventname, eventname, namelength) == 0 + && pel->eventname[namelength] == 0) + break; } if (pel == NULL) { - pel = dbCalloc(1, sizeof(event_list)); - strcpy(pel->event_name, eventname); + pel = dbCalloc(1, sizeof(event_list) + namelength); + if (eventnumber > 0) + { + /* backward compatibility: make all numeric events look like integers */ + sprintf(pel->eventname, "%i", (int)eventnumber); + pevent_list[(int)eventnumber] = pel; + } + else + strncpy(pel->eventname, eventname, namelength); for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { callbackSetUser(&pel->scan_list[prio], &pel->callback[prio]); callbackSetPriority(prio, &pel->callback[prio]); @@ -501,12 +519,6 @@ event_list *eventNameToHandle(const char *eventname) } pel->next=pevent_list[0]; pevent_list[0]=pel; - { /* backward compatibility */ - char* p; - long e = strtol(eventname, &p, 0); - if (*p == 0 && e > 0 && e <= 255) - pevent_list[e] = pel; - } } epicsMutexUnlock(event_lock); return pel; @@ -518,6 +530,7 @@ void postEvent(event_list *pel) if (scanCtl != ctlRun) return; if (!pel) return; + printf("postEvent %p \"%s\"\n", pel, pel->eventname); for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { if (ellCount(&pel->scan_list[prio].list) >0) callbackRequest(&pel->callback[prio]); @@ -527,13 +540,8 @@ void postEvent(event_list *pel) /* backward compatibility */ void post_event(int event) { - event_list* pel; - if (event <= 0 || event > 255) return; - do { /* multithreading: make sure pel is consistent */ - pel = pevent_list[event]; - } while (pel != pevent_list[event]); - postEvent(pel); + postEvent(pevent_list[event]); } static void ioscanOnce(void *arg) diff --git a/src/ioc/db/dbScan.h b/src/ioc/db/dbScan.h index 28d2e133d..d3102712d 100644 --- a/src/ioc/db/dbScan.h +++ b/src/ioc/db/dbScan.h @@ -50,7 +50,7 @@ epicsShareFunc void scanCleanup(void); epicsShareFunc EVENTPVT eventNameToHandle(const char* event); epicsShareFunc void postEvent(EVENTPVT epvt); -epicsShareFunc void post_event(int event) EPICS_DEPRECATED; +epicsShareFunc void post_event(int event); epicsShareFunc void scanAdd(struct dbCommon *); epicsShareFunc void scanDelete(struct dbCommon *); epicsShareFunc double scanPeriod(int scan); From 7d836d9554fd728c3dc40915c503a7fa0cf79ab0 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Fri, 9 Feb 2018 16:58:36 +0100 Subject: [PATCH 02/12] some cleanup and scanpel improvement --- src/ioc/db/dbScan.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c index 78c098281..974cd847f 100644 --- a/src/ioc/db/dbScan.c +++ b/src/ioc/db/dbScan.c @@ -27,6 +27,7 @@ #include "epicsEvent.h" #include "epicsExit.h" #include "epicsInterrupt.h" +#include "epicsMath.h" #include "epicsMutex.h" #include "epicsPrint.h" #include "epicsRingPointer.h" @@ -412,10 +413,11 @@ int scanpel(const char* eventname) /* print event list */ for (pel = pevent_list[0]; pel; pel = pel->next) { if (!eventname || epicsStrGlobMatch(pel->eventname, eventname) == 0) { + printf("Event \"%s\"\n", pel->eventname); for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { - if (ellCount(&pel->scan_list[prio].list) == 0) continue; sprintf(message, "Event \"%.*s\" Priority %s", - sizeof(message)-25, pel->eventname, priorityName[prio]); + (int)(sizeof(message)-25), pel->eventname, priorityName[prio]); + sprintf(message, " Priority %s", priorityName[prio]); printList(&pel->scan_list[prio], message); } } @@ -466,15 +468,14 @@ event_list *eventNameToHandle(const char *eventname) int prio; event_list *pel; static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT; - char* p; double eventnumber; size_t namelength; if (!eventname) return NULL; - while (isblank(eventname[0])) eventname++; + while (isspace((unsigned char)eventname[0])) eventname++; if (!eventname[0]) return NULL; namelength = strlen(eventname); - while (isblank(eventname[namelength-1])) namelength--; + while (isspace((unsigned char)eventname[namelength-1])) namelength--; /* Backward compatibility with numeric events: Treat any string that represents a double with an @@ -482,13 +483,17 @@ event_list *eventNameToHandle(const char *eventname) because it is most probably a conversion from double like from a calc record. */ - if (epicsParseDouble(eventname, &eventnumber, &p) == 0 && - eventnumber >= 0 && eventnumber < 256 && *p == 0) + if (epicsParseDouble(eventname, &eventnumber, NULL) == 0) { - if (eventnumber < 1) - return NULL; /* 0 is no event */ - if ((pel = pevent_list[(int)eventnumber]) != NULL) - return pel; + if (!finite(eventnumber)) + return NULL; /* Inf and NaN are no events */ + if (eventnumber >= 0 && eventnumber < 256) + { + if (eventnumber < 1) + return NULL; /* 0 is no event */ + if ((pel = pevent_list[(int)eventnumber]) != NULL) + return pel; + } } else eventnumber = 0; /* not a numeric event */ @@ -530,7 +535,6 @@ void postEvent(event_list *pel) if (scanCtl != ctlRun) return; if (!pel) return; - printf("postEvent %p \"%s\"\n", pel, pel->eventname); for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { if (ellCount(&pel->scan_list[prio].list) >0) callbackRequest(&pel->callback[prio]); From adf53756162088892dece1303d604aae748a407c Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Mon, 12 Feb 2018 09:01:05 +0100 Subject: [PATCH 03/12] fix scanpel glob matching --- src/ioc/db/dbScan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c index 974cd847f..a77ec3a5a 100644 --- a/src/ioc/db/dbScan.c +++ b/src/ioc/db/dbScan.c @@ -412,7 +412,7 @@ int scanpel(const char* eventname) /* print event list */ event_list *pel; for (pel = pevent_list[0]; pel; pel = pel->next) { - if (!eventname || epicsStrGlobMatch(pel->eventname, eventname) == 0) { + if (!eventname || epicsStrGlobMatch(pel->eventname, eventname)) { printf("Event \"%s\"\n", pel->eventname); for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { sprintf(message, "Event \"%.*s\" Priority %s", From d19afc73afd01861c61462d60588595ba9d8673c Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Mon, 12 Feb 2018 12:06:12 +0100 Subject: [PATCH 04/12] Updated RELEASE_NOTES.html with soft event fix. --- documentation/RELEASE_NOTES.html | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 33f12c441..d8dd5d501 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -29,11 +29,28 @@ be put in a locally created base/configure/CONFIG_SITE.local file instead of having go modify or replace the original. A new .gitignore pattern tells git to ignore all configure/*.local files.

+

Fix problem with numeric soft events

+

Changing from numeric to named soft events introduced an incompatibility +when a numeric event is converted from a DOUBLE, e.g. from a calc record. +To make named events backward compatible to numeric events, the logic has +changed as follows:

+
  • Leading and trailing spaces are strippd from the event name +
  • Empty event names are no events +
  • If the event name can be converted to double: +
    • If the double is not finite (inf or nan) it is no event. +
    • If the double truncated to integer is between 1 and 255 + it is a numeric event. Its name is changed to the decimal + integer representation. +
    • If the double truncated to integer is 0 it is no event. +
    +
  • All other cases are named events +
+

Also scanpel has been modified to accept a glob pattern for +filtering and to show events with no connected records as well.

Changes from the 3.14 branch since 3.15.5

-

Extend maximum Posix epicsEventWaitWithTimeout() delay

The Posix implementation of epicsEventWaitWithTimeout() was limiting the From 8a3080c16fd4ac4fdba504ef79d4d275d916aef6 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Tue, 13 Feb 2018 13:50:19 +0100 Subject: [PATCH 05/12] added test for named soft events --- src/ioc/db/test/Makefile | 13 ++++ src/ioc/db/test/epicsRunDbTests.c | 2 + src/ioc/db/test/scanEventTest.c | 117 ++++++++++++++++++++++++++++++ src/ioc/db/test/scanEventTest.db | 9 +++ 4 files changed, 141 insertions(+) create mode 100644 src/ioc/db/test/scanEventTest.c create mode 100644 src/ioc/db/test/scanEventTest.db diff --git a/src/ioc/db/test/Makefile b/src/ioc/db/test/Makefile index 215545f4a..ec6b85673 100644 --- a/src/ioc/db/test/Makefile +++ b/src/ioc/db/test/Makefile @@ -138,6 +138,19 @@ testHarness_SRCS += dbPutGetTest.db TESTFILES += ../dbPutGetTest.db TESTS += testPutGetTest +TARGETS += $(COMMON_DIR)/scanEventTest.dbd +DBDDEPENDS_FILES += scanEventTest.dbd$(DEP) +scanEventTest_DBD += menuGlobal.dbd +scanEventTest_DBD += menuConvert.dbd +scanEventTest_DBD += menuScan.dbd +scanEventTest_DBD += eventRecord.dbd +scanEventTest_DBD += calcRecord.dbd +TESTPROD_HOST += scanEventTest +scanEventTest_SRCS += scanEventTest.c +scanEventTest_SRCS += scanEventTest_registerRecordDeviceDriver.cpp +scanEventTest_LIBS = dbRecStd +TESTS += scanEventTest + # This runs all the test programs in a known working order: testHarness_SRCS += epicsRunDbTests.c diff --git a/src/ioc/db/test/epicsRunDbTests.c b/src/ioc/db/test/epicsRunDbTests.c index 05fedeb51..ce41815fb 100644 --- a/src/ioc/db/test/epicsRunDbTests.c +++ b/src/ioc/db/test/epicsRunDbTests.c @@ -29,6 +29,7 @@ int testDbChannel(void); int chfPluginTest(void); int arrShorthandTest(void); int recGblCheckDeadbandTest(void); +int scanEventTest(void); void epicsRunDbTests(void) { @@ -47,6 +48,7 @@ void epicsRunDbTests(void) runTest(arrShorthandTest); runTest(recGblCheckDeadbandTest); runTest(chfPluginTest); + runTest(scanEventTest); dbmfFreeChunks(); diff --git a/src/ioc/db/test/scanEventTest.c b/src/ioc/db/test/scanEventTest.c new file mode 100644 index 000000000..e48110bcc --- /dev/null +++ b/src/ioc/db/test/scanEventTest.c @@ -0,0 +1,117 @@ +/*************************************************************************\ +* Copyright (c) 2018 Paul Scherrer Institut +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. + \*************************************************************************/ + +/* + * Author: Dirk Zimoch + */ + +#include +#include "dbStaticLib.h" +#include "dbAccessDefs.h" +#include "dbUnitTest.h" +#include "testMain.h" +#include "osiFileName.h" +#include "dbScan.h" + +void scanEventTest_registerRecordDeviceDriver(struct dbBase *); + +/* test name to event number: + num = 0 is no event, + num > 0 is numeric event + num < 0 is string event (use same unique number for aliases) +*/ +const struct {char* name; int num;} events[] = { + {"", 0}, + {" ", 0}, + {"0", 0}, + {"0.000000", 0}, + {"-0.00000", 0}, + {"0.9", 0}, + {"nan", 0}, + {"NaN", 0}, + {"-NAN", 0}, + {"-inf", 0}, + {"inf", 0}, + {"info 1", -1}, + {" info 1 ", -1}, + {"-0.9", -2}, + {"2", 2}, + {"2.000000", 2}, + {"2.5", 2}, + {" 2.5 ", 2}, + {"+0x02", 2}, + {"-2", -3}, + {"-2.000000", -4}, + {"-2.5", -5}, + {" -2.5 ", -5}, +}; + +MAIN(scanEventTest) +{ + unsigned int i; + int aliases[512] ; + int expected_count[512]; + #define INDX(i) 256-events[i].num + + testPlan(NELEMENTS(events)*2); + + memset(aliases, 0, sizeof(aliases)); + memset(expected_count, 0, sizeof(expected_count)); + + if (dbReadDatabase(&pdbbase, "scanEventTest.dbd", + "." OSI_PATH_LIST_SEPARATOR ".." OSI_PATH_LIST_SEPARATOR + "../O.Common" OSI_PATH_LIST_SEPARATOR "O.Common", NULL)) + testAbort("Database description 'scanEventTest.dbd' not found"); + + scanEventTest_registerRecordDeviceDriver(pdbbase); + for (i = 0; i < NELEMENTS(events); i++) { + char substitutions[256]; + sprintf(substitutions, "N=%d,EVENT=%s", i, events[i].name); + if (dbReadDatabase(&pdbbase, "scanEventTest.db", + "." OSI_PATH_LIST_SEPARATOR "..", substitutions)) + testAbort("Error reading test database 'scanEventTest.db'"); + } + testIocInitOk(); + for (i = 0; i < NELEMENTS(events); i++) { + EVENTPVT pev = eventNameToHandle(events[i].name); + /* test that some names are not events (num=0) */ + if (events[i].num == 0) + testOk(pev == NULL, "\"%s\" -> no event", events[i].name); + else + { + expected_count[INDX(i)]++; /* +1 for postEvent */ + if (events[i].num > 0) + { + testOk(pev != NULL, "\"%s\" -> numeric event %d", events[i].name, events[i].num); + expected_count[INDX(i)]++; /* +1 for post_event */ + } + else + { + /* test that some strings resolve the same event (num!=0) */ + if (!aliases[INDX(i)]) + { + aliases[INDX(i)] = i; + testOk(pev != NULL, "\"%s\" -> new named event", events[i].name); + } + else + { + testOk(pev == eventNameToHandle(events[aliases[INDX(i)]].name), + "\"%s\" alias for \"%s\"", events[i].name, events[aliases[INDX(i)]].name); + } + } + } + post_event(events[i].num); + postEvent(pev); + } + for (i = 0; i < NELEMENTS(events); i++) { + char pvname[100]; + sprintf(pvname, "c%d", i); + testDiag("Check if %s (event \"%s\") has processed %d times", pvname, events[i].name, expected_count[INDX(i)]); + testdbGetFieldEqual(pvname, DBR_LONG, expected_count[INDX(i)]); + } + + return testDone(); +} diff --git a/src/ioc/db/test/scanEventTest.db b/src/ioc/db/test/scanEventTest.db new file mode 100644 index 000000000..439d30da8 --- /dev/null +++ b/src/ioc/db/test/scanEventTest.db @@ -0,0 +1,9 @@ +record(calc, "c$(N)") { + field(SCAN, "Event") + field(EVNT, "$(EVENT)") + field(CALC, "VAL+1") +} +record(event, "e$(N)") { + field(SCAN, "Event") + field(VAL, "$(EVENT)") +} From 0691fc5f57fb9c6cf79669e3a0d3260c0a1a2f42 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Tue, 13 Feb 2018 14:10:29 +0100 Subject: [PATCH 06/12] fix scanEvent test --- src/ioc/db/test/scanEventTest.db | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/ioc/db/test/scanEventTest.db b/src/ioc/db/test/scanEventTest.db index 439d30da8..dbdb61f77 100644 --- a/src/ioc/db/test/scanEventTest.db +++ b/src/ioc/db/test/scanEventTest.db @@ -3,7 +3,3 @@ record(calc, "c$(N)") { field(EVNT, "$(EVENT)") field(CALC, "VAL+1") } -record(event, "e$(N)") { - field(SCAN, "Event") - field(VAL, "$(EVENT)") -} From 1e9826d1878a2a3cbbed38eea0fd1a1183213917 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Tue, 13 Feb 2018 15:36:21 +0100 Subject: [PATCH 07/12] add tests for calculated numeric soft events --- src/ioc/db/test/Makefile | 2 ++ src/ioc/db/test/devEventSoft.dbd | 1 + src/ioc/db/test/scanEventTest.c | 34 +++++++++++++++++++++++++------- src/ioc/db/test/scanEventTest.db | 11 +++++++++++ 4 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 src/ioc/db/test/devEventSoft.dbd diff --git a/src/ioc/db/test/Makefile b/src/ioc/db/test/Makefile index ec6b85673..77e485aec 100644 --- a/src/ioc/db/test/Makefile +++ b/src/ioc/db/test/Makefile @@ -144,7 +144,9 @@ scanEventTest_DBD += menuGlobal.dbd scanEventTest_DBD += menuConvert.dbd scanEventTest_DBD += menuScan.dbd scanEventTest_DBD += eventRecord.dbd +scanEventTest_DBD += devEventSoft.dbd scanEventTest_DBD += calcRecord.dbd +scanEventTest_DBD += dfanoutRecord.dbd TESTPROD_HOST += scanEventTest scanEventTest_SRCS += scanEventTest.c scanEventTest_SRCS += scanEventTest_registerRecordDeviceDriver.cpp diff --git a/src/ioc/db/test/devEventSoft.dbd b/src/ioc/db/test/devEventSoft.dbd new file mode 100644 index 000000000..ec3bc2d07 --- /dev/null +++ b/src/ioc/db/test/devEventSoft.dbd @@ -0,0 +1 @@ +device(event,CONSTANT,devEventSoft,"Soft Channel") diff --git a/src/ioc/db/test/scanEventTest.c b/src/ioc/db/test/scanEventTest.c index e48110bcc..9835b7bf8 100644 --- a/src/ioc/db/test/scanEventTest.c +++ b/src/ioc/db/test/scanEventTest.c @@ -35,14 +35,15 @@ const struct {char* name; int num;} events[] = { {"-NAN", 0}, {"-inf", 0}, {"inf", 0}, - {"info 1", -1}, - {" info 1 ", -1}, - {"-0.9", -2}, {"2", 2}, {"2.000000", 2}, {"2.5", 2}, {" 2.5 ", 2}, {"+0x02", 2}, + {"3", 3}, + {"info 1", -1}, + {" info 1 ", -1}, + {"-0.9", -2}, {"-2", -3}, {"-2.000000", -4}, {"-2.5", -5}, @@ -51,12 +52,13 @@ const struct {char* name; int num;} events[] = { MAIN(scanEventTest) { - unsigned int i; + int i, e; int aliases[512] ; int expected_count[512]; #define INDX(i) 256-events[i].num + #define MAXEV 5 - testPlan(NELEMENTS(events)*2); + testPlan(NELEMENTS(events)*2+(MAXEV+1)*5); memset(aliases, 0, sizeof(aliases)); memset(expected_count, 0, sizeof(expected_count)); @@ -75,6 +77,7 @@ MAIN(scanEventTest) testAbort("Error reading test database 'scanEventTest.db'"); } testIocInitOk(); + testDiag("Test if eventNameToHandle() strips spaces and handles numeric events"); for (i = 0; i < NELEMENTS(events); i++) { EVENTPVT pev = eventNameToHandle(events[i].name); /* test that some names are not events (num=0) */ @@ -103,13 +106,30 @@ MAIN(scanEventTest) } } } - post_event(events[i].num); + post_event(events[i].num); /* triggers numeric events only */ postEvent(pev); } + + testDiag("Check calculated numeric events (backward compatibility)"); + for (e = 0; e <= MAXEV; e++) { + testdbPutFieldOk("eventnum", DBR_LONG, e); + testdbGetFieldEqual("e1", DBR_LONG, e); + testdbGetFieldEqual("e2", DBR_LONG, e); + testdbPutFieldOk("e3", DBR_LONG, e); + testdbPutFieldOk("e3.PROC", DBR_LONG, 1); + if (e != 0) + for (i = 0; i < NELEMENTS(events); i++) + if (events[i].num == e) { + expected_count[INDX(i)]+=3; /* +1 for eventnum->e1, +1 for e2<-eventnum, +1 for e3 */ + break; + } + } + + testDiag("Check if events have been processed the expected number of times"); for (i = 0; i < NELEMENTS(events); i++) { char pvname[100]; sprintf(pvname, "c%d", i); - testDiag("Check if %s (event \"%s\") has processed %d times", pvname, events[i].name, expected_count[INDX(i)]); + testDiag("Event \"%s\" expected %d times", events[i].name, expected_count[INDX(i)]); testdbGetFieldEqual(pvname, DBR_LONG, expected_count[INDX(i)]); } diff --git a/src/ioc/db/test/scanEventTest.db b/src/ioc/db/test/scanEventTest.db index dbdb61f77..9118823d8 100644 --- a/src/ioc/db/test/scanEventTest.db +++ b/src/ioc/db/test/scanEventTest.db @@ -3,3 +3,14 @@ record(calc, "c$(N)") { field(EVNT, "$(EVENT)") field(CALC, "VAL+1") } +record(dfanout, "eventnum") { + field(OUTA, "e1 PP") + field(FLNK, "e2") +} +record(event, "e1") { +} +record(event, "e2") { + field(INP, "eventnum") +} +record(event, "e3") { +} From b2d6b67b06bd40acd31bfdbee78d353b98deacfa Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Fri, 16 Feb 2018 11:03:12 +0100 Subject: [PATCH 08/12] removed obsolete code in scanpel --- src/ioc/db/dbScan.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c index a77ec3a5a..cabd73679 100644 --- a/src/ioc/db/dbScan.c +++ b/src/ioc/db/dbScan.c @@ -415,8 +415,7 @@ int scanpel(const char* eventname) /* print event list */ if (!eventname || epicsStrGlobMatch(pel->eventname, eventname)) { printf("Event \"%s\"\n", pel->eventname); for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { - sprintf(message, "Event \"%.*s\" Priority %s", - (int)(sizeof(message)-25), pel->eventname, priorityName[prio]); + if (ellCount(&pel->scan_list[prio].list) == 0) continue; sprintf(message, " Priority %s", priorityName[prio]); printList(&pel->scan_list[prio], message); } From 29795656e6be467d541f2292b750129a64f782cf Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Tue, 20 Feb 2018 09:53:06 +0100 Subject: [PATCH 09/12] bugfix for soft events >= 256 --- src/ioc/db/dbScan.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c index cabd73679..28c3dda5e 100644 --- a/src/ioc/db/dbScan.c +++ b/src/ioc/db/dbScan.c @@ -467,7 +467,7 @@ event_list *eventNameToHandle(const char *eventname) int prio; event_list *pel; static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT; - double eventnumber; + double eventnumber = 0; size_t namelength; if (!eventname) return NULL; @@ -493,9 +493,9 @@ event_list *eventNameToHandle(const char *eventname) if ((pel = pevent_list[(int)eventnumber]) != NULL) return pel; } + else + eventnumber = 0; /* not a numeric event between 1 and 255 */ } - else - eventnumber = 0; /* not a numeric event */ epicsThreadOnce(&onceId, eventOnce, NULL); epicsMutexMustLock(event_lock); From e50c46851274f4f4cf791428a5c2bab9f1f4c677 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Mon, 26 Feb 2018 11:41:20 +0100 Subject: [PATCH 10/12] moved scanEventTest from src/ioc/db/test to src/std/rec/test --- src/ioc/db/test/Makefile | 15 --------------- src/ioc/db/test/devEventSoft.dbd | 1 - src/ioc/db/test/epicsRunDbTests.c | 2 -- src/std/rec/test/Makefile | 9 +++++++++ src/std/rec/test/epicsRunRecordTests.c | 2 ++ src/{ioc/db => std/rec}/test/scanEventTest.c | 0 src/{ioc/db => std/rec}/test/scanEventTest.db | 0 7 files changed, 11 insertions(+), 18 deletions(-) delete mode 100644 src/ioc/db/test/devEventSoft.dbd rename src/{ioc/db => std/rec}/test/scanEventTest.c (100%) rename src/{ioc/db => std/rec}/test/scanEventTest.db (100%) diff --git a/src/ioc/db/test/Makefile b/src/ioc/db/test/Makefile index 77e485aec..215545f4a 100644 --- a/src/ioc/db/test/Makefile +++ b/src/ioc/db/test/Makefile @@ -138,21 +138,6 @@ testHarness_SRCS += dbPutGetTest.db TESTFILES += ../dbPutGetTest.db TESTS += testPutGetTest -TARGETS += $(COMMON_DIR)/scanEventTest.dbd -DBDDEPENDS_FILES += scanEventTest.dbd$(DEP) -scanEventTest_DBD += menuGlobal.dbd -scanEventTest_DBD += menuConvert.dbd -scanEventTest_DBD += menuScan.dbd -scanEventTest_DBD += eventRecord.dbd -scanEventTest_DBD += devEventSoft.dbd -scanEventTest_DBD += calcRecord.dbd -scanEventTest_DBD += dfanoutRecord.dbd -TESTPROD_HOST += scanEventTest -scanEventTest_SRCS += scanEventTest.c -scanEventTest_SRCS += scanEventTest_registerRecordDeviceDriver.cpp -scanEventTest_LIBS = dbRecStd -TESTS += scanEventTest - # This runs all the test programs in a known working order: testHarness_SRCS += epicsRunDbTests.c diff --git a/src/ioc/db/test/devEventSoft.dbd b/src/ioc/db/test/devEventSoft.dbd deleted file mode 100644 index ec3bc2d07..000000000 --- a/src/ioc/db/test/devEventSoft.dbd +++ /dev/null @@ -1 +0,0 @@ -device(event,CONSTANT,devEventSoft,"Soft Channel") diff --git a/src/ioc/db/test/epicsRunDbTests.c b/src/ioc/db/test/epicsRunDbTests.c index ce41815fb..05fedeb51 100644 --- a/src/ioc/db/test/epicsRunDbTests.c +++ b/src/ioc/db/test/epicsRunDbTests.c @@ -29,7 +29,6 @@ int testDbChannel(void); int chfPluginTest(void); int arrShorthandTest(void); int recGblCheckDeadbandTest(void); -int scanEventTest(void); void epicsRunDbTests(void) { @@ -48,7 +47,6 @@ void epicsRunDbTests(void) runTest(arrShorthandTest); runTest(recGblCheckDeadbandTest); runTest(chfPluginTest); - runTest(scanEventTest); dbmfFreeChunks(); diff --git a/src/std/rec/test/Makefile b/src/std/rec/test/Makefile index 5322c8e92..70b6e173e 100644 --- a/src/std/rec/test/Makefile +++ b/src/std/rec/test/Makefile @@ -37,6 +37,15 @@ testHarness_SRCS += analogMonitorTest_registerRecordDeviceDriver.cpp TESTFILES += $(COMMON_DIR)/analogMonitorTest.dbd ../analogMonitorTest.db TESTS += analogMonitorTest +TARGETS += $(COMMON_DIR)/scanEventTest.dbd +DBDDEPENDS_FILES += scanEventTest.dbd$(DEP) +scanEventTest_DBD += base.dbd +TESTPROD_HOST += scanEventTest +scanEventTest_SRCS += scanEventTest.c +scanEventTest_SRCS += scanEventTest_registerRecordDeviceDriver.cpp +TESTFILES += $(COMMON_DIR)/scanEventTest.dbd ../scanEventTest.db +TESTS += scanEventTest + TARGETS += $(COMMON_DIR)/regressTest.dbd DBDDEPENDS_FILES += regressTest.dbd$(DEP) regressTest_DBD += base.dbd diff --git a/src/std/rec/test/epicsRunRecordTests.c b/src/std/rec/test/epicsRunRecordTests.c index 092c0a6ce..1a7133c19 100644 --- a/src/std/rec/test/epicsRunRecordTests.c +++ b/src/std/rec/test/epicsRunRecordTests.c @@ -14,6 +14,7 @@ int analogMonitorTest(void); int arrayOpTest(void); +int scanEventTest(void); void epicsRunRecordTests(void) { @@ -22,6 +23,7 @@ void epicsRunRecordTests(void) runTest(analogMonitorTest); runTest(arrayOpTest); + runTest(scanEventTest); epicsExit(0); /* Trigger test harness */ } diff --git a/src/ioc/db/test/scanEventTest.c b/src/std/rec/test/scanEventTest.c similarity index 100% rename from src/ioc/db/test/scanEventTest.c rename to src/std/rec/test/scanEventTest.c diff --git a/src/ioc/db/test/scanEventTest.db b/src/std/rec/test/scanEventTest.db similarity index 100% rename from src/ioc/db/test/scanEventTest.db rename to src/std/rec/test/scanEventTest.db From 396cf4ee3f7194b6e4939fba7708d2b87e0740aa Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Wed, 7 Mar 2018 14:49:12 +0100 Subject: [PATCH 11/12] remove special handling for inf and nan events --- src/ioc/db/dbScan.c | 5 +---- src/std/rec/test/scanEventTest.c | 29 +++++++++++++++++------------ 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c index 28c3dda5e..e9dc178a2 100644 --- a/src/ioc/db/dbScan.c +++ b/src/ioc/db/dbScan.c @@ -27,7 +27,6 @@ #include "epicsEvent.h" #include "epicsExit.h" #include "epicsInterrupt.h" -#include "epicsMath.h" #include "epicsMutex.h" #include "epicsPrint.h" #include "epicsRingPointer.h" @@ -484,8 +483,6 @@ event_list *eventNameToHandle(const char *eventname) */ if (epicsParseDouble(eventname, &eventnumber, NULL) == 0) { - if (!finite(eventnumber)) - return NULL; /* Inf and NaN are no events */ if (eventnumber >= 0 && eventnumber < 256) { if (eventnumber < 1) @@ -493,7 +490,7 @@ event_list *eventNameToHandle(const char *eventname) if ((pel = pevent_list[(int)eventnumber]) != NULL) return pel; } - else + else eventnumber = 0; /* not a numeric event between 1 and 255 */ } diff --git a/src/std/rec/test/scanEventTest.c b/src/std/rec/test/scanEventTest.c index 9835b7bf8..595264a8f 100644 --- a/src/std/rec/test/scanEventTest.c +++ b/src/std/rec/test/scanEventTest.c @@ -14,6 +14,7 @@ #include "dbUnitTest.h" #include "testMain.h" #include "osiFileName.h" +#include "epicsThread.h" #include "dbScan.h" void scanEventTest_registerRecordDeviceDriver(struct dbBase *); @@ -24,23 +25,22 @@ void scanEventTest_registerRecordDeviceDriver(struct dbBase *); num < 0 is string event (use same unique number for aliases) */ const struct {char* name; int num;} events[] = { +/* No events */ + {NULL, 0}, {"", 0}, {" ", 0}, {"0", 0}, {"0.000000", 0}, {"-0.00000", 0}, {"0.9", 0}, - {"nan", 0}, - {"NaN", 0}, - {"-NAN", 0}, - {"-inf", 0}, - {"inf", 0}, +/* Numeric events */ {"2", 2}, {"2.000000", 2}, {"2.5", 2}, {" 2.5 ", 2}, {"+0x02", 2}, {"3", 3}, +/* Named events */ {"info 1", -1}, {" info 1 ", -1}, {"-0.9", -2}, @@ -48,6 +48,11 @@ const struct {char* name; int num;} events[] = { {"-2.000000", -4}, {"-2.5", -5}, {" -2.5 ", -5}, + {"nan", -6}, + {"NaN", -7}, + {"-NAN", -8}, + {"-inf", -9}, + {"inf", -10}, }; MAIN(scanEventTest) @@ -117,14 +122,14 @@ MAIN(scanEventTest) testdbGetFieldEqual("e2", DBR_LONG, e); testdbPutFieldOk("e3", DBR_LONG, e); testdbPutFieldOk("e3.PROC", DBR_LONG, 1); - if (e != 0) - for (i = 0; i < NELEMENTS(events); i++) - if (events[i].num == e) { - expected_count[INDX(i)]+=3; /* +1 for eventnum->e1, +1 for e2<-eventnum, +1 for e3 */ - break; - } + for (i = 0; i < NELEMENTS(events); i++) + if (e > 0 && e < 256 && events[i].num == e) { /* numeric events */ + expected_count[INDX(i)]+=3; /* +1 for eventnum->e1, +1 for e2<-eventnum, +1 for e3 */ + break; + } } - + /* Allow records to finish processing */ + epicsThreadSleep(0.1); testDiag("Check if events have been processed the expected number of times"); for (i = 0; i < NELEMENTS(events); i++) { char pvname[100]; From 2b4a9632b7e21a60b80e1454e44db41d8128ad06 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Wed, 7 Mar 2018 14:51:38 +0100 Subject: [PATCH 12/12] update RELEASE_NOTES for named event fix --- documentation/RELEASE_NOTES.html | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index d8dd5d501..d19664ea1 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -16,6 +16,14 @@ +

Fix problem with numeric soft events

+

Changing from numeric to named soft events introduced an incompatibility +when a numeric event 1-255 is converted from a DOUBLE, e.g. from a calc record. +The post_event() API is not marked deprecated any more. + +

Also scanpel has been modified to accept a glob pattern for +event name filtering and to show events with no connected records as well.

+

Add osiSockOptMcastLoop_t and osiSockTest

Added a new OS-independent typedef for multicast socket options, and a test @@ -29,28 +37,11 @@ be put in a locally created base/configure/CONFIG_SITE.local file instead of having go modify or replace the original. A new .gitignore pattern tells git to ignore all configure/*.local files.

-

Fix problem with numeric soft events

-

Changing from numeric to named soft events introduced an incompatibility -when a numeric event is converted from a DOUBLE, e.g. from a calc record. -To make named events backward compatible to numeric events, the logic has -changed as follows:

-
  • Leading and trailing spaces are strippd from the event name -
  • Empty event names are no events -
  • If the event name can be converted to double: -
    • If the double is not finite (inf or nan) it is no event. -
    • If the double truncated to integer is between 1 and 255 - it is a numeric event. Its name is changed to the decimal - integer representation. -
    • If the double truncated to integer is 0 it is no event. -
    -
  • All other cases are named events -
-

Also scanpel has been modified to accept a glob pattern for -filtering and to show events with no connected records as well.

Changes from the 3.14 branch since 3.15.5

+

Extend maximum Posix epicsEventWaitWithTimeout() delay

The Posix implementation of epicsEventWaitWithTimeout() was limiting the