Skip to content

Commit f4c8f6d

Browse files
committed
add new iocsh function addReccasterExcludePattern
1 parent ddab4f3 commit f4c8f6d

File tree

7 files changed

+308
-0
lines changed

7 files changed

+308
-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: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,81 @@ static void addReccasterEnvVarsCallFunc(const iocshArgBuf *args)
200200
addReccasterEnvVars(&thecaster, args[0].aval.ac, args[0].aval.av);
201201
}
202202

203+
void addReccasterExcludePattern(caster_t* self, int argc, char **argv) {
204+
size_t i;
205+
int ret = 0;
206+
argv++; argc--; /* skip function arg */
207+
if (argc < 1) {
208+
errlogSevPrintf(errlogMinor, "At least one argument expected for addReccasterExcludePattern\n");
209+
return;
210+
}
211+
epicsMutexMustLock(self->lock);
212+
if (self->shutdown) {
213+
/* shutdown in progress, silent no-op */
214+
epicsMutexUnlock(self->lock);
215+
return;
216+
}
217+
/* error if called after iocInit() */
218+
if (self->current != casterStateInit) {
219+
errlogSevPrintf(errlogMinor, "addReccasterExcludePattern called after iocInit() when reccaster might already be connected. Not supported\n");
220+
epicsMutexUnlock(self->lock);
221+
return;
222+
}
223+
224+
for (i = 0; i < argc; i++) {
225+
if (strcmp(argv[i], "") == 0) {
226+
errlogSevPrintf(errlogMinor, "Arg is empty for addReccasterExcludePattern\n");
227+
}
228+
/* check duplicates */
229+
else {
230+
int dup = 0;
231+
ELLNODE *cur = ellFirst(&self->exclude_patterns);
232+
while (cur != NULL) {
233+
string_list_t *temp = (string_list_t *)cur;
234+
if (strcmp(argv[i], temp->item_str) == 0) {
235+
errlogSevPrintf(errlogMinor, "Duplicate pattern %s\n", argv[i]);
236+
dup = 1;
237+
break;
238+
}
239+
cur = ellNext(cur);
240+
}
241+
if (!dup) {
242+
string_list_t *new = malloc(sizeof(string_list_t));
243+
if (new == NULL) {
244+
errlogSevPrintf(errlogMajor, "malloc error for creating linked list node");
245+
ret = 1;
246+
break;
247+
}
248+
new->item_str = strdup(argv[i]);
249+
if (new->item_str == NULL) {
250+
errlogSevPrintf(errlogMinor, "strdup error for copying %s to new->item_str from addReccasterExcludePattern\n", argv[i]);
251+
free(new); /* frees if strdup fails */
252+
ret = 1;
253+
break;
254+
}
255+
ellAdd(&self->exclude_patterns, &new->node);
256+
}
257+
}
258+
}
259+
260+
if (ret) {
261+
errlogSevPrintf(errlogMajor, "Error in addReccasterExcludePattern - exclude patterns may not be set\n");
262+
}
263+
epicsMutexUnlock(self->lock);
264+
}
265+
266+
static const iocshArg addReccasterExcludePatternArg0 = { "excludePattern", iocshArgArgv };
267+
static const iocshArg * const addReccasterExcludePatternArgs[] = { &addReccasterExcludePatternArg0 };
268+
static const iocshFuncDef addReccasterExcludePatternFuncDef = {
269+
"addReccasterExcludePattern",
270+
1,
271+
addReccasterExcludePatternArgs
272+
};
273+
274+
static void addReccasterExcludePatternCallFunc(const iocshArgBuf *args) {
275+
addReccasterExcludePattern(&thecaster, args[0].aval.ac, args[0].aval.av);
276+
}
277+
203278
static void reccasterRegistrar(void)
204279
{
205280
osiSockAttach();
@@ -210,6 +285,7 @@ static void reccasterRegistrar(void)
210285
thepriv.laststate=casterStateInit;
211286
strcpy(thepriv.lastmsg, "Initializing");
212287
iocshRegister(&addReccasterEnvVarsFuncDef,addReccasterEnvVarsCallFunc);
288+
iocshRegister(&addReccasterExcludePatternFuncDef,addReccasterExcludePatternCallFunc);
213289
}
214290

215291
static long init_record(void* prec)

