Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions client/castApp/src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ testAddEnvVars_SRCS += testAddEnvVars.c
testAddEnvVars_SYS_LIBS_WIN32 = ws2_32
TESTS += testAddEnvVars

TESTPROD_HOST += testAddExcludePattern
testAddExcludePattern_SRCS += testAddExcludePattern.c
testAddExcludePattern_SYS_LIBS_WIN32 = ws2_32
TESTS += testAddExcludePattern

TESTSCRIPTS_HOST += $(TESTS:%=%.t)
ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),)
TESTPROD = $(TESTPROD_HOST)
Expand Down
5 changes: 5 additions & 0 deletions client/castApp/src/caster.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ void casterInit(caster_t *self)
self->onmsg = &casterShowMsgDefault;
self->current = casterStateInit;
self->timeout = reccastTimeout;
ellInit(&self->exclude_patterns);

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

epicsMutexMustLock(self->lock);
ellFree(&self->exclude_patterns);
epicsMutexUnlock(self->lock);

epicsEventDestroy(self->shutdownEvent);
self->shutdownEvent = NULL;
if (self->wakeup[0] != INVALID_SOCKET) {
Expand Down
11 changes: 11 additions & 0 deletions client/castApp/src/caster.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <epicsEvent.h>
#include <epicsMutex.h>
#include <compilerDependencies.h>
#include <ellLib.h>

#include "sockhelpers.h"

Expand All @@ -35,6 +36,11 @@ typedef enum {
casterStateDone,
} casterState;

typedef struct {
ELLNODE node;
char *item_str;
} string_list_t;

typedef struct _caster_t {
double timeout;

Expand Down Expand Up @@ -71,6 +77,8 @@ typedef struct _caster_t {
char **extra_envs;
int num_extra_envs;

ELLLIST exclude_patterns;

} caster_t;

epicsShareFunc
Expand Down Expand Up @@ -101,6 +109,9 @@ int casterPushPDB(void *junk, caster_t *caster);
epicsShareFunc
void addReccasterEnvVars(caster_t* self, int argc, char **argv);

epicsShareFunc
void addReccasterExcludePattern(caster_t* self, int argc, char **argv);

/* internal */

epicsShareFunc
Expand Down
66 changes: 66 additions & 0 deletions client/castApp/src/castinit.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <epicsExit.h>
#include <epicsMutex.h>
#include <epicsAssert.h>
#include <cantProceed.h>
#include <dbDefs.h>
#include <iocsh.h>
#include <errlog.h>

Expand Down Expand Up @@ -200,6 +202,69 @@ static void addReccasterEnvVarsCallFunc(const iocshArgBuf *args)
addReccasterEnvVars(&thecaster, args[0].aval.ac, args[0].aval.av);
}

void addReccasterExcludePattern(caster_t* self, int argc, char **argv) {
size_t i;
int dup;
ELLNODE *cur;
argv++; argc--; /* skip function arg */
if (argc < 1) {
errlogSevPrintf(errlogMinor, "At least one argument expected for addReccasterExcludePattern\n");
return;
}
epicsMutexMustLock(self->lock);
if (self->shutdown) {
/* shutdown in progress, silent no-op */
epicsMutexUnlock(self->lock);
return;
}
/* error if called after iocInit() */
if (self->current != casterStateInit) {
errlogSevPrintf(errlogMinor, "addReccasterExcludePattern called after iocInit() when reccaster might already be connected. Not supported\n");
epicsMutexUnlock(self->lock);
return;
}

for (i = 0; i < argc; i++) {
const size_t arg_len = strlen(argv[i]) + 1;
if (argv[i][0] == '\0') {
errlogSevPrintf(errlogMinor, "Arg is empty for addReccasterExcludePattern\n");
continue;
}
/* check duplicates */
dup = 0;
for(cur = ellFirst(&self->exclude_patterns); cur; cur = ellNext(cur)) {
const string_list_t *ppattern = CONTAINER(cur, string_list_t, node);
if (strcmp(argv[i], ppattern->item_str) == 0) {
dup = 1;
break;
}
}
if (dup) {
errlogSevPrintf(errlogMinor, "Duplicate pattern %s in addReccasterExcludePattern\n", argv[i]);
continue;
}
string_list_t *new_node = mallocMustSucceed(sizeof(string_list_t) + arg_len, "addReccasterExcludePattern");
new_node->item_str = (char *)(new_node + 1);
memcpy(new_node->item_str, argv[i], arg_len);

ellAdd(&self->exclude_patterns, &new_node->node);
}

epicsMutexUnlock(self->lock);
}

static const iocshArg addReccasterExcludePatternArg0 = { "excludePattern", iocshArgArgv };
static const iocshArg * const addReccasterExcludePatternArgs[] = { &addReccasterExcludePatternArg0 };
static const iocshFuncDef addReccasterExcludePatternFuncDef = {
"addReccasterExcludePattern",
1,
addReccasterExcludePatternArgs
};

static void addReccasterExcludePatternCallFunc(const iocshArgBuf *args) {
addReccasterExcludePattern(&thecaster, args[0].aval.ac, args[0].aval.av);
}

static void reccasterRegistrar(void)
{
osiSockAttach();
Expand All @@ -210,6 +275,7 @@ static void reccasterRegistrar(void)
thepriv.laststate=casterStateInit;
strcpy(thepriv.lastmsg, "Initializing");
iocshRegister(&addReccasterEnvVarsFuncDef,addReccasterEnvVarsCallFunc);
iocshRegister(&addReccasterExcludePatternFuncDef,addReccasterExcludePatternCallFunc);
}

static long init_record(void* prec)
Expand Down
8 changes: 8 additions & 0 deletions client/castApp/src/dbcb.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <epicsVersion.h>
#include <epicsString.h>
#include <envDefs.h>
#include <dbDefs.h>

#include <dbStaticLib.h>
#include <dbAccess.h>
Expand Down Expand Up @@ -87,12 +88,19 @@ static int pushRecord(caster_t *caster, DBENTRY *pent)
{
dbCommon *prec = pent->precnode->precord;
ssize_t rid;
ELLNODE *cur;
int ret = 0;
long status;

if(dbIsAlias(pent))
return 0;

for(cur = ellFirst(&caster->exclude_patterns); cur; cur = ellNext(cur)) {
const string_list_t *ppattern = CONTAINER(cur, string_list_t, node);
if(epicsStrGlobMatch(prec->name, ppattern->item_str))
return 0;
}

rid = casterSendRecord(caster, prec->rdes->name, prec->name);
if(rid<=0)
return rid;
Expand Down
173 changes: 173 additions & 0 deletions client/castApp/src/testAddExcludePattern.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
#include <string.h>

#include <epicsUnitTest.h>
#include <testMain.h>

#include "caster.h"

void* epicsRtemsFSImage;

static void testLog(void* arg, struct _caster_t* self)
{
testDiag("ERR %s", self->lastmsg);
}

static void testAddExcludePatternX(void)
{
int i = 0;
caster_t caster;
casterInit(&caster);
caster.onmsg = &testLog;

int argc;
char *argvlist[5];
argvlist[0] = "addReccasterExcludePattern";

char *expectedPatterns[] =
{
"*_",
"*__",
"*:Intrnl:*",
"*_internal",
"*exclude_me"
};
int expectedNumPatterns = 0;

testDiag("Testing addReccasterExcludePattern with one good env");
argvlist[1] = "*_";
argc = 2;
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
addReccasterExcludePattern(&caster, argc, argvlist);
expectedNumPatterns++;
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
ELLNODE *cur;
cur = ellFirst(&caster.exclude_patterns);
while (cur != NULL) {
string_list_t *temp = (string_list_t *)cur;
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
i++;
cur = ellNext(cur);
}

testDiag("Testing addReccasterExcludePattern with two more patterns");
argvlist[1] = "*__";
argvlist[2] = "*:Intrnl:*";
argc = 3;
i = 0;
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
addReccasterExcludePattern(&caster, argc, argvlist);
expectedNumPatterns += 2;
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
cur = ellFirst(&caster.exclude_patterns);
while (cur != NULL) {
string_list_t *temp = (string_list_t *)cur;
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
i++;
cur = ellNext(cur);
}

testDiag("Testing addReccasterExcludePattern with a duplicate pattern");
argvlist[1] = "*_";
argc = 2;
i = 0;
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
addReccasterExcludePattern(&caster, argc, argvlist);
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
cur = ellFirst(&caster.exclude_patterns);
while (cur != NULL) {
string_list_t *temp = (string_list_t *)cur;
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
i++;
cur = ellNext(cur);
}

testDiag("Testing addReccasterExcludePattern with a new and a duplicate");
argvlist[1] = "*_internal";
argvlist[2] = "*__";
argc = 3;
i = 0;
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
addReccasterExcludePattern(&caster, argc, argvlist);
expectedNumPatterns++;
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
cur = ellFirst(&caster.exclude_patterns);
while (cur != NULL) {
string_list_t *temp = (string_list_t *)cur;
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
i++;
cur = ellNext(cur);
}

testDiag("Testing addReccasterExcludePattern with two of the same pattern");
argvlist[1] = "*exclude_me";
argvlist[2] = "*exclude_me";
argc = 3;
i = 0;
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
addReccasterExcludePattern(&caster, argc, argvlist);
expectedNumPatterns++;
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
cur = ellFirst(&caster.exclude_patterns);
while (cur != NULL) {
string_list_t *temp = (string_list_t *)cur;
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
i++;
cur = ellNext(cur);
}

testDiag("Testing addReccasterExcludePattern with duplicates in argv and exclude pattern list");
argvlist[1] = "*__";
argvlist[2] = "*__";
argc = 3;
i = 0;
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
addReccasterExcludePattern(&caster, argc, argvlist);
testOk1(caster.exclude_patterns.count==expectedNumPatterns);
cur = ellFirst(&caster.exclude_patterns);
while (cur != NULL) {
string_list_t *temp = (string_list_t *)cur;
testOk1(strcmp(temp->item_str, expectedPatterns[i]) == 0);
i++;
cur = ellNext(cur);
}

epicsEventSignal(caster.shutdownEvent);
casterShutdown(&caster);
}

static void testAddExcludePatternBadInput()
{
caster_t caster;
casterInit(&caster);
caster.onmsg = &testLog;

int argc;
char *argvlist[2];
argvlist[0] = "addReccasterExcludePattern";

testDiag("Testing addReccasterExcludePattern with no arguments");
argc = 1;
testOk1(caster.exclude_patterns.count==0);
addReccasterExcludePattern(&caster, argc, argvlist);
testOk1(caster.exclude_patterns.count==0);

testDiag("Testing addReccasterExcludePattern with empty string argument");
argvlist[1] = "";
argc = 2;
testOk1(caster.exclude_patterns.count==0);
addReccasterExcludePattern(&caster, argc, argvlist);
testOk1(caster.exclude_patterns.count==0);

epicsEventSignal(caster.shutdownEvent);
casterShutdown(&caster);
}

MAIN(testAddExcludePattern)
{
testPlan(37);
osiSockAttach();
testAddExcludePatternX();
testAddExcludePatternBadInput();
osiSockRelease();
return testDone();
}
3 changes: 3 additions & 0 deletions client/iocBoot/iocdemo/st.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ epicsEnvSet("SECTOR", "mysector")
addReccasterEnvVars("CONTACT", "SECTOR")
addReccasterEnvVars("BUILDING")

addReccasterExcludePattern("*_", "*__")
addReccasterExcludePattern("*exclude_this")

## Load record instances
dbLoadRecords("../../db/reccaster.db", "P=$(IOCSH_NAME):")
dbLoadRecords("../../db/somerecords.db","P=$(IOCSH_NAME):")
Expand Down