EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  <20192020  2021  2022  2023  2024  Index 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  <20192020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: [Merge] ~anj/epics-base/+git/base-7.0:fix-1824277 into epics-base:7.0
From: Andrew Johnson via Core-talk <[email protected]>
To: [email protected]
Date: Thu, 18 Apr 2019 04:33:22 -0000
Andrew Johnson has proposed merging ~anj/epics-base/+git/base-7.0:fix-1824277 into epics-base:7.0.

Commit message:
Fix for bug lp: #1824277 and related issues.

This could go into 7.0.2.2 if nobody objects. The bug has existed since 3.16.1.

Requested reviews:
  EPICS Core Developers (epics-core)
Related bugs:
  Bug #1824277 in EPICS Base: "Regression in calcout setting constant links at runtime"
  https://bugs.launchpad.net/epics-base/+bug/1824277

For more details, see:
https://code.launchpad.net/~anj/epics-base/+git/base-7.0/+merge/366247
-- 
Your team EPICS Core Developers is requested to review the proposed merge of ~anj/epics-base/+git/base-7.0:fix-1824277 into epics-base:7.0.
diff --git a/modules/database/src/ioc/db/dbAccess.c b/modules/database/src/ioc/db/dbAccess.c
index be81d22..35f19e2 100644
--- a/modules/database/src/ioc/db/dbAccess.c
+++ b/modules/database/src/ioc/db/dbAccess.c
@@ -1140,8 +1140,6 @@ static long dbPutFieldLink(DBADDR *paddr,
 
     if (!status) status = dbSetLink(plink, &link_info, new_devsup);
 
-    if (!status && special) status = dbPutSpecial(paddr, 1);
-
     if (status) {
         if (isDevLink) {
             precord->dset = NULL;
@@ -1150,28 +1148,57 @@ static long dbPutFieldLink(DBADDR *paddr,
         goto postScanEvent;
     }
 
-    if (isDevLink) {
+    /* We need to initialize any links with a link support layer, i.e.
+     * any CONSTANT, JSON_LINK, or PV_LINK types. However for a PV_LINK
+     * when isDevLink is set (i.e. this is the record's INP or OUT link)
+     * we must wait until after calling dsxt->add_record(). This allows
+     * the Async Soft Channel input supports to change it to a PN_LINK.
+     * For other cases we initialize the link before the second call to
+     * dbPutSpecial() because some record types such as calcout need to
+     * be able to call link support methods from prset->special().
+     */
+
+    switch (plink->type) { /* New type */
+    case PV_LINK:
+        if (isDevLink)
+            break;
+        /* else fall through */
+    case CONSTANT:
+    case JSON_LINK:
+        dbAddLink(&locker, plink, pfldDes->field_type, pdbaddr);
+    }
+
+    if (special) status = dbPutSpecial(paddr, 1);
+
+    if (!status && isDevLink) {
         precord->dpvt = NULL;
         precord->dset = new_dset;
         precord->pact = FALSE;
 
         status = new_dsxt->add_record(precord);
-        if (status) {
+    }
+
+    if (status) {
+        if (isDevLink) {
             precord->dset = NULL;
             precord->pact = TRUE;
-            goto postScanEvent;
         }
+        goto postScanEvent;
     }
 
     switch (plink->type) { /* New link type */
-    case PV_LINK:
     case CONSTANT:
+    case CA_LINK:
+    case DB_LINK:
+    case PN_LINK:
     case JSON_LINK:
-        dbAddLink(&locker, plink, pfldDes->field_type, pdbaddr);
         break;
 
-    case DB_LINK:
-    case CA_LINK:
+    case PV_LINK:
+        if (isDevLink)
+            dbAddLink(&locker, plink, pfldDes->field_type, pdbaddr);
+        break;
+
     case MACRO_LINK:
         break;  /* should never get here */
 
@@ -1180,7 +1207,6 @@ static long dbPutFieldLink(DBADDR *paddr,
             status = S_db_badHWaddr;
             goto postScanEvent;
         }
-        break;
     }
     db_post_events(precord, plink, DBE_VALUE | DBE_LOG);
 
diff --git a/modules/database/src/std/dev/devAiSoftCallback.c b/modules/database/src/std/dev/devAiSoftCallback.c
index cf38c87..872684c 100644
--- a/modules/database/src/std/dev/devAiSoftCallback.c
+++ b/modules/database/src/std/dev/devAiSoftCallback.c
@@ -80,7 +80,7 @@ static long add_record(dbCommon *pcommon)
     devPvt *pdevPvt;
     processNotify *ppn;
 
-    if (dbLinkIsDefined(plink) && dbLinkIsConstant(plink))
+    if (plink->type == CONSTANT)
         return 0;
 
     if (plink->type != PV_LINK) {
diff --git a/modules/database/src/std/dev/devBiSoftCallback.c b/modules/database/src/std/dev/devBiSoftCallback.c
index 3144600..88b96f8 100644
--- a/modules/database/src/std/dev/devBiSoftCallback.c
+++ b/modules/database/src/std/dev/devBiSoftCallback.c
@@ -78,7 +78,7 @@ static long add_record(dbCommon *pcommon)
     devPvt *pdevPvt;
     processNotify *ppn;
 
-    if (dbLinkIsDefined(plink) && dbLinkIsConstant(plink))
+    if (plink->type == CONSTANT)
         return 0;
 
     if (plink->type != PV_LINK) {
diff --git a/modules/database/src/std/dev/devI64inSoftCallback.c b/modules/database/src/std/dev/devI64inSoftCallback.c
index 9eb5656..43c48f6 100644
--- a/modules/database/src/std/dev/devI64inSoftCallback.c
+++ b/modules/database/src/std/dev/devI64inSoftCallback.c
@@ -78,7 +78,7 @@ static long add_record(dbCommon *pcommon)
     devPvt *pdevPvt;
     processNotify *ppn;
 
-    if (dbLinkIsDefined(plink) && dbLinkIsConstant(plink))
+    if (plink->type == CONSTANT)
         return 0;
 
     if (plink->type != PV_LINK) {
diff --git a/modules/database/src/std/dev/devLiSoftCallback.c b/modules/database/src/std/dev/devLiSoftCallback.c
index caab523..a95f989 100644
--- a/modules/database/src/std/dev/devLiSoftCallback.c
+++ b/modules/database/src/std/dev/devLiSoftCallback.c
@@ -78,7 +78,7 @@ static long add_record(dbCommon *pcommon)
     devPvt *pdevPvt;
     processNotify *ppn;
 
-    if (dbLinkIsDefined(plink) && dbLinkIsConstant(plink))
+    if (plink->type == CONSTANT)
         return 0;
 
     if (plink->type != PV_LINK) {
diff --git a/modules/database/src/std/dev/devMbbiDirectSoftCallback.c b/modules/database/src/std/dev/devMbbiDirectSoftCallback.c
index d785f73..947b9c0 100644
--- a/modules/database/src/std/dev/devMbbiDirectSoftCallback.c
+++ b/modules/database/src/std/dev/devMbbiDirectSoftCallback.c
@@ -78,7 +78,7 @@ static long add_record(dbCommon *pcommon)
     devPvt *pdevPvt;
     processNotify *ppn;
 
-    if (dbLinkIsDefined(plink) && dbLinkIsConstant(plink))
+    if (plink->type == CONSTANT)
         return 0;
 
     if (plink->type != PV_LINK) {
diff --git a/modules/database/src/std/dev/devMbbiSoftCallback.c b/modules/database/src/std/dev/devMbbiSoftCallback.c
index 3796bce..5b3370f 100644
--- a/modules/database/src/std/dev/devMbbiSoftCallback.c
+++ b/modules/database/src/std/dev/devMbbiSoftCallback.c
@@ -78,7 +78,7 @@ static long add_record(dbCommon *pcommon)
     devPvt *pdevPvt;
     processNotify *ppn;
 
-    if (dbLinkIsDefined(plink) && dbLinkIsConstant(plink))
+    if (plink->type == CONSTANT)
         return 0;
 
     if (plink->type != PV_LINK) {
diff --git a/modules/database/src/std/dev/devSiSoftCallback.c b/modules/database/src/std/dev/devSiSoftCallback.c
index 8f67988..2b0922c 100644
--- a/modules/database/src/std/dev/devSiSoftCallback.c
+++ b/modules/database/src/std/dev/devSiSoftCallback.c
@@ -80,7 +80,7 @@ static long add_record(dbCommon *pcommon)
     devPvt *pdevPvt;
     processNotify *ppn;
 
-    if (dbLinkIsDefined(plink) && dbLinkIsConstant(plink))
+    if (plink->type == CONSTANT)
         return 0;
 
     if (plink->type != PV_LINK) {
diff --git a/modules/database/test/std/rec/Makefile b/modules/database/test/std/rec/Makefile
index 185c2c0..cd7316a 100644
--- a/modules/database/test/std/rec/Makefile
+++ b/modules/database/test/std/rec/Makefile
@@ -113,8 +113,8 @@ regressTest_DBD += base.dbd
 TESTPROD_HOST += regressTest
 regressTest_SRCS += regressTest.c
 regressTest_SRCS += regressTest_registerRecordDeviceDriver.cpp
-TESTFILES += $(COMMON_DIR)/regressTest.dbd ../regressArray1.db ../regressHex.db ../regressLinkMS.db
-TESTFILES += ../badCaLink.db
+TESTFILES += $(COMMON_DIR)/regressTest.dbd ../regressArray1.db ../regressHex.db
+TESTFILES += ../regressLinkMS.db ../badCaLink.db ../regressCalcout.db
 TESTS += regressTest
 
 TARGETS += $(COMMON_DIR)/simmTest.dbd
diff --git a/modules/database/test/std/rec/regressCalcout.db b/modules/database/test/std/rec/regressCalcout.db
new file mode 100644
index 0000000..8896131
--- /dev/null
+++ b/modules/database/test/std/rec/regressCalcout.db
@@ -0,0 +1,27 @@
+record(calcout, "cout") {
+    field(INPA, "99")
+    field(INPB, "99")
+    field(INPC, "99")
+    field(INPD, "99")
+}
+record(ai, "ain") {
+    field(DTYP, "Async Soft Channel")
+}
+record(bi, "bin") {
+    field(DTYP, "Async Soft Channel")
+}
+record(int64in, "iin") {
+    field(DTYP, "Async Soft Channel")
+}
+record(longin, "lin") {
+    field(DTYP, "Async Soft Channel")
+}
+record(mbbi, "min") {
+    field(DTYP, "Async Soft Channel")
+}
+record(mbbiDirect, "din") {
+    field(DTYP, "Async Soft Channel")
+}
+record(stringin, "sin") {
+    field(DTYP, "Async Soft Channel")
+}
diff --git a/modules/database/test/std/rec/regressTest.c b/modules/database/test/std/rec/regressTest.c
index 6614639..37bcc31 100644
--- a/modules/database/test/std/rec/regressTest.c
+++ b/modules/database/test/std/rec/regressTest.c
@@ -135,15 +135,61 @@ void testCADisconn(void)
     testdbPutFieldOk("ai:disconn.PROC", DBF_LONG, 1);
     testdbGetFieldEqual("ai:disconn.SEVR", DBF_LONG, INVALID_ALARM);
     testdbGetFieldEqual("ai:disconn.STAT", DBF_LONG, LINK_ALARM);
+
+    testIocShutdownOk();
+    testdbCleanup();
+}
+
+/* lp:1824277 Regression in calcout, setting links at runtime */
+static void
+testSpecialLinks(void)
+{
+    testDiag("In testSpecialLinks()");
+
+    startRegressTestIoc("regressCalcout.db");
+
+    testdbPutFieldOk("cout.INPA", DBF_STRING, "10");
+    testdbGetFieldEqual("cout.A", DBF_LONG, 10);
+    testdbGetFieldEqual("cout.INAV", DBF_LONG, calcoutINAV_CON);
+    testdbPutFieldOk("cout.INPB", DBF_STRING, "{\"const\":20}");
+    testdbGetFieldEqual("cout.B", DBF_LONG, 20);
+    testdbGetFieldEqual("cout.INBV", DBF_LONG, calcoutINAV_CON);
+    testdbPutFieldOk("cout.INPC", DBF_STRING, "cout.A");
+    testdbGetFieldEqual("cout.C", DBF_LONG, 99);
+    testdbGetFieldEqual("cout.INCV", DBF_LONG, calcoutINAV_LOC);
+    testdbPutFieldOk("cout.INPD", DBF_STRING, "no-such-pv");
+    testdbGetFieldEqual("cout.D", DBF_LONG, 99);
+    testdbGetFieldEqual("cout.INDV", DBF_LONG, calcoutINAV_EXT_NC);
+
+    eltc(0);
+    testdbPutFieldOk("ain.INP", DBF_STRING, "cout");
+    testdbPutFieldFail(S_db_badField, "ain.INP", DBF_STRING, "{\"const\":1}");
+    testdbPutFieldOk("bin.INP", DBF_STRING, "cout");
+    testdbPutFieldFail(S_db_badField, "bin.INP", DBF_STRING, "{\"const\":1}");
+    testdbPutFieldOk("iin.INP", DBF_STRING, "cout");
+    testdbPutFieldFail(S_db_badField, "iin.INP", DBF_STRING, "{\"const\":1}");
+    testdbPutFieldOk("lin.INP", DBF_STRING, "cout");
+    testdbPutFieldFail(S_db_badField, "lin.INP", DBF_STRING, "{\"const\":1}");
+    testdbPutFieldOk("min.INP", DBF_STRING, "cout");
+    testdbPutFieldFail(S_db_badField, "min.INP", DBF_STRING, "{\"const\":1}");
+    testdbPutFieldOk("din.INP", DBF_STRING, "cout");
+    testdbPutFieldFail(S_db_badField, "din.INP", DBF_STRING, "{\"const\":1}");
+    testdbPutFieldOk("sin.INP", DBF_STRING, "cout");
+    testdbPutFieldFail(S_db_badField, "sin.INP", DBF_STRING, "{\"const\":1}");
+    eltc(1);
+
+    testIocShutdownOk();
+    testdbCleanup();
 }
 
 
 MAIN(regressTest)
 {
-    testPlan(34);
+    testPlan(60);
     testArrayLength1();
     testHexConstantLinks();
     testLinkMS();
     testCADisconn();
+    testSpecialLinks();
     return testDone();
 }

Replies:
Re: [Merge] ~anj/epics-base/+git/base-7.0:fix-1824277 into epics-base:7.0 Andrew Johnson via Core-talk
Re: [Merge] ~anj/epics-base/+git/base-7.0:fix-1824277 into epics-base:7.0 mdavidsaver via Core-talk
Re: [Merge] ~anj/epics-base/+git/base-7.0:fix-1824277 into epics-base:7.0 Andrew Johnson via Core-talk
Re: [Merge] ~anj/epics-base/+git/base-7.0:fix-1824277 into epics-base:7.0 Keenan Lang via Core-talk
Re: [Merge] ~anj/epics-base/+git/base-7.0:fix-1824277 into epics-base:7.0 Keenan Lang via Core-talk
Re: [Merge] ~anj/epics-base/+git/base-7.0:fix-1824277 into epics-base:7.0 Keenan Lang via Core-talk
Re: [Merge] ~anj/epics-base/+git/base-7.0:fix-1824277 into epics-base:7.0 mdavidsaver via Core-talk
Re: [Merge] ~anj/epics-base/+git/base-7.0:fix-1824277 into epics-base:7.0 mdavidsaver via Core-talk
Re: [Merge] ~anj/epics-base/+git/base-7.0:fix-1824277 into epics-base:7.0 Andrew Johnson via Core-talk

Navigate by Date:
Prev: Build failed in Jenkins: epics-base-7.0-win64s-test #23 APS Jenkins via Core-talk
Next: Re: Support for Google Test in EPICS base / modules? Ralph Lange via Core-talk
Index: 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  <20192020  2021  2022  2023  2024 
Navigate by Thread:
Prev: Jenkins build is back to normal : epics-base-7.0-win64-test #22 APS Jenkins via Core-talk
Next: Re: [Merge] ~anj/epics-base/+git/base-7.0:fix-1824277 into epics-base:7.0 Andrew Johnson via Core-talk
Index: 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  <20192020  2021  2022  2023  2024 
ANJ, 04 Oct 2019 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·