client/castApp/src/dbcb.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,21 @@ static int pushRecord(caster_t *caster, DBENTRY *pent)
8787
{
8888
dbCommon *prec = pent->precnode->precord;
8989
ssize_t rid;
90+
ELLNODE *cur;
9091
int ret = 0;
9192
long status;
9293

9394
if(dbIsAlias(pent))
9495
return 0;
9596

97+
cur = ellFirst(&caster->exclude_patterns);
98+
while (cur != NULL) {
99+
string_list_t *temp = (string_list_t *)cur;
100+
if(epicsStrGlobMatch(prec->name, temp->item_str))
101+
return 0;
102+
cur = ellNext(cur);
103+
}
104+
96105
rid = casterSendRecord(caster, prec->rdes->name, prec->name);
97106
if(rid<=0)
98107
return rid;
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
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[6];
24+
argvlist[0] = "addReccasterExcludePattern";
25+
26+
char *expectedPatterns[] =
27+
{
28+
"*_",
29+
"*__",
30+
"*:Intrnl:*",
31+
"*_internal",
32+
"_*",
33+
"*exclude_me"
34+
};
35+
int expectedNumPatterns = 0;
36+
37+
testDiag("Testing addReccasterExcludePattern with one good env");
38+
argvlist[1] = "*_";
39+
argc = 2;
40+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
41+
addReccasterExcludePattern(&caster, argc, argvlist);
42+
expectedNumPatterns++;
43+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
44+
ELLNODE *cur;
45+
cur = ellFirst(&caster.exclude_patterns);
46+
while (cur != NULL) {
47+
string_list_t *temp = (string_list_t *)cur;
48+
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
49+
i++;
50+
cur = ellNext(cur);
51+
}
52+
53+
testDiag("Testing addReccasterExcludePattern with two more patterns");
54+
argvlist[1] = "*__";
55+
argvlist[2] = "*:Intrnl:*";
56+
argc = 3;
57+
i = 0;
58+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
59+
addReccasterExcludePattern(&caster, argc, argvlist);
60+
expectedNumPatterns += 2;
61+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
62+
cur = ellFirst(&caster.exclude_patterns);
63+
while (cur != NULL) {
64+
string_list_t *temp = (string_list_t *)cur;
65+
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
66+
i++;
67+
cur = ellNext(cur);
68+
}
69+
70+
testDiag("Testing addReccasterExcludePattern with a duplicate pattern");
71+
argvlist[1] = "*_";
72+
argc = 2;
73+
i = 0;
74+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
75+
addReccasterExcludePattern(&caster, argc, argvlist);
76+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
77+
cur = ellFirst(&caster.exclude_patterns);
78+
while (cur != NULL) {
79+
string_list_t *temp = (string_list_t *)cur;
80+
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
81+
i++;
82+
cur = ellNext(cur);
83+
}
84+
85+
testDiag("Testing addReccasterExcludePattern with a new and a duplicate");
86+
argvlist[1] = "*_internal";
87+
argvlist[2] = "*__";
88+
argc = 3;
89+
i = 0;
90+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
91+
addReccasterExcludePattern(&caster, argc, argvlist);
92+
expectedNumPatterns++;
93+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
94+
cur = ellFirst(&caster.exclude_patterns);
95+
while (cur != NULL) {
96+
string_list_t *temp = (string_list_t *)cur;
97+
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
98+
i++;
99+
cur = ellNext(cur);
100+
}
101+
102+
testDiag("Testing addReccasterExcludePattern with a NULL and a new pattern");
103+
argvlist[1] = NULL;
104+
argvlist[2] = "_*";
105+
argc = 3;
106+
i = 0;
107+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
108+
addReccasterExcludePattern(&caster, argc, argvlist);
109+
expectedNumPatterns++;
110+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
111+
cur = ellFirst(&caster.exclude_patterns);
112+
while (cur != NULL) {
113+
string_list_t *temp = (string_list_t *)cur;
114+
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
115+
i++;
116+
cur = ellNext(cur);
117+
}
118+
119+
testDiag("Testing addReccasterExcludePattern with two of the same pattern");
120+
argvlist[1] = "*exclude_me";
121+
argvlist[2] = "*exclude_me";
122+
argvlist[3] = NULL;
123+
argc = 4;
124+
i = 0;
125+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
126+
addReccasterExcludePattern(&caster, argc, argvlist);
127+
expectedNumPatterns++;
128+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
129+
cur = ellFirst(&caster.exclude_patterns);
130+
while (cur != NULL) {
131+
string_list_t *temp = (string_list_t *)cur;
132+
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
133+
i++;
134+
cur = ellNext(cur);
135+
}
136+
137+
testDiag("Testing addReccasterExcludePattern with duplicates in argv and exclude pattern list");
138+
argvlist[1] = "*__";
139+
argvlist[2] = "*__";
140+
argc = 3;
141+
i = 0;
142+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
143+
addReccasterExcludePattern(&caster, argc, argvlist);
144+
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
145+
cur = ellFirst(&caster.exclude_patterns);
146+
while (cur != NULL) {
147+
string_list_t *temp = (string_list_t *)cur;
148+
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
149+
i++;
150+
cur = ellNext(cur);
151+
}
152+
153+
epicsEventSignal(caster.shutdownEvent);
154+
casterShutdown(&caster);
155+
}
156+
157+
static void testAddExcludePatternBadInput()
158+
{
159+
caster_t caster;
160+
casterInit(&caster);
161+
caster.onmsg = &testLog;
162+
163+
int argc;
164+
char *argvlist[2];
165+
argvlist[0] = "addReccasterExcludePattern";
166+
167+
testDiag("Testing addReccasterExcludePattern with no arguments");
168+
argc = 1;
169+
testOk1(caster.exclude_patterns.count==0);
170+
addReccasterExcludePattern(&caster, argc, argvlist);
171+
testOk1(caster.exclude_patterns.count==0);
172+
173+
testDiag("Testing addReccasterExcludePattern with empty string argument");
174+
argvlist[1] = "";
175+
argc = 2;
176+
testOk1(caster.exclude_patterns.count==0);
177+
addReccasterExcludePattern(&caster, argc, argvlist);
178+
testOk1(caster.exclude_patterns.count==0);
179+
180+
testDiag("Testing addReccasterExcludePattern with NULL argument");
181+
argvlist[1] = NULL;
182+
argc = 2;
183+
testOk1(caster.exclude_patterns.count==0);
184+
addReccasterExcludePattern(&caster, argc, argvlist);
185+
testOk1(caster.exclude_patterns.count==0);
186+
187+
epicsEventSignal(caster.shutdownEvent);
188+
casterShutdown(&caster);
189+
}
190+
191+
MAIN(testAddExcludePattern)
192+
{
193+
testPlan(48);
194+
osiSockAttach();
195+
testAddExcludePatternX();
196+
testAddExcludePatternBadInput();
197+
osiSockRelease();
198+
return testDone();
199+
}

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)