Skip to content

Commit 10cbe2f

Browse files
authored
Merge pull request #112 from madelinespark/madeline
Reccaster exclusion pattern for record filtering
2 parents 973fdf8 + 31d290b commit 10cbe2f

File tree

7 files changed

+271
-0
lines changed

7 files changed

+271
-0
lines changed

client/castApp/src/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ testAddEnvVars_SRCS += testAddEnvVars.c
4848
testAddEnvVars_SYS_LIBS_WIN32 = ws2_32
4949
TESTS += testAddEnvVars
5050

51+
TESTPROD_HOST += testAddExcludePattern
52+
testAddExcludePattern_SRCS += testAddExcludePattern.c
53+
testAddExcludePattern_SYS_LIBS_WIN32 = ws2_32
54+
TESTS += testAddExcludePattern
55+
5156
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
5257
ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),)
5358
TESTPROD = $(TESTPROD_HOST)

client/castApp/src/caster.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ void casterInit(caster_t *self)
114114
self->onmsg = &casterShowMsgDefault;
115115
self->current = casterStateInit;
116116
self->timeout = reccastTimeout;
117+
ellInit(&self->exclude_patterns);
117118

118119
if(shSocketPair(self->wakeup))
119120
errlogPrintf("Error: casterInit failed to create shutdown socket: %d\n", SOCKERRNO);
@@ -142,6 +143,10 @@ void casterShutdown(caster_t *self)
142143
free(self->extra_envs);
143144
epicsMutexUnlock(self->lock);
144145

