From 5641afa0e2148eddf075125c2615b2e7d13f559a Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 19 Sep 2017 00:12:18 -0500 Subject: [PATCH 1/3] Change pvlOptTSELisTime to DBLINK_FLAG_TSELisTIME Renames recGblTSELwasModified() to TSEL_modified() in dbLink.c. Adds some tests for using JSON link types in dbCommon links. --- src/ioc/db/dbLink.c | 28 +++++++++++++++++++++++++--- src/ioc/db/recGbl.c | 30 +++++------------------------- src/ioc/db/recGbl.h | 3 +-- src/ioc/db/test/dbPutLinkTest.c | 19 ++++++++++++++----- src/ioc/db/test/dbPutLinkTestJ.db | 4 ++++ src/ioc/dbStatic/dbStaticLib.c | 2 +- src/ioc/dbStatic/link.h | 2 +- 7 files changed, 51 insertions(+), 37 deletions(-) diff --git a/src/ioc/db/dbLink.c b/src/ioc/db/dbLink.c index 9279b91fb..c90dcb3df 100644 --- a/src/ioc/db/dbLink.c +++ b/src/ioc/db/dbLink.c @@ -66,6 +66,26 @@ static const char * link_field_name(const struct link *plink) return "????"; } +/* Special TSEL handler for PV links */ +/* FIXME: Generalize for new link types... */ +static void TSEL_modified(struct link *plink) +{ + struct pv_link *ppv_link; + char *pfieldname; + + if (plink->type != PV_LINK) { + errlogPrintf("dbLink::TSEL_modified called for non PV_LINK\n"); + return; + } + /* If pvname contains .TIME truncate it to point to VAL instead */ + ppv_link = &plink->value.pv_link; + pfieldname = strstr(ppv_link->pvname, ".TIME"); + if (pfieldname) { + *pfieldname = 0; + plink->flags |= DBLINK_FLAG_TSELisTIME; + } +} + /***************************** Generic Link API *****************************/ @@ -93,7 +113,7 @@ void dbInitLink(struct link *plink, short dbfType) return; if (plink == &precord->tsel) - recGblTSELwasModified(plink); + TSEL_modified(plink); if (!(plink->value.pv_link.pvlMask & (pvlOptCA | pvlOptCP | pvlOptCPP))) { /* Make it a DB link if possible */ @@ -127,6 +147,9 @@ void dbAddLink(struct dbLocker *locker, struct link *plink, short dbfType, { struct dbCommon *precord = plink->precord; + /* Clear old TSELisTIME flag */ + plink->flags &= ~DBLINK_FLAG_TSELisTIME; + if (plink->type == CONSTANT) { dbConstAddLink(plink); return; @@ -145,7 +168,7 @@ void dbAddLink(struct dbLocker *locker, struct link *plink, short dbfType, return; if (plink == &precord->tsel) - recGblTSELwasModified(plink); + TSEL_modified(plink); if (ptarget) { /* It's a DB link */ @@ -470,4 +493,3 @@ long dbPutLinkLS(struct link *plink, char *pbuffer, epicsUInt32 len) return dbPutLink(plink, DBR_STRING, pbuffer, 1); } - diff --git a/src/ioc/db/recGbl.c b/src/ioc/db/recGbl.c index a614b5268..337ed7875 100644 --- a/src/ioc/db/recGbl.c +++ b/src/ioc/db/recGbl.c @@ -4,7 +4,7 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* recGbl.c */ /* @@ -259,15 +259,13 @@ void recGblGetTimeStamp(void *pvoid) struct link *plink = &prec->tsel; if (!dbLinkIsConstant(plink)) { - struct pv_link *ppv_link = &plink->value.pv_link; - - if (ppv_link->pvlMask & pvlOptTSELisTime) { + if (plink->flags & DBLINK_FLAG_TSELisTIME) { if (dbGetTimeStamp(plink, &prec->time)) - errlogPrintf("recGblGetTimeStamp: dbGetTimeStamp failed, %s.TSEL = %s\n", - prec->name, ppv_link->pvname); + errlogPrintf("recGblGetTimeStamp: dbGetTimeStamp failed for %s.TSEL", + prec->name); return; } - dbGetLink(&prec->tsel, DBR_SHORT, &prec->tse, 0, 0); + dbGetLink(plink, DBR_SHORT, &prec->tse, 0, 0); } if (prec->tse != epicsTimeEventDeviceTime) { if (epicsTimeGetEvent(&prec->time, prec->tse)) @@ -276,24 +274,6 @@ void recGblGetTimeStamp(void *pvoid) } } -void recGblTSELwasModified(struct link *plink) -{ - struct pv_link *ppv_link = &plink->value.pv_link; - char *pfieldname; - - if (plink->type != PV_LINK) { - errlogPrintf("recGblTSELwasModified called for non PV_LINK\n"); - return; - } - /*If pvname ends in .TIME then just ask for VAL*/ - /*Note that the VAL value will not be used*/ - pfieldname = strstr(ppv_link->pvname, ".TIME"); - if (pfieldname) { - *pfieldname = 0; - ppv_link->pvlMask |= pvlOptTSELisTime; - } -} - void recGblCheckDeadband(epicsFloat64 *poldval, const epicsFloat64 newval, const epicsFloat64 deadband, unsigned *monitor_mask, const unsigned add_mask) { diff --git a/src/ioc/db/recGbl.h b/src/ioc/db/recGbl.h index 8eb589450..171c00964 100644 --- a/src/ioc/db/recGbl.h +++ b/src/ioc/db/recGbl.h @@ -4,7 +4,7 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* recGbl.h */ /* Record Global @@ -63,7 +63,6 @@ epicsShareFunc void recGblInheritSevr(int msMode, void *precord, epicsEnum16 sta epicsEnum16 sevr); epicsShareFunc void recGblFwdLink(void *precord); epicsShareFunc void recGblGetTimeStamp(void *precord); -epicsShareFunc void recGblTSELwasModified(struct link *plink); epicsShareFunc void recGblCheckDeadband(epicsFloat64 *poldval, const epicsFloat64 newval, const epicsFloat64 deadband, unsigned *monitor_mask, const unsigned add_mask); diff --git a/src/ioc/db/test/dbPutLinkTest.c b/src/ioc/db/test/dbPutLinkTest.c index b39b98db2..8d2f1765a 100644 --- a/src/ioc/db/test/dbPutLinkTest.c +++ b/src/ioc/db/test/dbPutLinkTest.c @@ -565,7 +565,7 @@ void testJLink(void) testIocInitOk(); eltc(1); - testNumZ(3); + testNumZ(6); testdbPutFieldOk("j1.PROC", DBF_LONG, 1); testdbPutFieldOk("j2.PROC", DBF_LONG, 1); @@ -576,13 +576,16 @@ void testJLink(void) testdbGetFieldEqual("j2.VAL", DBF_LONG, 2); testdbGetFieldEqual("j3.VAL", DBF_LONG, 3); - testNumZ(3); + testNumZ(6); testdbPutFieldOk("j1.INP", DBF_STRING, "{\"z\":{\"good\":4}}"); testdbPutFieldOk("j1.PROC", DBF_LONG, 1); testdbGetFieldEqual("j1.VAL", DBF_LONG, 4); - testNumZ(3); + testdbPutFieldOk("j2.TSEL", DBF_STRING, "{\"z\":{\"good\":0}}"); + testdbPutFieldOk("j2.PROC", DBF_LONG, 1); + + testNumZ(7); testdbPutFieldFail(S_dbLib_badField, "j1.INP", DBF_STRING, "{\"z\":{\"fail\":5}}"); testdbPutFieldOk("j1.PROC", DBF_LONG, 1); @@ -590,7 +593,13 @@ void testJLink(void) /* put failure in parsing stage doesn't modify link */ testdbGetFieldEqual("j1.INP", DBF_STRING, "{\"z\":{\"good\":4}}"); - testNumZ(3); + testNumZ(7); + + /* Check SDIS using a JSON link prevents processing */ + testdbPutFieldOk("j1.SDIS", DBF_STRING, "{\"z\":{\"good\":1}}"); + testdbPutFieldOk("j1.INP", DBF_STRING, "{\"z\":{\"good\":1}}"); + testdbPutFieldOk("j1.PROC", DBF_LONG, 1); + testdbGetFieldEqual("j1.VAL", DBF_LONG, 4); testIocShutdownOk(); @@ -601,7 +610,7 @@ void testJLink(void) MAIN(dbPutLinkTest) { - testPlan(301); + testPlan(307); testLinkParse(); testLinkFailParse(); testCADBSet(); diff --git a/src/ioc/db/test/dbPutLinkTestJ.db b/src/ioc/db/test/dbPutLinkTestJ.db index 25cf4c822..621557c2c 100644 --- a/src/ioc/db/test/dbPutLinkTestJ.db +++ b/src/ioc/db/test/dbPutLinkTestJ.db @@ -1,10 +1,14 @@ record(x, "j1") { field(INP, {z:{good:1}}) + field(TSEL, {z:{good:0}}) + field(SDIS, {z:{good:0}}) + field(FLNK, {z:{good:0}}) } record(x, "j2") { field(INP, {z:{good:2}}) + field(TSEL, "j1.TIME") } record(x, "j3") { diff --git a/src/ioc/dbStatic/dbStaticLib.c b/src/ioc/dbStatic/dbStaticLib.c index d647f787d..bcfa93727 100644 --- a/src/ioc/dbStatic/dbStaticLib.c +++ b/src/ioc/dbStatic/dbStaticLib.c @@ -1940,7 +1940,7 @@ char * dbGetString(DBENTRY *pdbentry) else ppind=0; dbMsgPrint(pdbentry, "%s%s%s%s", plink->value.pv_link.pvname ? plink->value.pv_link.pvname : "", - (pvlMask & pvlOptTSELisTime) ? ".TIME" : "", + (plink->flags & DBLINK_FLAG_TSELisTIME) ? ".TIME" : "", ppstring[ppind], msstring[plink->value.pv_link.pvlMask&pvlOptMsMode]); break; diff --git a/src/ioc/dbStatic/link.h b/src/ioc/dbStatic/link.h index f2b426308..2e3c77820 100644 --- a/src/ioc/dbStatic/link.h +++ b/src/ioc/dbStatic/link.h @@ -67,10 +67,10 @@ epicsShareExtern maplinkType pamaplinkType[]; #define pvlOptInpString 0x100 /*Input as string*/ #define pvlOptOutNative 0x200 /*Output native*/ #define pvlOptOutString 0x400 /*Output as string*/ -#define pvlOptTSELisTime 0x800 /*Field TSEL is getting timeStamp*/ /* DBLINK Flag bits */ #define DBLINK_FLAG_INITIALIZED 1 /* dbInitLink() called */ +#define DBLINK_FLAG_TSELisTIME 2 /* Use TSEL to get timeStamp */ struct macro_link { char *macroStr; From e3c9d5900ed27f13b341fee8f04e0c4507b90df1 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 18 Oct 2017 15:39:22 -0500 Subject: [PATCH 2/3] Added timestamp support to the lnkCalc link type. --- src/std/link/links.dbd.pod | 8 +++++ src/std/link/lnkCalc.c | 61 ++++++++++++++++++++++++++++---- src/std/rec/test/linkInitTest.db | 3 +- 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/src/std/link/links.dbd.pod b/src/std/link/links.dbd.pod index ceb6ced77..d94e9e8f0 100644 --- a/src/std/link/links.dbd.pod +++ b/src/std/link/links.dbd.pod @@ -114,6 +114,14 @@ expression. Equivalent to the C field of a record. An optional integer specifying the numeric precision with which the calculation result should be displayed. Equivalent to the C field of a record. +=item time + +An optional string containing a single upper or lower-case letter C ... C +which must correspond to an input provided in the c parameter. When the +record containing such a link has C set to -2 (epicsTimeEventDeviceTime) +the record's timestamp field C