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