diff --git a/src/ioc/db/dbAccess.c b/src/ioc/db/dbAccess.c index 1f8b68ba6..ff94a5b53 100644 --- a/src/ioc/db/dbAccess.c +++ b/src/ioc/db/dbAccess.c @@ -1048,23 +1048,12 @@ static long dbPutFieldLink(DBADDR *paddr, } } - switch (plink->type) { /* Old link type */ - case DB_LINK: - case CA_LINK: - case CONSTANT: - dbRemoveLink(&locker, plink); /* link type becomes PV_LINK */ - break; - - case PV_LINK: - case MACRO_LINK: - break; /* should never get here */ - - default: /* Hardware address */ - if (!isDevLink) { - status = S_db_badHWaddr; - goto restoreScan; - } - break; + if (dbLinkIsDefined(plink)) { + dbRemoveLink(&locker, plink); /* Clear out old link */ + } + else if (!isDevLink) { + status = S_db_badHWaddr; + goto restoreScan; } if (special) status = dbPutSpecial(paddr, 0); @@ -1097,6 +1086,7 @@ static long dbPutFieldLink(DBADDR *paddr, switch (plink->type) { /* New link type */ case PV_LINK: case CONSTANT: + case JSON_LINK: dbAddLink(&locker, plink, pfldDes->field_type, pdbaddr); break; diff --git a/src/ioc/db/dbCa.c b/src/ioc/db/dbCa.c index 1763fe3e7..99dcd75bb 100644 --- a/src/ioc/db/dbCa.c +++ b/src/ioc/db/dbCa.c @@ -713,6 +713,7 @@ static void scanLinkOnce(dbCommon *prec, caLink *pca) { } static lset dbCa_lset = { + 0, 1, /* not Constant, Volatile */ dbCaRemoveLink, NULL, NULL, isConnected, diff --git a/src/ioc/db/dbConstLink.c b/src/ioc/db/dbConstLink.c index 38f5d448c..a969addf3 100644 --- a/src/ioc/db/dbConstLink.c +++ b/src/ioc/db/dbConstLink.c @@ -85,6 +85,7 @@ static long dbConstGetValue(struct link *plink, short dbrType, void *pbuffer, } static lset dbConst_lset = { + 1, 0, /* Constant, not Volatile */ NULL, dbConstLoadScalar, dbConstLoadArray, diff --git a/src/ioc/db/dbDbLink.c b/src/ioc/db/dbDbLink.c index 58f089126..cdecd0ea6 100644 --- a/src/ioc/db/dbDbLink.c +++ b/src/ioc/db/dbDbLink.c @@ -336,6 +336,7 @@ static void dbDbScanFwdLink(struct link *plink) } static lset dbDb_lset = { + 0, 0, /* not Constant, not Volatile */ dbDbRemoveLink, NULL, NULL, dbDbIsConnected, diff --git a/src/ioc/db/dbLink.c b/src/ioc/db/dbLink.c index a877eec6e..c2ae385d0 100644 --- a/src/ioc/db/dbLink.c +++ b/src/ioc/db/dbLink.c @@ -120,6 +120,9 @@ void dbAddLink(struct dbLocker *locker, struct link *plink, short dbfType, return; } + if (plink->type != PV_LINK) + return; + if (plink == &precord->tsel) recGblTSELwasModified(plink); @@ -142,10 +145,45 @@ void dbAddLink(struct dbLocker *locker, struct link *plink, short dbfType, } } -long dbLoadLink(struct link *plink, short dbrType, void *pbuffer) +void dbRemoveLink(struct dbLocker *locker, struct link *plink) { lset *plset = plink->lset; + if (plset) { + if (plset->removeLink) + plset->removeLink(locker, plink); + plink->lset = NULL; + } +} + +int dbLinkIsDefined(const struct link *plink) +{ + return (plink->lset != 0); +} + +int dbLinkIsConstant(const struct link *plink) +{ + lset *plset = plink->lset; + + if (plset) + return plset->isConstant; + + return -1; +} + +int dbLinkIsVolatile(const struct link *plink) +{ + lset *plset = plink->lset; + + if (plset) + return plset->isVolatile; + + return -1; +} + +long dbLoadLink(struct link *plink, short dbrType, void *pbuffer) +{ + lset *plset = plink->lset; if (plset && plset->loadScalar) return plset->loadScalar(plink, dbrType, pbuffer); @@ -164,17 +202,6 @@ long dbLoadLinkArray(struct link *plink, short dbrType, void *pbuffer, return S_db_noLSET; } -void dbRemoveLink(struct dbLocker *locker, struct link *plink) -{ - lset *plset = plink->lset; - - if (plset) { - if (plset->removeLink) - plset->removeLink(locker, plink); - plink->lset = NULL; - } -} - int dbIsLinkConnected(const struct link *plink) { lset *plset = plink->lset; diff --git a/src/ioc/db/dbLink.h b/src/ioc/db/dbLink.h index 834400c73..2903528c1 100644 --- a/src/ioc/db/dbLink.h +++ b/src/ioc/db/dbLink.h @@ -28,13 +28,24 @@ extern "C" { struct dbLocker; typedef struct lset { + /* Characteristics of the link type */ + const unsigned isConstant:1; + const unsigned isVolatile:1; + + /* Destructor */ void (*removeLink)(struct dbLocker *locker, struct link *plink); + + /* Const init, data type hinting */ long (*loadScalar)(struct link *plink, short dbrType, void *pbuffer); long (*loadArray)(struct link *plink, short dbrType, void *pbuffer, long *pnRequest); + + /* Metadata */ int (*isConnected)(const struct link *plink); int (*getDBFtype)(const struct link *plink); long (*getElements)(const struct link *plink, long *nelements); + + /* Get data */ long (*getValue)(struct link *plink, short dbrType, void *pbuffer, epicsEnum16 *pstat, epicsEnum16 *psevr, long *pnRequest); long (*getControlLimits)(const struct link *plink, double *lo, double *hi); @@ -46,10 +57,14 @@ typedef struct lset { long (*getAlarm)(const struct link *plink, epicsEnum16 *status, epicsEnum16 *severity); long (*getTimeStamp)(const struct link *plink, epicsTimeStamp *pstamp); + + /* Put data */ long (*putValue)(struct link *plink, short dbrType, const void *pbuffer, long nRequest); long (*putAsync)(struct link *plink, short dbrType, const void *pbuffer, long nRequest); + + /* Process */ void (*scanForward)(struct link *plink); } lset; @@ -60,6 +75,11 @@ epicsShareFunc void dbInitLink(struct link *plink, short dbfType); epicsShareFunc void dbAddLink(struct dbLocker *locker, struct link *plink, short dbfType, DBADDR *ptarget); epicsShareFunc void dbRemoveLink(struct dbLocker *locker, struct link *plink); + +epicsShareFunc int dbLinkIsDefined(const struct link *plink); /* 0 or 1 */ +epicsShareFunc int dbLinkIsConstant(const struct link *plink); /* -1, 0 or 1 */ +epicsShareFunc int dbLinkIsVolatile(const struct link *plink); /* -1, 0 or 1 */ + epicsShareFunc long dbLoadLink(struct link *plink, short dbrType, void *pbuffer); epicsShareFunc long dbLoadLinkArray(struct link *, short dbrType, void *pbuffer, diff --git a/src/ioc/db/recGbl.c b/src/ioc/db/recGbl.c index 19bc425ba..0d835b9a4 100644 --- a/src/ioc/db/recGbl.c +++ b/src/ioc/db/recGbl.c @@ -256,7 +256,7 @@ void recGblGetTimeStamp(void *pvoid) dbCommon* prec = (dbCommon*)pvoid; struct link *plink = &prec->tsel; - if (plink->type != CONSTANT) { + if (!dbLinkIsConstant(plink)) { struct pv_link *ppv_link = &plink->value.pv_link; if (ppv_link->pvlMask & pvlOptTSELisTime) {