add testing lset
This commit is contained in:
committed by
Andrew Johnson
parent
00549c832a
commit
428dfe7a5c
@@ -20,6 +20,7 @@ dbTestIoc_SRCS += xRecord.c
|
||||
dbTestIoc_SRCS += dbLinkdset.c
|
||||
dbTestIoc_SRCS += xLink.c
|
||||
dbTestIoc_SRCS += devx.c
|
||||
dbTestIoc_SRCS += jlinkz.c
|
||||
dbTestIoc_LIBS = dbCore ca Com
|
||||
|
||||
TARGETS += $(COMMON_DIR)/dbTestIoc.dbd
|
||||
@@ -31,6 +32,7 @@ dbTestIoc_DBD += xRecord.dbd
|
||||
dbTestIoc_DBD += arrRecord.dbd
|
||||
dbTestIoc_DBD += xLink.dbd
|
||||
dbTestIoc_DBD += devx.dbd
|
||||
dbTestIoc_DBD += jlinkz.dbd
|
||||
dbTestIoc_DBD += dbLinkdset.dbd
|
||||
TESTFILES += $(COMMON_DIR)/dbTestIoc.dbd ../xRecord.db
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ static void testLinkParse(void)
|
||||
{
|
||||
const struct testParseDataT *td = testParseData;
|
||||
dbLinkInfo info;
|
||||
testDiag("link parsing");
|
||||
testDiag("\n# Checking link parsing\n#");
|
||||
testdbPrepare();
|
||||
|
||||
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
|
||||
@@ -81,22 +81,27 @@ static void testLinkParse(void)
|
||||
testIocInitOk();
|
||||
eltc(1);
|
||||
|
||||
for(;td->str; td++) {
|
||||
for (;td->str; td++) {
|
||||
int i, N;
|
||||
testDiag("Parse \"%s\"", td->str);
|
||||
testOk1(dbParseLink(td->str, DBF_INLINK, &info)==0);
|
||||
testOk1(info.ltype==td->info.ltype);
|
||||
if(td->info.target)
|
||||
testDiag("Parsing \"%s\"", td->str);
|
||||
testOk(dbParseLink(td->str, DBF_INLINK, &info) == 0, "Parser returned OK");
|
||||
if (!testOk(info.ltype == td->info.ltype, "Link type value"))
|
||||
testDiag("Expected %d, got %d", td->info.ltype, info.ltype);
|
||||
if (td->info.target)
|
||||
testStrcmp(0, info.target, td->info.target);
|
||||
if(info.ltype==td->info.ltype) {
|
||||
switch(info.ltype) {
|
||||
if (info.ltype == td->info.ltype) {
|
||||
switch (info.ltype) {
|
||||
case PV_LINK:
|
||||
testOk1(info.modifiers==td->info.modifiers);
|
||||
if (!testOk(info.modifiers == td->info.modifiers,
|
||||
"PV Link modifier flags"))
|
||||
testDiag("Expected %d, got %d", td->info.modifiers,
|
||||
info.modifiers);
|
||||
break;
|
||||
case VME_IO:
|
||||
case CAMAC_IO:
|
||||
testStrcmp(0, info.hwid, td->info.hwid);
|
||||
N = strlen(td->info.hwid);
|
||||
for(i=0; i<N; i++)
|
||||
for (i=0; i<N; i++)
|
||||
testOk(info.hwnums[i]==td->info.hwnums[i], "%d == %d",
|
||||
info.hwnums[i], td->info.hwnums[i]);
|
||||
}
|
||||
@@ -125,7 +130,7 @@ static void testLinkFailParse(void)
|
||||
{
|
||||
const char * const *td = testParseFailData;
|
||||
dbLinkInfo info;
|
||||
testDiag("link parsing of invalid input");
|
||||
testDiag("\n# Check parsing of invalid inputs\n#");
|
||||
testdbPrepare();
|
||||
|
||||
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
|
||||
@@ -139,8 +144,8 @@ static void testLinkFailParse(void)
|
||||
eltc(1);
|
||||
|
||||
for(;*td; td++) {
|
||||
testDiag("Expect failure \"%s\"", *td);
|
||||
testOk1(dbParseLink(*td, DBF_INLINK, &info)==S_dbLib_badField);
|
||||
testOk(dbParseLink(*td, DBF_INLINK, &info) == S_dbLib_badField,
|
||||
"dbParseLink correctly rejected \"%s\"", *td);
|
||||
}
|
||||
|
||||
testIocShutdownOk();
|
||||
@@ -180,7 +185,7 @@ static void testCADBSet(void)
|
||||
const struct testDataT *td = testSetData;
|
||||
xRecord *prec;
|
||||
DBLINK *plink;
|
||||
testDiag("DB/CA link retargeting");
|
||||
testDiag("\n# Checking DB/CA link retargeting\n#");
|
||||
testdbPrepare();
|
||||
|
||||
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
|
||||
@@ -197,21 +202,22 @@ static void testCADBSet(void)
|
||||
plink = &prec->lnk;
|
||||
|
||||
for (;td->linkstring;td++) {
|
||||
testDiag("x1.LNK <- \"%s\"", td->linkstring);
|
||||
testDiag("Trying field value \"%s\"", td->linkstring);
|
||||
|
||||
testdbPutFieldOk("x1.LNK", DBF_STRING, td->linkstring);
|
||||
if (td->linkback)
|
||||
testdbGetFieldEqual("x1.LNK", DBF_STRING, td->linkback);
|
||||
else
|
||||
testdbGetFieldEqual("x1.LNK", DBF_STRING, td->linkstring);
|
||||
testOk1(plink->type==td->linkType);
|
||||
if (!testOk(plink->type == td->linkType, "Link type"))
|
||||
testDiag("Expected %d, got %d", td->linkType, plink->type);
|
||||
|
||||
if (plink->type==td->linkType) {
|
||||
switch(td->linkType) {
|
||||
if (plink->type == td->linkType) {
|
||||
switch (td->linkType) {
|
||||
case CONSTANT:
|
||||
if(plink->value.constantStr)
|
||||
testOk1(strcmp(plink->value.constantStr,td->linkstring)==0);
|
||||
else if(td->linkstring[0]=='\0')
|
||||
if (plink->value.constantStr)
|
||||
testOk1(strcmp(plink->value.constantStr, td->linkstring) == 0);
|
||||
else if (td->linkstring[0]=='\0')
|
||||
testPass("Empty String");
|
||||
else
|
||||
testFail("oops");
|
||||
@@ -219,7 +225,7 @@ static void testCADBSet(void)
|
||||
|
||||
case DB_LINK:
|
||||
case CA_LINK:
|
||||
testOk(plink->value.pv_link.pvlMask==td->pvlMask,
|
||||
testOk(plink->value.pv_link.pvlMask == td->pvlMask,
|
||||
"pvlMask %x == %x", plink->value.pv_link.pvlMask, td->pvlMask);
|
||||
break;
|
||||
}
|
||||
@@ -258,65 +264,65 @@ static void testLink(DBLINK *plink, const testHWDataT *td)
|
||||
{
|
||||
switch(td->ltype) {
|
||||
case JSON_LINK:
|
||||
testOk1(strcmp(plink->value.json.string, td->parm)==0);
|
||||
testOk1(strcmp(plink->value.json.string, td->parm) == 0);
|
||||
break;
|
||||
case VME_IO:
|
||||
testOk1(plink->value.vmeio.card==td->vals[0]);
|
||||
testOk1(plink->value.vmeio.signal==td->vals[1]);
|
||||
testOk1(strcmp(plink->value.vmeio.parm, td->parm)==0);
|
||||
testOk1(plink->value.vmeio.card == td->vals[0]);
|
||||
testOk1(plink->value.vmeio.signal == td->vals[1]);
|
||||
testOk1(strcmp(plink->value.vmeio.parm, td->parm) == 0);
|
||||
break;
|
||||
case CAMAC_IO:
|
||||
testOk1(plink->value.camacio.b==td->vals[0]);
|
||||
testOk1(plink->value.camacio.c==td->vals[1]);
|
||||
testOk1(plink->value.camacio.n==td->vals[2]);
|
||||
testOk1(plink->value.camacio.a==td->vals[3]);
|
||||
testOk1(plink->value.camacio.f==td->vals[4]);
|
||||
testOk1(strcmp(plink->value.camacio.parm, td->parm)==0);
|
||||
testOk1(plink->value.camacio.b == td->vals[0]);
|
||||
testOk1(plink->value.camacio.c == td->vals[1]);
|
||||
testOk1(plink->value.camacio.n == td->vals[2]);
|
||||
testOk1(plink->value.camacio.a == td->vals[3]);
|
||||
testOk1(plink->value.camacio.f == td->vals[4]);
|
||||
testOk1(strcmp(plink->value.camacio.parm, td->parm) == 0);
|
||||
break;
|
||||
case AB_IO:
|
||||
testOk1(plink->value.abio.link==td->vals[0]);
|
||||
testOk1(plink->value.abio.adapter==td->vals[1]);
|
||||
testOk1(plink->value.abio.card==td->vals[2]);
|
||||
testOk1(plink->value.abio.signal==td->vals[3]);
|
||||
testOk1(strcmp(plink->value.abio.parm, td->parm)==0);
|
||||
testOk1(plink->value.abio.link == td->vals[0]);
|
||||
testOk1(plink->value.abio.adapter == td->vals[1]);
|
||||
testOk1(plink->value.abio.card == td->vals[2]);
|
||||
testOk1(plink->value.abio.signal == td->vals[3]);
|
||||
testOk1(strcmp(plink->value.abio.parm, td->parm) == 0);
|
||||
break;
|
||||
case GPIB_IO:
|
||||
testOk1(plink->value.gpibio.link==td->vals[0]);
|
||||
testOk1(plink->value.gpibio.addr==td->vals[1]);
|
||||
testOk1(strcmp(plink->value.gpibio.parm, td->parm)==0);
|
||||
testOk1(plink->value.gpibio.link == td->vals[0]);
|
||||
testOk1(plink->value.gpibio.addr == td->vals[1]);
|
||||
testOk1(strcmp(plink->value.gpibio.parm, td->parm) == 0);
|
||||
break;
|
||||
case BITBUS_IO:
|
||||
testOk1(plink->value.bitbusio.link==td->vals[0]);
|
||||
testOk1(plink->value.bitbusio.node==td->vals[1]);
|
||||
testOk1(plink->value.bitbusio.port==td->vals[2]);
|
||||
testOk1(plink->value.bitbusio.signal==td->vals[3]);
|
||||
testOk1(strcmp(plink->value.bitbusio.parm, td->parm)==0);
|
||||
testOk1(plink->value.bitbusio.link == td->vals[0]);
|
||||
testOk1(plink->value.bitbusio.node == td->vals[1]);
|
||||
testOk1(plink->value.bitbusio.port == td->vals[2]);
|
||||
testOk1(plink->value.bitbusio.signal == td->vals[3]);
|
||||
testOk1(strcmp(plink->value.bitbusio.parm, td->parm) == 0);
|
||||
break;
|
||||
case INST_IO:
|
||||
testOk1(strcmp(plink->value.instio.string, td->parm)==0);
|
||||
testOk1(strcmp(plink->value.instio.string, td->parm) == 0);
|
||||
break;
|
||||
case BBGPIB_IO:
|
||||
testOk1(plink->value.bbgpibio.link==td->vals[0]);
|
||||
testOk1(plink->value.bbgpibio.bbaddr==td->vals[1]);
|
||||
testOk1(plink->value.bbgpibio.gpibaddr==td->vals[2]);
|
||||
testOk1(strcmp(plink->value.bbgpibio.parm, td->parm)==0);
|
||||
testOk1(plink->value.bbgpibio.link == td->vals[0]);
|
||||
testOk1(plink->value.bbgpibio.bbaddr == td->vals[1]);
|
||||
testOk1(plink->value.bbgpibio.gpibaddr == td->vals[2]);
|
||||
testOk1(strcmp(plink->value.bbgpibio.parm, td->parm) == 0);
|
||||
break;
|
||||
case RF_IO:
|
||||
testOk1(plink->value.rfio.cryo==td->vals[0]);
|
||||
testOk1(plink->value.rfio.micro==td->vals[1]);
|
||||
testOk1(plink->value.rfio.dataset==td->vals[2]);
|
||||
testOk1(plink->value.rfio.element==td->vals[3]);
|
||||
testOk1(plink->value.rfio.cryo == td->vals[0]);
|
||||
testOk1(plink->value.rfio.micro == td->vals[1]);
|
||||
testOk1(plink->value.rfio.dataset == td->vals[2]);
|
||||
testOk1(plink->value.rfio.element == td->vals[3]);
|
||||
break;
|
||||
case VXI_IO:
|
||||
if(plink->value.vxiio.flag==VXIDYNAMIC) {
|
||||
testOk1(plink->value.vxiio.frame==td->vals[0]);
|
||||
testOk1(plink->value.vxiio.slot==td->vals[1]);
|
||||
testOk1(plink->value.vxiio.signal==td->vals[2]);
|
||||
if(plink->value.vxiio.flag == VXIDYNAMIC) {
|
||||
testOk1(plink->value.vxiio.frame == td->vals[0]);
|
||||
testOk1(plink->value.vxiio.slot == td->vals[1]);
|
||||
testOk1(plink->value.vxiio.signal == td->vals[2]);
|
||||
} else {
|
||||
testOk1(plink->value.vxiio.la==td->vals[0]);
|
||||
testOk1(plink->value.vxiio.signal==td->vals[1]);
|
||||
testOk1(plink->value.vxiio.la == td->vals[0]);
|
||||
testOk1(plink->value.vxiio.signal == td->vals[1]);
|
||||
}
|
||||
testOk1(strcmp(plink->value.vxiio.parm, td->parm)==0);
|
||||
testOk1(strcmp(plink->value.vxiio.parm, td->parm) == 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -324,7 +330,7 @@ static void testLink(DBLINK *plink, const testHWDataT *td)
|
||||
static void testHWInitSet(void)
|
||||
{
|
||||
const testHWDataT *td = testHWData;
|
||||
testDiag("HW link parsing during initialization");
|
||||
testDiag("\n# Checking HW link parsing during initialization\n#");
|
||||
testdbPrepare();
|
||||
|
||||
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
|
||||
@@ -337,13 +343,14 @@ static void testHWInitSet(void)
|
||||
testIocInitOk();
|
||||
eltc(1);
|
||||
|
||||
for(;td->recname;td++) {
|
||||
for (;td->recname; td++) {
|
||||
char buf[MAX_STRING_SIZE];
|
||||
xRecord *prec;
|
||||
DBLINK *plink;
|
||||
|
||||
testDiag("%s == \"%s\"", td->recname, td->wval);
|
||||
|
||||
prec = (xRecord*)testdbRecordPtr(td->recname);
|
||||
prec = (xRecord *) testdbRecordPtr(td->recname);
|
||||
plink = &prec->inp;
|
||||
|
||||
strcpy(buf, td->recname);
|
||||
@@ -351,9 +358,11 @@ static void testHWInitSet(void)
|
||||
|
||||
testdbGetFieldEqual(buf, DBR_STRING, td->wval);
|
||||
|
||||
testOk(plink->type==td->ltype, "link type %d == %d",
|
||||
plink->type, td->ltype);
|
||||
if(plink->type==td->ltype) {
|
||||
if (!testOk(plink->type == td->ltype, "Link type")) {
|
||||
testDiag("Expected %d, got %d",
|
||||
td->ltype, plink->type);
|
||||
}
|
||||
else {
|
||||
testLink(plink, td);
|
||||
}
|
||||
|
||||
@@ -382,7 +391,8 @@ static const testHWDataT testHWData2[] = {
|
||||
static void testHWMod(void)
|
||||
{
|
||||
const testHWDataT *td = testHWData2;
|
||||
testDiag("HW link parsing during retarget");
|
||||
|
||||
testDiag("\n# Checking HW link parsing during retarget\n#");
|
||||
testdbPrepare();
|
||||
|
||||
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
|
||||
@@ -411,9 +421,11 @@ static void testHWMod(void)
|
||||
|
||||
testdbGetFieldEqual(buf, DBR_STRING, td->wval);
|
||||
|
||||
testOk(plink->type==td->ltype, "link type %d == %d",
|
||||
plink->type, td->ltype);
|
||||
if(plink->type==td->ltype) {
|
||||
if (!testOk(plink->type == td->ltype, "Link type")) {
|
||||
testDiag("Expected %d, got %d",
|
||||
td->ltype, plink->type);
|
||||
}
|
||||
else {
|
||||
testLink(plink, td);
|
||||
}
|
||||
|
||||
@@ -428,42 +440,42 @@ static void testLinkInitFail(void)
|
||||
{
|
||||
xRecord *prec;
|
||||
DBLINK *plink;
|
||||
testDiag("Link parsing failures during initialization");
|
||||
testDiag("\n# Checking link parse failures at iocInit\n#");
|
||||
testdbPrepare();
|
||||
|
||||
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
|
||||
|
||||
dbTestIoc_registerRecordDeviceDriver(pdbbase);
|
||||
|
||||
|
||||
/* this load will fail */
|
||||
eltc(0);
|
||||
testOk1(dbReadDatabase(&pdbbase, "dbBadLink.db", "." OSI_PATH_LIST_SEPARATOR ".." OSI_PATH_LIST_SEPARATOR
|
||||
"../O.Common" OSI_PATH_LIST_SEPARATOR "O.Common", NULL)!=0);
|
||||
testOk(dbReadDatabase(&pdbbase, "dbBadLink.db", "." OSI_PATH_LIST_SEPARATOR
|
||||
".." OSI_PATH_LIST_SEPARATOR "../O.Common" OSI_PATH_LIST_SEPARATOR
|
||||
"O.Common", NULL) != 0, "dbReadDatabase returned error (expected)");
|
||||
|
||||
testIocInitOk();
|
||||
eltc(1);
|
||||
|
||||
testdbGetFieldEqual("eVME_IO1.INP", DBR_STRING, "#C0 S0 @");
|
||||
|
||||
prec = (xRecord*)testdbRecordPtr("eVME_IO1");
|
||||
prec = (xRecord *) testdbRecordPtr("eVME_IO1");
|
||||
plink = &prec->inp;
|
||||
testOk1(plink->type==VME_IO);
|
||||
testOk1(plink->value.vmeio.parm!=NULL);
|
||||
testOk1(plink->type == VME_IO);
|
||||
testOk1(plink->value.vmeio.parm != NULL);
|
||||
|
||||
testdbGetFieldEqual("eVME_IO2.INP", DBR_STRING, "#C0 S0 @");
|
||||
|
||||
prec = (xRecord*)testdbRecordPtr("eVME_IO2");
|
||||
prec = (xRecord *) testdbRecordPtr("eVME_IO2");
|
||||
plink = &prec->inp;
|
||||
testOk1(plink->type==VME_IO);
|
||||
testOk1(plink->value.vmeio.parm!=NULL);
|
||||
testOk1(plink->type == VME_IO);
|
||||
testOk1(plink->value.vmeio.parm != NULL);
|
||||
|
||||
testdbGetFieldEqual("eINST_IO.INP", DBR_STRING, "@");
|
||||
|
||||
prec = (xRecord*)testdbRecordPtr("eINST_IO");
|
||||
prec = (xRecord *) testdbRecordPtr("eINST_IO");
|
||||
plink = &prec->inp;
|
||||
testOk1(plink->type==INST_IO);
|
||||
testOk1(plink->value.instio.string!=NULL);
|
||||
testOk1(plink->type == INST_IO);
|
||||
testOk1(plink->value.instio.string != NULL);
|
||||
|
||||
testIocShutdownOk();
|
||||
|
||||
@@ -472,7 +484,7 @@ static void testLinkInitFail(void)
|
||||
|
||||
static void testLinkFail(void)
|
||||
{
|
||||
testDiag("Link parsing failures");
|
||||
testDiag("\n# Checking runtime link parse failures\n#");
|
||||
testdbPrepare();
|
||||
|
||||
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
|
||||
@@ -491,7 +503,8 @@ static void testLinkFail(void)
|
||||
/* INST_IO doesn't accept string without @ */
|
||||
testdbPutFieldFail(S_dbLib_badField, "rINST_IO.INP", DBR_STRING, "abc");
|
||||
|
||||
/* JSON_LINK dies properly */
|
||||
/* JSON_LINK dies when expected */
|
||||
testdbPutFieldOk("rJSON_LINK.INP", DBR_STRING, "{\"x\":true}");
|
||||
testdbPutFieldFail(S_dbLib_badField, "rJSON_LINK.INP", DBR_STRING, "{\"x\":false}");
|
||||
testdbPutFieldFail(S_dbLib_badField, "rJSON_LINK.INP", DBR_STRING, "{\"x\":null}");
|
||||
testdbPutFieldFail(S_dbLib_badField, "rJSON_LINK.INP", DBR_STRING, "{\"x\":1}");
|
||||
@@ -522,7 +535,7 @@ static void testLinkFail(void)
|
||||
|
||||
MAIN(dbPutLinkTest)
|
||||
{
|
||||
testPlan(269);
|
||||
testPlan(280);
|
||||
testLinkParse();
|
||||
testLinkFailParse();
|
||||
testCADBSet();
|
||||
|
||||
232
src/ioc/db/test/jlinkz.c
Normal file
232
src/ioc/db/test/jlinkz.c
Normal file
@@ -0,0 +1,232 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2016 Michael Davidsaver
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <epicsExport.h>
|
||||
#include <dbAccess.h>
|
||||
#include <link.h>
|
||||
#include <alarm.h>
|
||||
#include <dbJLink.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbConvertFast.h>
|
||||
#include <epicsAtomic.h>
|
||||
#include <epicsMutex.h>
|
||||
#include <epicsUnitTest.h>
|
||||
|
||||
int numzalloc;
|
||||
|
||||
typedef struct {
|
||||
jlink base;
|
||||
epicsMutexId lock;
|
||||
unsigned isset:1;
|
||||
unsigned isopen:1;
|
||||
epicsInt32 value;
|
||||
} zpriv;
|
||||
|
||||
|
||||
static
|
||||
void z_open(struct link *plink)
|
||||
{
|
||||
zpriv *priv = CONTAINER(plink->value.json.jlink, zpriv, base);
|
||||
|
||||
if(priv->isopen)
|
||||
testDiag("lsetZ re-open");
|
||||
priv->isopen = 1;
|
||||
}
|
||||
|
||||
static
|
||||
void z_remove(struct dbLocker *locker, struct link *plink)
|
||||
{
|
||||
zpriv *priv = CONTAINER(plink->value.json.jlink, zpriv, base);
|
||||
|
||||
epicsMutexLock(priv->lock);
|
||||
|
||||
if(!priv->isopen)
|
||||
testDiag("lsetZ remove without open");
|
||||
|
||||
epicsMutexUnlock(priv->lock);
|
||||
|
||||
epicsAtomicDecrIntT(&numzalloc);
|
||||
|
||||
free(priv);
|
||||
plink->value.json.jlink = NULL; /* paranoia */
|
||||
}
|
||||
|
||||
static
|
||||
int z_connected(const struct link *plink)
|
||||
{
|
||||
return 1; /* TODO: not provided should be connected */
|
||||
}
|
||||
|
||||
static
|
||||
int z_dbftype(const struct link *plink)
|
||||
{
|
||||
return DBF_LONG;
|
||||
}
|
||||
|
||||
static
|
||||
long z_elements(const struct link *plink, long *nelements)
|
||||
{
|
||||
*nelements = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
long z_getval(struct link *plink, short dbrType, void *pbuffer,
|
||||
long *pnRequest)
|
||||
{
|
||||
long ret;
|
||||
long (*pconv)(const epicsInt32 *, void *, const dbAddr *) = dbFastGetConvertRoutine[DBF_LONG][dbrType];
|
||||
zpriv *priv = CONTAINER(plink->value.json.jlink, zpriv, base);
|
||||
|
||||
if(pnRequest && *pnRequest==0) return 0;
|
||||
|
||||
epicsMutexLock(priv->lock);
|
||||
ret = (*pconv)(&priv->value, pbuffer, NULL);
|
||||
epicsMutexUnlock(priv->lock);
|
||||
if(ret==0 && pnRequest) *pnRequest = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TODO: atomicly get value and alarm */
|
||||
static
|
||||
long z_getalarm(const struct link *plink, epicsEnum16 *status,
|
||||
epicsEnum16 *severity)
|
||||
{
|
||||
zpriv *priv = CONTAINER(plink->value.json.jlink, zpriv, base);
|
||||
epicsEnum16 sevr, stat;
|
||||
|
||||
epicsMutexLock(priv->lock);
|
||||
sevr = priv->isset ? 0 : INVALID_ALARM;
|
||||
stat = priv->isset ? 0 : LINK_ALARM;
|
||||
epicsMutexUnlock(priv->lock);
|
||||
|
||||
if(status) *status = stat;
|
||||
if(severity) *severity = sevr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
long z_putval(struct link *plink, short dbrType,
|
||||
const void *pbuffer, long nRequest)
|
||||
{
|
||||
long ret;
|
||||
long (*pconv)(epicsInt32 *, const void *, const dbAddr *) = dbFastPutConvertRoutine[DBF_LONG][dbrType];
|
||||
zpriv *priv = CONTAINER(plink->value.json.jlink, zpriv, base);
|
||||
|
||||
if(nRequest==0) return 0;
|
||||
|
||||
epicsMutexLock(priv->lock);
|
||||
ret = (*pconv)(&priv->value, pbuffer, NULL);
|
||||
epicsMutexUnlock(priv->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static lset lsetZ = {
|
||||
0, 0, /* non-const, non-volatile */
|
||||
&z_open,
|
||||
&z_remove,
|
||||
NULL, NULL, NULL, /* load */
|
||||
&z_connected,
|
||||
&z_dbftype,
|
||||
&z_elements,
|
||||
&z_getval,
|
||||
NULL, /* control limits */
|
||||
NULL, /* display limits */
|
||||
NULL, /* alarm limits */
|
||||
NULL, /* prec */
|
||||
NULL, /* units */
|
||||
&z_getalarm,
|
||||
NULL, /* time */
|
||||
&z_putval,
|
||||
NULL, /* putasync */
|
||||
NULL, /* forward */
|
||||
};
|
||||
|
||||
static
|
||||
jlink* z_alloc(short dbfType)
|
||||
{
|
||||
zpriv *priv;
|
||||
priv = calloc(1, sizeof(*priv));
|
||||
if(!priv) return NULL;
|
||||
|
||||
epicsAtomicIncrIntT(&numzalloc);
|
||||
|
||||
return &priv->base;
|
||||
}
|
||||
|
||||
static
|
||||
void z_free(jlink *pj)
|
||||
{
|
||||
zpriv *priv = CONTAINER(pj, zpriv, base);
|
||||
|
||||
if(priv->isopen)
|
||||
testDiag("lsetZ jlink free after open()\n");
|
||||
|
||||
epicsAtomicDecrIntT(&numzalloc);
|
||||
|
||||
free(priv);
|
||||
}
|
||||
|
||||
static
|
||||
jlif_result z_int(jlink *pj, long num)
|
||||
{
|
||||
zpriv *priv = CONTAINER(pj, zpriv, base);
|
||||
|
||||
priv->value = num;
|
||||
priv->isset = 1;
|
||||
|
||||
return jlif_continue;
|
||||
}
|
||||
|
||||
static
|
||||
jlif_key_result z_start(jlink *pj)
|
||||
{
|
||||
return jlif_continue;
|
||||
}
|
||||
|
||||
static
|
||||
jlif_result z_key(jlink *pj, const char *key, size_t len)
|
||||
{
|
||||
if(strcmp(key,"fail")==0) return jlif_stop;
|
||||
else return jlif_continue;
|
||||
}
|
||||
|
||||
static
|
||||
jlif_result z_end(jlink *pj)
|
||||
{
|
||||
return jlif_continue;
|
||||
}
|
||||
|
||||
static
|
||||
struct lset* z_lset(const jlink *pj)
|
||||
{
|
||||
return &lsetZ;
|
||||
}
|
||||
|
||||
static jlif jlifZ = {
|
||||
"z",
|
||||
&z_alloc,
|
||||
&z_free,
|
||||
NULL, /* null */
|
||||
NULL, /* bool */
|
||||
&z_int,
|
||||
NULL, /* double */
|
||||
NULL, /* string */
|
||||
&z_start,
|
||||
&z_key,
|
||||
&z_end,
|
||||
NULL, /* start array */
|
||||
NULL, /* end array */
|
||||
NULL, /* end child */
|
||||
&z_lset,
|
||||
NULL, /* report */
|
||||
NULL /* map child */
|
||||
};
|
||||
|
||||
epicsExportAddress(jlif, jlifZ);
|
||||
1
src/ioc/db/test/jlinkz.dbd
Normal file
1
src/ioc/db/test/jlinkz.dbd
Normal file
@@ -0,0 +1 @@
|
||||
link("z", "jlifZ")
|
||||
Reference in New Issue
Block a user