146+
epicsMutexMustLock(self->lock);
147+
ellFree(&self->exclude_patterns);
148+
epicsMutexUnlock(self->lock);
149+
145150
epicsEventDestroy(self->shutdownEvent);
146151
self->shutdownEvent = NULL;
147152
if (self->wakeup[0] != INVALID_SOCKET) {

client/castApp/src/caster.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <epicsEvent.h>
1313
#include <epicsMutex.h>
1414
#include <compilerDependencies.h>
15+
#include <ellLib.h>
1516

1617
#include "sockhelpers.h"
1718

@@ -35,6 +36,11 @@ typedef enum {
3536
casterStateDone,
3637
} casterState;
3738

39+
typedef struct {
40+
ELLNODE node;
41+
char *item_str;
42+
} string_list_t;
43+
3844
typedef struct _caster_t {
3945
double timeout;
4046

@@ -71,6 +77,8 @@ typedef struct _caster_t {
7177
char **extra_envs;
7278
int num_extra_envs;
7379

80+
ELLLIST exclude_patterns;
81+
7482
} caster_t;
7583

7684
epicsShareFunc
@@ -101,6 +109,9 @@ int casterPushPDB(void *junk, caster_t *caster);
101109
epicsShareFunc
102110
void addReccasterEnvVars(caster_t* self, int argc, char **argv);
103111

112+
epicsShareFunc
113+
void addReccasterExcludePattern(caster_t* self, int argc, char **argv);
114+
104115
/* internal */
105116

106117
epicsShareFunc

client/castApp/src/castinit.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <epicsExit.h>
1010
#include <epicsMutex.h>
1111
#include <epicsAssert.h>
12+
#include <cantProceed.h>
13+
#include <dbDefs.h>
1214
#include <iocsh.h>
1315
#include <errlog.h>
1416

@@ -206,6 +208,69 @@ static void addReccasterEnvVarsCallFunc(const iocshArgBuf *args)
206208
addReccasterEnvVars(&thecaster, args[0].aval.ac, args[0].aval.av);
207209
}
208210

211+
void addReccasterExcludePattern(caster_t* self, int argc, char **argv) {
212+
size_t i;
213+
int dup;
214+
ELLNODE *cur;
215+
argv++; argc--; /* skip function arg */
216+
if (argc < 1) {
217+
errlogSevPrintf(errlogMinor, "At least one argument expected for addReccasterExcludePattern\n");
218+
return;
219+
}
220+
epicsMutexMustLock(self->lock);
221+
if (self->shutdown) {
222+
/* shutdown in progress, silent no-op */
223+
epicsMutexUnlock(self->lock);
224+
return;
225+
}
226+
/* error if called after iocInit() */
227+
if (self->current != casterStateInit) {
228+
errlogSevPrintf(errlogMinor, "addReccasterExcludePattern called after iocInit() when reccaster might already be connected. Not supported\n");
229+
epicsMutexUnlock(self->lock);
230+
return;
231+
}
232+
233+
for (i = 0; i < argc; i++) {
234+
const size_t arg_len = strlen(argv[i]) + 1;
235+
if (argv[i][0] == '\0') {
236+
errlogSevPrintf(errlogMinor, "Arg is empty for addReccasterExcludePattern\n");
237+
continue;
238+
}
239+
/* check duplicates */
240+
dup = 0;
241+
for(cur = ellFirst(&self->exclude_patterns); cur; cur = ellNext(cur)) {
242+
const string_list_t *ppattern = CONTAINER(cur, string_list_t, node);
243+
if (strcmp(argv[i], ppattern->item_str) == 0) {
244+
dup = 1;
245+
break;
246+
}
247+
}
248+
if (dup) {
249+
errlogSevPrintf(errlogMinor, "Duplicate pattern %s in addReccasterExcludePattern\n", argv[i]);
250+
continue;
251+
}
252+
string_list_t *new_node = mallocMustSucceed(sizeof(string_list_t) + arg_len, "addReccasterExcludePattern");
253+
new_node->item_str = (char *)(new_node + 1);
254+
memcpy(new_node->item_str, argv[i], arg_len);
255+
256+
ellAdd(&self->exclude_patterns, &new_node->node);
257+
}
258+
259+
epicsMutexUnlock(self->lock);
260+
}
261+
262+
static const iocshArg addReccasterExcludePatternArg0 = { "excludePattern", iocshArgArgv };
263+
static const iocshArg * const addReccasterExcludePatternArgs[] = { &addReccasterExcludePatternArg0 };
264+
static const iocshFuncDef addReccasterExcludePatternFuncDef = {
265+
"addReccasterExcludePattern",
266+
1,
267+
addReccasterExcludePatternArgs
268+
};
269+
270+
static void addReccasterExcludePatternCallFunc(const iocshArgBuf *args) {
271+
addReccasterExcludePattern(&thecaster, args[0].aval.ac, args[0].aval.av);
272+
}
273+
209274
static void reccasterRegistrar(void)
210275
{
211276
osiSockAttach();
@@ -216,6 +281,7 @@ static void reccasterRegistrar(void)
216281
thepriv.laststate=casterStateInit;
217282
strcpy(thepriv.lastmsg, "Initializing");
218283
iocshRegister(&addReccasterEnvVarsFuncDef,addReccasterEnvVarsCallFunc);
284+
iocshRegister(&addReccasterExcludePatternFuncDef,addReccasterExcludePatternCallFunc);
219285
}
220286

221287
static long drv_report(int lvl)

client/castApp/src/dbcb.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <epicsVersion.h>
33
#include <epicsString.h>
44
#include <envDefs.h>
5+
#include <dbDefs.h>
56

67
#include <dbStaticLib.h>
78
#include <dbAccess.h>
@@ -87,12 +88,19 @@ static int pushRecord(caster_t *caster, DBENTRY *pent)
8788
{
8889
dbCommon *prec = pent->precnode->precord;
8990
ssize_t rid;
91+
ELLNODE *cur;
9092
int ret = 0;
9193
long status;
9294

9395
if(dbIsAlias(pent))
9496
return 0;
9597

98+
for(cur = ellFirst(&caster->exclude_patterns); cur; cur = ellNext(cur)) {
99+
const string_list_t *ppattern = CONTAINER(cur, string_list_t, node);
100+
if(epicsStrGlobMatch(prec->name, ppattern->item_str))
101+
return 0;
102+
}
103+
96104
rid = casterSendRecord(caster, prec->rdes->name, prec->name);
97105
if(rid<=0)
98106
return rid;
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
#include <string.h>
2+
3+
#include <epicsUnitTest.h>
4+
#include <testMain.h>
5+
6+
#include "caster.h"
7+
8+
void* epicsRtemsFSImage;
9+
10+
static void testLog(void* arg, struct _caster_t* self)
11+
{
12+
testDiag("ERR %s", self->lastmsg);
13+
}
14+
15+
static void testAddExcludePatternX(void)
16+
{
17+
int i = 0;
18+
caster_t caster;
19+
casterInit(&caster);
20+
caster.onmsg = &testLog;
21+
22+
int argc;
23+
char *argvlist[5];
24+
argvlist[0] = "addReccasterExcludePattern";
25+
26+
char *expectedPatterns[] =
27+
{
28+
"*_",
29+
"*__",
30+
"*:Intrnl:*",
31+
"*_internal",
32+
"*exclude_me"
33+
};
34+
int expectedNumPatterns = 0;
35+
36+
testDiag("Testing addReccasterExcludePattern with one good env");
37+
argvlist[1] = "*_";
38+
argc = 2;
39+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
40+
addReccasterExcludePattern(&caster, argc, argvlist);
41+
expectedNumPatterns++;
42+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
43+
ELLNODE *cur;
44+
cur = ellFirst(&caster.exclude_patterns);
45+
while (cur != NULL) {
46+
string_list_t *temp = (string_list_t *)cur;
47+
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
48+
i++;
49+
cur = ellNext(cur);
50+
}
51+
52+
testDiag("Testing addReccasterExcludePattern with two more patterns");
53+
argvlist[1] = "*__";
54+
argvlist[2] = "*:Intrnl:*";
55+
argc = 3;
56+
i = 0;
57+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
58+
addReccasterExcludePattern(&caster, argc, argvlist);
59+
expectedNumPatterns += 2;
60+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
61+
cur = ellFirst(&caster.exclude_patterns);
62+
while (cur != NULL) {
63+
string_list_t *temp = (string_list_t *)cur;
64+
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
65+
i++;
66+
cur = ellNext(cur);
67+
}
68+
69+
testDiag("Testing addReccasterExcludePattern with a duplicate pattern");
70+
argvlist[1] = "*_";
71+
argc = 2;
72+
i = 0;
73+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
74+
addReccasterExcludePattern(&caster, argc, argvlist);
75+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
76+
cur = ellFirst(&caster.exclude_patterns);
77+
while (cur != NULL) {
78+
string_list_t *temp = (string_list_t *)cur;
79+
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
80+
i++;
81+
cur = ellNext(cur);
82+
}
83+
84+
testDiag("Testing addReccasterExcludePattern with a new and a duplicate");
85+
argvlist[1] = "*_internal";
86+
argvlist[2] = "*__";
87+
argc = 3;
88+
i = 0;
89+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
90+
addReccasterExcludePattern(&caster, argc, argvlist);
91+
expectedNumPatterns++;
92+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
93+
cur = ellFirst(&caster.exclude_patterns);
94+
while (cur != NULL) {
95+
string_list_t *temp = (string_list_t *)cur;
96+
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
97+
i++;
98+
cur = ellNext(cur);
99+
}
100+
101+
testDiag("Testing addReccasterExcludePattern with two of the same pattern");
102+
argvlist[1] = "*exclude_me";
103+
argvlist[2] = "*exclude_me";
104+
argc = 3;
105+
i = 0;
106+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
107+
addReccasterExcludePattern(&caster, argc, argvlist);
108+
expectedNumPatterns++;
109+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
110+
cur = ellFirst(&caster.exclude_patterns);
111+
while (cur != NULL) {
112+
string_list_t *temp = (string_list_t *)cur;
113+
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
114+
i++;
115+
cur = ellNext(cur);
116+
}
117+
118+
testDiag("Testing addReccasterExcludePattern with duplicates in argv and exclude pattern list");
119+
argvlist[1] = "*__";
120+
argvlist[2] = "*__";
121+
argc = 3;
122+
i = 0;
123+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
124+
addReccasterExcludePattern(&caster, argc, argvlist);
125+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
126+
cur = ellFirst(&caster.exclude_patterns);
127+
while (cur != NULL) {
128+
string_list_t *temp = (string_list_t *)cur;
129+
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
130+
i++;
131+
cur = ellNext(cur);
132+
}
133+
134+
epicsEventSignal(caster.shutdownEvent);
135+
casterShutdown(&caster);
136+
}
137+
138+
static void testAddExcludePatternBadInput()
139+
{
140+
caster_t caster;
141+
casterInit(&caster);
142+
caster.onmsg = &testLog;
143+
144+
int argc;
145+
char *argvlist[2];
146+
argvlist[0] = "addReccasterExcludePattern";
147+
148+
testDiag("Testing addReccasterExcludePattern with no arguments");
149+
argc = 1;
150+
testOk1(caster.exclude_patterns.count==0);
151+
addReccasterExcludePattern(&caster, argc, argvlist);
152+
testOk1(caster.exclude_patterns.count==0);
153+
154+
testDiag("Testing addReccasterExcludePattern with empty string argument");
155+
argvlist[1] = "";
156+
argc = 2;
157+
testOk1(caster.exclude_patterns.count==0);
158+
addReccasterExcludePattern(&caster, argc, argvlist);
159+
testOk1(caster.exclude_patterns.count==0);
160+
161+
epicsEventSignal(caster.shutdownEvent);
162+
casterShutdown(&caster);
163+
}
164+
165+
MAIN(testAddExcludePattern)
166+
{
167+
testPlan(37);
168+
osiSockAttach();
169+
testAddExcludePatternX();
170+
testAddExcludePatternBadInput();
171+
osiSockRelease();
172+
return testDone();
173+
}

client/iocBoot/iocdemo/st.cmd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ epicsEnvSet("SECTOR", "mysector")
2323
addReccasterEnvVars("CONTACT", "SECTOR")
2424
addReccasterEnvVars("BUILDING")
2525

26+
addReccasterExcludePattern("*_", "*__")
27+
addReccasterExcludePattern("*exclude_this")
28+
2629
## Load record instances
2730
dbLoadRecords("../../db/reccaster.db", "P=$(IOCSH_NAME):")
2831
dbLoadRecords("../../db/somerecords.db","P=$(IOCSH_NAME):")

0 commit comments

Comments
 (0)