diff --git a/src/ioc/db/dbAccess.c b/src/ioc/db/dbAccess.c index e0360db59..478b69e5d 100644 --- a/src/ioc/db/dbAccess.c +++ b/src/ioc/db/dbAccess.c @@ -1050,13 +1050,11 @@ static long dbPutFieldLink(DBADDR *paddr, switch (plink->type) { /* Old link type */ case DB_LINK: case CA_LINK: - dbRemoveLink(&locker, precord, plink); /* link type becomes PV_LINK */ + case CONSTANT: + dbRemoveLink(&locker, plink); /* link type becomes PV_LINK */ break; case PV_LINK: - case CONSTANT: - break; /* do nothing */ - case MACRO_LINK: break; /* should never get here */ @@ -1097,11 +1095,9 @@ static long dbPutFieldLink(DBADDR *paddr, switch (plink->type) { /* New link type */ case PV_LINK: - dbAddLink(&locker, precord, plink, pfldDes->field_type, pdbaddr); - break; - case CONSTANT: - break; /* do nothing */ + dbAddLink(&locker, plink, pfldDes->field_type, pdbaddr); + break; case DB_LINK: case CA_LINK: diff --git a/src/ioc/db/dbCa.c b/src/ioc/db/dbCa.c index 3939cec7a..7fa04db79 100644 --- a/src/ioc/db/dbCa.c +++ b/src/ioc/db/dbCa.c @@ -47,6 +47,7 @@ #include "dbCaPvt.h" #include "dbCommon.h" #include "db_convert.h" +#include "dbLink.h" #include "dbLock.h" #include "dbScan.h" #include "link.h" @@ -74,9 +75,11 @@ struct ca_client_context * dbCaClientContext; /* Forward declarations */ static void dbCaTask(void *); +static lset dbCa_lset; + #define printLinks(pcaLink) \ errlogPrintf("%s has DB CA link to %s\n",\ - pcaLink->plink->value.pv_link.precord->name, pcaLink->pvname) + pcaLink->plink->precord->name, pcaLink->pvname) static int dbca_chan_count; @@ -194,7 +197,7 @@ static void caLinkDec(caLink *pca) void dbCaCallbackProcess(void *userPvt) { struct link *plink = (struct link *)userPvt; - dbCommon *pdbCommon = plink->value.pv_link.precord; + dbCommon *pdbCommon = plink->precord; dbScanLock(pdbCommon); pdbCommon->rset->process(pdbCommon); @@ -273,13 +276,20 @@ void dbCaAddLinkCallback(struct link *plink, pca->userPvt = userPvt; epicsMutexMustLock(pca->lock); + plink->lset = &dbCa_lset; plink->type = CA_LINK; plink->value.pv_link.pvt = pca; addAction(pca, CA_CONNECT); epicsMutexUnlock(pca->lock); } -void dbCaRemoveLink(struct link *plink) +long dbCaAddLink(struct dbLocker *locker, struct link *plink, short dbfType) +{ + dbCaAddLinkCallback(plink, 0, 0, NULL); + return 0; +} + +void dbCaRemoveLink(struct dbLocker *locker, struct link *plink) { caLink *pca = (caLink *)plink->value.pv_link.pvt; @@ -287,6 +297,9 @@ void dbCaRemoveLink(struct link *plink) epicsMutexMustLock(pca->lock); pca->plink = 0; plink->value.pv_link.pvt = 0; + plink->value.pv_link.pvlMask = 0; + plink->type = PV_LINK; + plink->lset = NULL; /* Unlock before addAction or dbCaTask might free first */ epicsMutexUnlock(pca->lock); addAction(pca, CA_CLEAR_CHANNEL); @@ -453,6 +466,12 @@ long dbCaPutLinkCallback(struct link *plink,short dbrType, return status; } +long dbCaPutLink(struct link *plink, short dbrType, + const void *pbuffer, long nRequest) +{ + return dbCaPutLinkCallback(plink, dbrType, pbuffer, nRequest, 0, NULL); +} + int dbCaIsLinkConnected(const struct link *plink) { caLink *pca; @@ -655,6 +674,18 @@ static void scanLinkOnce(dbCommon *prec, caLink *pca) { /* else too many scans queued */ } +static lset dbCa_lset = { + dbCaRemoveLink, + dbCaIsLinkConnected, + dbCaGetLinkDBFtype, dbCaGetNelements, + dbCaGetLink, + dbCaGetControlLimits, dbCaGetGraphicLimits, dbCaGetAlarmLimits, + dbCaGetPrecision, dbCaGetUnits, + dbCaGetAlarm, dbCaGetTimeStamp, + dbCaPutLink, + dbCaScanFwdLink +}; + static void connectionCallback(struct connection_handler_args arg) { caLink *pca; @@ -669,7 +700,7 @@ static void connectionCallback(struct connection_handler_args arg) pca->isConnected = (ca_state(arg.chid) == cs_conn); if (!pca->isConnected) { struct pv_link *ppv_link = &plink->value.pv_link; - dbCommon *precord = ppv_link->precord; + dbCommon *precord = plink->precord; pca->nDisconnect++; if (precord && @@ -743,7 +774,7 @@ static void eventCallback(struct event_handler_args arg) if (!plink) goto done; monitor = pca->monitor; userPvt = pca->userPvt; - precord = plink->value.pv_link.precord; + precord = plink->precord; if (arg.status != ECA_NORMAL) { if (precord) { if (arg.status != ECA_NORDACCESS && @@ -858,7 +889,7 @@ static void accessRightsCallback(struct access_rights_handler_args arg) pca->hasWriteAccess = ca_write_access(arg.chid); if (pca->hasReadAccess && pca->hasWriteAccess) goto done; ppv_link = &plink->value.pv_link; - precord = ppv_link->precord; + precord = plink->precord; if (precord && ((ppv_link->pvlMask & pvlOptCP) || ((ppv_link->pvlMask & pvlOptCPP) && precord->scan == 0))) @@ -889,7 +920,7 @@ static void getAttribEventCallback(struct event_handler_args arg) getAttributes = pca->getAttributes; getAttributesPvt = pca->getAttributesPvt; if (arg.status != ECA_NORMAL) { - dbCommon *precord = plink->value.pv_link.precord; + dbCommon *precord = plink->precord; if (precord) { errlogPrintf("dbCa: getAttribEventCallback record %s error %s\n", precord->name, ca_message(arg.status)); diff --git a/src/ioc/db/dbCa.h b/src/ioc/db/dbCa.h index cfdf7321f..21bedb684 100644 --- a/src/ioc/db/dbCa.h +++ b/src/ioc/db/dbCa.h @@ -29,18 +29,19 @@ epicsShareFunc void dbCaRun(void); epicsShareFunc void dbCaPause(void); epicsShareFunc void dbCaShutdown(void); +struct dbLocker; epicsShareFunc void dbCaAddLinkCallback(struct link *plink, dbCaCallback connect, dbCaCallback monitor, void *userPvt); -#define dbCaAddLink(plink) dbCaAddLinkCallback((plink), 0, 0, 0) -epicsShareFunc void dbCaRemoveLink(struct link *plink); +epicsShareFunc long dbCaAddLink(struct dbLocker *locker, struct link *plink, short dbfType); +epicsShareFunc void dbCaRemoveLink(struct dbLocker *locker, struct link *plink); epicsShareFunc long dbCaGetLink(struct link *plink, short dbrType, void *pbuffer, epicsEnum16 *pstat, epicsEnum16 *psevr, long *nRequest); epicsShareFunc long dbCaPutLinkCallback(struct link *plink, short dbrType, const void *pbuffer,long nRequest, dbCaCallback callback, void *userPvt); -#define dbCaPutLink(plink, dbrType, pbuffer, nRequest) \ - dbCaPutLinkCallback((plink), (dbrType), (pbuffer), (nRequest), 0, 0) +epicsShareFunc long dbCaPutLink(struct link *plink,short dbrType, + const void *pbuffer,long nRequest); epicsShareFunc int dbCaIsLinkConnected(const struct link *plink); epicsShareFunc void dbCaScanFwdLink(struct link *plink); diff --git a/src/ioc/db/dbLink.c b/src/ioc/db/dbLink.c index 5ffd4fc17..b97d2a4ea 100644 --- a/src/ioc/db/dbLink.c +++ b/src/ioc/db/dbLink.c @@ -79,7 +79,7 @@ static void inherit_severity(const struct pv_link *ppv_link, dbCommon *pdest, /* How to identify links in error messages */ static const char * link_field_name(const struct link *plink) { - const struct dbCommon *precord = plink->value.pv_link.precord; + const struct dbCommon *precord = plink->precord; const dbRecordType *pdbRecordType = precord->rdes; dbFldDes * const *papFldDes = pdbRecordType->papFldDes; const short *link_ind = pdbRecordType->link_ind; @@ -97,13 +97,28 @@ static const char * link_field_name(const struct link *plink) /***************************** Constant Links *****************************/ +/* Forward definition */ +static lset dbConst_lset; + +static void dbConstInitLink(struct link *plink) +{ + plink->lset = &dbConst_lset; +} + +static void dbConstAddLink(struct link *plink) +{ + plink->lset = &dbConst_lset; +} + static long dbConstLoadLink(struct link *plink, short dbrType, void *pbuffer) { if (!plink->value.constantStr) return S_db_badField; + plink->lset = &dbConst_lset; + /* Constant strings are always numeric */ - if (dbrType== DBF_MENU || dbrType == DBF_ENUM || dbrType == DBF_DEVICE) + if (dbrType == DBF_MENU || dbrType == DBF_ENUM || dbrType == DBF_DEVICE) dbrType = DBF_USHORT; return dbFastPutConvertRoutine[DBR_STRING][dbrType] @@ -116,7 +131,7 @@ static long dbConstGetNelements(const struct link *plink, long *nelements) return 0; } -static long dbConstGetLink(struct link *plink, short dbrType, void *pbuffer, +static long dbConstGetValue(struct link *plink, short dbrType, void *pbuffer, epicsEnum16 *pstat, epicsEnum16 *psevr, long *pnRequest) { if (pnRequest) @@ -124,9 +139,24 @@ static long dbConstGetLink(struct link *plink, short dbrType, void *pbuffer, return 0; } +static lset dbConst_lset = { + NULL, + NULL, + NULL, dbConstGetNelements, + dbConstGetValue, + NULL, NULL, NULL, + NULL, NULL, + NULL, NULL, + NULL, + NULL +}; + /***************************** Database Links *****************************/ -static long dbDbInitLink(struct dbCommon *precord, struct link *plink, short dbfType) +/* Forward definition */ +static lset dbDb_lset; + +static long dbDbInitLink(struct link *plink, short dbfType) { DBADDR dbaddr; long status; @@ -136,6 +166,7 @@ static long dbDbInitLink(struct dbCommon *precord, struct link *plink, short dbf if (status) return status; + plink->lset = &dbDb_lset; plink->type = DB_LINK; pdbAddr = dbCalloc(1, sizeof(struct dbAddr)); *pdbAddr = dbaddr; /* structure copy */ @@ -144,20 +175,33 @@ static long dbDbInitLink(struct dbCommon *precord, struct link *plink, short dbf /* merging into the same lockset is deferred to the caller. * cf. initPVLinks() */ - dbLockSetMerge(NULL, precord, dbaddr.precord); - assert(precord->lset->plockSet==dbaddr.precord->lset->plockSet); + dbLockSetMerge(NULL, plink->precord, dbaddr.precord); + assert(plink->precord->lset->plockSet == dbaddr.precord->lset->plockSet); return 0; } -static void dbDbRemoveLink(dbLocker *locker, struct dbCommon *prec, struct link *plink) +static void dbDbAddLink(dbLocker *locker, struct link *plink, short dbfType, DBADDR *ptarget) +{ + plink->lset = &dbDb_lset; + plink->type = DB_LINK; + plink->value.pv_link.pvt = ptarget; + ellAdd(&ptarget->precord->bklnk, &plink->value.pv_link.backlinknode); + + /* target record is already locked in dbPutFieldLink() */ + dbLockSetMerge(locker, plink->precord, ptarget->precord); +} + +static void dbDbRemoveLink(dbLocker *locker, struct link *plink) { DBADDR *pdbAddr = (DBADDR *) plink->value.pv_link.pvt; plink->value.pv_link.pvt = 0; plink->value.pv_link.getCvt = 0; + plink->value.pv_link.pvlMask = 0; plink->value.pv_link.lastGetdbrType = 0; plink->type = PV_LINK; + plink->lset = NULL; ellDelete(&pdbAddr->precord->bklnk, &plink->value.pv_link.backlinknode); - dbLockSetSplit(locker, prec, pdbAddr->precord); + dbLockSetSplit(locker, plink->precord, pdbAddr->precord); free(pdbAddr); } @@ -186,7 +230,7 @@ static long dbDbGetValue(struct link *plink, short dbrType, void *pbuffer, { struct pv_link *ppv_link = &plink->value.pv_link; DBADDR *paddr = ppv_link->pvt; - dbCommon *precord = plink->value.pv_link.precord; + dbCommon *precord = plink->precord; long status; /* scan passive records if link is process passive */ @@ -350,7 +394,7 @@ static long dbDbPutValue(struct link *plink, short dbrType, const void *pbuffer, long nRequest) { struct pv_link *ppv_link = &plink->value.pv_link; - struct dbCommon *psrce = ppv_link->precord; + struct dbCommon *psrce = plink->precord; DBADDR *paddr = (DBADDR *) ppv_link->pvt; dbCommon *pdest = paddr->precord; long status = dbPut(paddr, dbrType, pbuffer, nRequest); @@ -381,30 +425,44 @@ static long dbDbPutValue(struct link *plink, short dbrType, static void dbDbScanFwdLink(struct link *plink) { - dbCommon *precord = plink->value.pv_link.precord; + dbCommon *precord = plink->precord; dbAddr *paddr = (dbAddr *) plink->value.pv_link.pvt; dbScanPassive(precord, paddr->precord); } -lset dbDb_lset = { NULL, - dbDbIsLinkConnected, dbDbGetDBFtype, dbDbGetElements, dbDbGetValue, - dbDbGetControlLimits, dbDbGetGraphicLimits, dbDbGetAlarmLimits, - dbDbGetPrecision, dbDbGetUnits, dbDbGetAlarm, dbDbGetTimeStamp, - dbDbPutValue, dbDbScanFwdLink }; +static lset dbDb_lset = { + dbDbRemoveLink, + dbDbIsLinkConnected, + dbDbGetDBFtype, dbDbGetElements, + dbDbGetValue, + dbDbGetControlLimits, dbDbGetGraphicLimits, dbDbGetAlarmLimits, + dbDbGetPrecision, dbDbGetUnits, + dbDbGetAlarm, dbDbGetTimeStamp, + dbDbPutValue, + dbDbScanFwdLink +}; /***************************** Generic Link API *****************************/ -void dbInitLink(struct dbCommon *precord, struct link *plink, short dbfType) +void dbInitLink(struct link *plink, short dbfType) { - plink->value.pv_link.precord = precord; + struct dbCommon *precord = plink->precord; + + if (plink->type == CONSTANT) { + dbConstInitLink(plink); + return; + } + + if (plink->type != PV_LINK) + return; if (plink == &precord->tsel) recGblTSELwasModified(plink); if (!(plink->value.pv_link.pvlMask & (pvlOptCA | pvlOptCP | pvlOptCPP))) { /* Make it a DB link if possible */ - if (!dbDbInitLink(precord, plink, dbfType)) + if (!dbDbInitLink(plink, dbfType)) return; } @@ -412,7 +470,7 @@ void dbInitLink(struct dbCommon *precord, struct link *plink, short dbfType) if (dbfType == DBF_INLINK) plink->value.pv_link.pvlMask |= pvlOptInpNative; - dbCaAddLink(plink); + dbCaAddLink(NULL, plink, dbfType); if (dbfType == DBF_FWDLINK) { char *pperiod = strrchr(plink->value.pv_link.pvname, '.'); @@ -429,23 +487,21 @@ void dbInitLink(struct dbCommon *precord, struct link *plink, short dbfType) } } -void dbAddLink(dbLocker *locker, struct dbCommon *precord, struct link *plink, short dbfType, DBADDR *ptargetaddr) +void dbAddLink(dbLocker *locker, struct link *plink, short dbfType, DBADDR *ptarget) { - plink->value.pv_link.precord = precord; + struct dbCommon *precord = plink->precord; + + if (plink->type == CONSTANT) { + dbConstAddLink(plink); + return; + } if (plink == &precord->tsel) recGblTSELwasModified(plink); - if (ptargetaddr) { - /* make a DB link */ - - plink->type = DB_LINK; - plink->value.pv_link.pvt = ptargetaddr; - ellAdd(&ptargetaddr->precord->bklnk, &plink->value.pv_link.backlinknode); - - /* target record is already locked in dbPutFieldLink() */ - dbLockSetMerge(locker, plink->value.pv_link.precord, ptargetaddr->precord); - + if (ptarget) { + /* It's a DB link */ + dbDbAddLink(locker, plink, dbfType, ptarget); return; } @@ -453,7 +509,7 @@ void dbAddLink(dbLocker *locker, struct dbCommon *precord, struct link *plink, s if (dbfType == DBF_INLINK) plink->value.pv_link.pvlMask |= pvlOptInpNative; - dbCaAddLink(plink); + dbCaAddLink(locker, plink, dbfType); if (dbfType == DBF_FWDLINK) { char *pperiod = strrchr(plink->value.pv_link.pvname, '.'); @@ -464,69 +520,60 @@ void dbAddLink(dbLocker *locker, struct dbCommon *precord, struct link *plink, s long dbLoadLink(struct link *plink, short dbrType, void *pbuffer) { - switch (plink->type) { - case CONSTANT: + if (plink->type == CONSTANT) return dbConstLoadLink(plink, dbrType, pbuffer); - } + + /* Could pass a type hint to the other link types here */ return S_db_notFound; } -void dbRemoveLink(dbLocker *locker, dbCommon *prec, struct link *plink) +void dbRemoveLink(dbLocker *locker, struct link *plink) { - switch (plink->type) { - case DB_LINK: - dbDbRemoveLink(locker, prec, plink); - break; - case CA_LINK: - dbCaRemoveLink(plink); - break; - default: - cantProceed("dbRemoveLink: Unexpected link type %d\n", plink->type); + lset *plset = plink->lset; + + if (plset) { + if (plset->removeLink) + plset->removeLink(locker, plink); + plink->lset = NULL; } - plink->type = PV_LINK; - plink->value.pv_link.pvlMask = 0; } int dbIsLinkConnected(const struct link *plink) { - switch (plink->type) { - case DB_LINK: - return dbDbIsLinkConnected(plink); - case CA_LINK: - return dbCaIsLinkConnected(plink); - } - return FALSE; + lset *plset = plink->lset; + + if (!plset || !plset->isLinkConnected) + return FALSE; + + return plset->isLinkConnected(plink); } int dbGetLinkDBFtype(const struct link *plink) { - switch (plink->type) { - case DB_LINK: - return dbDbGetDBFtype(plink); - case CA_LINK: - return dbCaGetLinkDBFtype(plink); - } - return -1; + lset *plset = plink->lset; + + if (!plset || !plset->getDBFtype) + return -1; + + return plset->getDBFtype(plink); } long dbGetNelements(const struct link *plink, long *nelements) { - switch (plink->type) { - case CONSTANT: - return dbConstGetNelements(plink, nelements); - case DB_LINK: - return dbDbGetElements(plink, nelements); - case CA_LINK: - return dbCaGetNelements(plink, nelements); - } - return S_db_badField; + lset *plset = plink->lset; + + if (!plset || !plset->getElements) + return S_db_badField; + + return plset->getElements(plink, nelements); } long dbGetLink(struct link *plink, short dbrType, void *pbuffer, long *poptions, long *pnRequest) { - struct dbCommon *precord = plink->value.pv_link.precord; + struct dbCommon *precord = plink->precord; epicsEnum16 sevr = 0, stat = 0; + lset *plset = plink->lset; long status; if (poptions && *poptions) { @@ -534,21 +581,10 @@ long dbGetLink(struct link *plink, short dbrType, void *pbuffer, *poptions = 0; } - switch (plink->type) { - case CONSTANT: - status = dbConstGetLink(plink, dbrType, pbuffer, &stat, &sevr, - pnRequest); - break; - case DB_LINK: - status = dbDbGetValue(plink, dbrType, pbuffer, &stat, &sevr, pnRequest); - break; - case CA_LINK: - status = dbCaGetLink(plink, dbrType, pbuffer, &stat, &sevr, pnRequest); - break; - default: - cantProceed("dbGetLinkValue: Illegal link type %d\n", plink->type); - status = -1; - } + if (!plset || !plset->getValue) + return -1; + + status = plset->getValue(plink, dbrType, pbuffer, &stat, &sevr, pnRequest); if (status) { recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM); } else { @@ -559,104 +595,88 @@ long dbGetLink(struct link *plink, short dbrType, void *pbuffer, long dbGetControlLimits(const struct link *plink, double *low, double *high) { - switch (plink->type) { - case DB_LINK: - return dbDbGetControlLimits(plink, low, high); - case CA_LINK: - return dbCaGetControlLimits(plink, low, high); - } - return S_db_notFound; + lset *plset = plink->lset; + + if (!plset || !plset->getControlLimits) + return S_db_notFound; + + return plset->getControlLimits(plink, low, high); } long dbGetGraphicLimits(const struct link *plink, double *low, double *high) { - switch (plink->type) { - case DB_LINK: - return dbDbGetGraphicLimits(plink, low, high); - case CA_LINK: - return dbCaGetGraphicLimits(plink, low, high); - } - return S_db_notFound; + lset *plset = plink->lset; + + if (!plset || !plset->getGraphicLimits) + return S_db_notFound; + + return plset->getGraphicLimits(plink, low, high); } long dbGetAlarmLimits(const struct link *plink, double *lolo, double *low, double *high, double *hihi) { - switch (plink->type) { - case DB_LINK: - return dbDbGetAlarmLimits(plink, lolo, low, high, hihi); - case CA_LINK: - return dbCaGetAlarmLimits(plink, lolo, low, high, hihi); - } - return S_db_notFound; + lset *plset = plink->lset; + + if (!plset || !plset->getAlarmLimits) + return S_db_notFound; + + return plset->getAlarmLimits(plink, lolo, low, high, hihi); } long dbGetPrecision(const struct link *plink, short *precision) { - switch (plink->type) { - case DB_LINK: - return dbDbGetPrecision(plink, precision); - case CA_LINK: - return dbCaGetPrecision(plink, precision); - } - return S_db_notFound; + lset *plset = plink->lset; + + if (!plset || !plset->getPrecision) + return S_db_notFound; + + return plset->getPrecision(plink, precision); } long dbGetUnits(const struct link *plink, char *units, int unitsSize) { - switch (plink->type) { - case DB_LINK: - return dbDbGetUnits(plink, units, unitsSize); - case CA_LINK: - return dbCaGetUnits(plink, units, unitsSize); - } - return S_db_notFound; + lset *plset = plink->lset; + + if (!plset || !plset->getUnits) + return S_db_notFound; + + return plset->getUnits(plink, units, unitsSize); } long dbGetAlarm(const struct link *plink, epicsEnum16 *status, epicsEnum16 *severity) { - switch (plink->type) { - case DB_LINK: - return dbDbGetAlarm(plink, status, severity); - case CA_LINK: - return dbCaGetAlarm(plink, status, severity); - } - return S_db_notFound; + lset *plset = plink->lset; + + if (!plset || !plset->getAlarm) + return S_db_notFound; + + return plset->getAlarm(plink, status, severity); } long dbGetTimeStamp(const struct link *plink, epicsTimeStamp *pstamp) { - switch (plink->type) { - case DB_LINK: - return dbDbGetTimeStamp(plink, pstamp); - case CA_LINK: - return dbCaGetTimeStamp(plink, pstamp); - } - return S_db_notFound; + lset *plset = plink->lset; + + if (!plset || !plset->getTimeStamp) + return S_db_notFound; + + return plset->getTimeStamp(plink, pstamp); } long dbPutLink(struct link *plink, short dbrType, const void *pbuffer, long nRequest) { + lset *plset = plink->lset; long status; - switch (plink->type) { - case CONSTANT: - status = 0; - break; - case DB_LINK: - status = dbDbPutValue(plink, dbrType, pbuffer, nRequest); - break; - case CA_LINK: - status = dbCaPutLink(plink, dbrType, pbuffer, nRequest); - break; - default: - cantProceed("dbPutLinkValue: Illegal link type %d\n", plink->type); - status = -1; - } + if (!plset || !plset->putValue) + return S_db_notFound; + + status = plset->putValue(plink, dbrType, pbuffer, nRequest); if (status) { - struct dbCommon *precord = plink->value.pv_link.precord; + struct dbCommon *precord = plink->precord; recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM); } @@ -665,14 +685,10 @@ long dbPutLink(struct link *plink, short dbrType, const void *pbuffer, void dbScanFwdLink(struct link *plink) { - switch (plink->type) { - case DB_LINK: - dbDbScanFwdLink(plink); - break; - case CA_LINK: - dbCaScanFwdLink(plink); - break; - } + lset *plset = plink->lset; + + if (plset && plset->scanFwdLink) + plset->scanFwdLink(plink); } /* Helper functions for long string support */ diff --git a/src/ioc/db/dbLink.h b/src/ioc/db/dbLink.h index 006189728..fd9b2c250 100644 --- a/src/ioc/db/dbLink.h +++ b/src/ioc/db/dbLink.h @@ -26,8 +26,10 @@ extern "C" { #endif +struct dbLocker; + typedef struct lset { - void (*removeLink)(struct link *plink); + void (*removeLink)(struct dbLocker *locker, struct link *plink); int (*isLinkConnected)(const struct link *plink); int (*getDBFtype)(const struct link *plink); long (*getElements)(const struct link *plink, long *nelements); @@ -50,15 +52,12 @@ typedef struct lset { #define dbGetSevr(PLINK, PSEVERITY) \ dbGetAlarm((PLINK), NULL, (PSEVERITY)) -struct dbLocker; - -epicsShareFunc void dbInitLink(struct dbCommon *precord, struct link *plink, - short dbfType); -epicsShareFunc void dbAddLink(struct dbLocker *locker, struct dbCommon *precord, struct link *plink, - short dbfType, DBADDR *ptargetaddr); +epicsShareFunc void dbInitLink(struct link *plink, short dbfType); +epicsShareFunc void dbAddLink(struct dbLocker *locker, struct link *plink, short dbfType, + DBADDR *ptarget); epicsShareFunc long dbLoadLink(struct link *plink, short dbrType, void *pbuffer); -epicsShareFunc void dbRemoveLink(struct dbLocker *locker, struct dbCommon *prec, struct link *plink); +epicsShareFunc void dbRemoveLink(struct dbLocker *locker, struct link *plink); epicsShareFunc long dbGetNelements(const struct link *plink, long *nelements); epicsShareFunc int dbIsLinkConnected(const struct link *plink); epicsShareFunc int dbGetLinkDBFtype(const struct link *plink); @@ -77,7 +76,7 @@ epicsShareFunc long dbGetAlarm(const struct link *plink, epicsEnum16 *status, epicsEnum16 *severity); epicsShareFunc long dbGetTimeStamp(const struct link *plink, epicsTimeStamp *pstamp); -epicsShareFunc long dbPutLink(struct link *, short dbrType, +epicsShareFunc long dbPutLink(struct link *plink, short dbrType, const void *pbuffer, long nRequest); epicsShareFunc void dbScanFwdLink(struct link *plink); diff --git a/src/ioc/db/dbLock.c b/src/ioc/db/dbLock.c index 8a02adabf..c36301d35 100644 --- a/src/ioc/db/dbLock.c +++ b/src/ioc/db/dbLock.c @@ -774,7 +774,7 @@ void dbLockSetSplit(dbLocker *locker, dbCommon *pfirst, dbCommon *psecond) struct pv_link *plink1 = CONTAINER(bcur, struct pv_link, backlinknode); union value *plink2 = CONTAINER(plink1, union value, pv_link); DBLINK *plink = CONTAINER(plink2, DBLINK, value); - lockRecord *lr = plink->value.pv_link.precord->lset; + lockRecord *lr = plink->precord->lset; /* plink->type==DB_LINK is implied. Only DB_LINKs are tracked from BKLNK */ diff --git a/src/ioc/db/recGbl.c b/src/ioc/db/recGbl.c index b30cb5f79..7b7affd97 100644 --- a/src/ioc/db/recGbl.c +++ b/src/ioc/db/recGbl.c @@ -161,14 +161,9 @@ void recGblGetControlDouble(const struct dbAddr *paddr, &pcd->upper_ctrl_limit, &pcd->lower_ctrl_limit); } -int recGblInitConstantLink( - struct link *plink,short dbftype,void *pdest) +int recGblInitConstantLink(struct link *plink, short dbftype, void *pdest) { - long status = dbLoadLink(plink, dbftype, pdest); - - if (status) - return FALSE; - return TRUE; + return !dbLoadLink(plink, dbftype, pdest); } unsigned short recGblResetAlarms(void *precord) diff --git a/src/ioc/dbStatic/dbStaticLib.c b/src/ioc/dbStatic/dbStaticLib.c index e4ba47e2f..995f9d582 100644 --- a/src/ioc/dbStatic/dbStaticLib.c +++ b/src/ioc/dbStatic/dbStaticLib.c @@ -136,7 +136,9 @@ void dbFreeLinkContents(struct link *plink) } if(parm && (parm != pNullString)) free((void *)parm); if(plink->text) free(plink->text); - memset((char *)plink,0,sizeof(struct link)); + plink->lset = NULL; + plink->text = NULL; + memset(&plink->value, 0, sizeof(union value)); } void dbFreePath(DBBASE *pdbbase) @@ -1903,6 +1905,8 @@ long dbInitRecordLinks(dbRecordType *rtyp, struct dbCommon *prec) DBLINK *plink = (DBLINK *)(((char *)prec) + pflddes->offset); devSup *devsup = NULL; + plink->precord = prec; + /* link fields are zero'd on allocation. * so are effectively CONSTANT, but with constantStr==NULL. * Here we initialize them to have the correct link type, @@ -2934,7 +2938,6 @@ long dbCvtLinkToPvlink(DBENTRY *pdbentry) plink->type = PV_LINK; plink->value.pv_link.pvlMask = 0; plink->value.pv_link.pvname = 0; - plink->value.pv_link.precord = pdbentry->precnode->precord; return(0); default: epicsPrintf("dbCvtLinkToPvlink called for non link field\n"); diff --git a/src/ioc/dbStatic/link.h b/src/ioc/dbStatic/link.h index 5f2510616..e0063a68b 100644 --- a/src/ioc/dbStatic/link.h +++ b/src/ioc/dbStatic/link.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. \*************************************************************************/ /* link.h */ /* $Id$ */ @@ -34,7 +34,7 @@ extern "C" { #define BITBUS_IO 6 #define MACRO_LINK 7 -#define PN_LINK 9 +#define PN_LINK 9 #define DB_LINK 10 #define CA_LINK 11 #define INST_IO 12 /* instrument */ @@ -43,8 +43,8 @@ extern "C" { #define VXI_IO 15 #define LINK_NTYPES 15 typedef struct maplinkType { - char *strvalue; - int value; + char *strvalue; + int value; } maplinkType; epicsShareExtern maplinkType pamaplinkType[]; @@ -70,121 +70,124 @@ epicsShareExtern maplinkType pamaplinkType[]; #define pvlOptOutString 0x400 /*Output as string*/ #define pvlOptTSELisTime 0x800 /*Field TSEL is getting timeStamp*/ -typedef long (*LINKCVT)(); struct macro_link { - char *macroStr; + char *macroStr; }; struct dbCommon; -struct pvlet; +typedef long (*LINKCVT)(); struct pv_link { - ELLNODE backlinknode; - char *pvname; /* pvname link points to */ - struct dbCommon *precord; /* Address of record owning link */ - void *pvt; /* CA or DB private */ - LINKCVT getCvt; /* input conversion function */ - short pvlMask; /* Options mask */ - short lastGetdbrType; /* last dbrType for DB or CA get */ + ELLNODE backlinknode; + char *pvname; /* pvname link points to */ + void *pvt; /* CA or DB private */ + LINKCVT getCvt; /* input conversion function */ + short pvlMask; /* Options mask */ + short lastGetdbrType; /* last dbrType for DB or CA get */ }; /* structure of a VME io channel */ struct vmeio { - short card; - short signal; - char *parm; + short card; + short signal; + char *parm; }; /* structure of a CAMAC io channel */ struct camacio { - short b; - short c; - short n; - short a; - short f; - char *parm; + short b; + short c; + short n; + short a; + short f; + char *parm; }; /* structure of a RF io channel */ struct rfio { - short branch; - short cryo; - short micro; - short dataset; - short element; - long ext; + short branch; + short cryo; + short micro; + short dataset; + short element; + long ext; }; /* structure of a Allen-Bradley io channel */ struct abio { - short link; - short adapter; - short card; - short signal; - char *parm; + short link; + short adapter; + short card; + short signal; + char *parm; }; /* structure of a gpib io channel */ struct gpibio { - short link; - short addr; /* device address */ - char *parm; + short link; + short addr; /* device address */ + char *parm; }; /* structure of a bitbus io channel */ -struct bitbusio { - unsigned char link; - unsigned char node; - unsigned char port; - unsigned char signal; - char *parm; +struct bitbusio { + unsigned char link; + unsigned char node; + unsigned char port; + unsigned char signal; + char *parm; }; /* structure of a bitbus to gpib io channel */ -struct bbgpibio { - unsigned char link; - unsigned char bbaddr; - unsigned char gpibaddr; - unsigned char pad; - char *parm; +struct bbgpibio { + unsigned char link; + unsigned char bbaddr; + unsigned char gpibaddr; + unsigned char pad; + char *parm; }; /* structure of an instrument io link */ -struct instio { - char *string; +struct instio { + char *string; }; /* structure of a vxi link */ -struct vxiio{ - short flag; /* 0 = frame/slot, 1 = SA */ - short frame; - short slot; - short la; /* logical address if flag =1 */ - short signal; - char *parm; +struct vxiio { + short flag; /* 0 = frame/slot, 1 = SA */ + short frame; + short slot; + short la; /* logical address if flag =1 */ + short signal; + char *parm; }; /* union of possible address structures */ union value { - char *constantStr; /*constant string*/ - struct macro_link macro_link; /* link containing macro substitution*/ - struct pv_link pv_link; /* link to process variable*/ - struct vmeio vmeio; /* vme io point */ - struct camacio camacio; /* camac io point */ - struct rfio rfio; /* CEBAF RF buffer interface */ - struct abio abio; /* allen-bradley io point */ - struct gpibio gpibio; - struct bitbusio bitbusio; - struct instio instio; /* instrument io link */ - struct bbgpibio bbgpibio; /* bitbus to gpib io link */ - struct vxiio vxiio; /* vxi io */ + char *constantStr; /*constant string*/ + struct macro_link macro_link; /* link containing macro substitution*/ + struct pv_link pv_link; /* link to process variable*/ + struct vmeio vmeio; /* vme io point */ + struct camacio camacio; /* camac io point */ + struct rfio rfio; /* CEBAF RF buffer interface */ + struct abio abio; /* allen-bradley io point */ + struct gpibio gpibio; + struct bitbusio bitbusio; + struct instio instio; /* instrument io link */ + struct bbgpibio bbgpibio; /* bitbus to gpib io link */ + struct vxiio vxiio; /* vxi io */ }; +struct lset; + struct link { - union value value; - short type; - char *text; /* original INP/OUT link text */ + struct dbCommon *precord; /* Pointer to record owning link */ + short type; + short flags; + struct lset *lset; + char *text; /* Raw link text */ + union value value; }; typedef struct link DBLINK; diff --git a/src/ioc/misc/iocInit.c b/src/ioc/misc/iocInit.c index f7f259201..974052655 100644 --- a/src/ioc/misc/iocInit.c +++ b/src/ioc/misc/iocInit.c @@ -509,8 +509,7 @@ static void doResolveLinks(dbRecordType *pdbRecordType, dbCommon *precord, } } - if (plink->type == PV_LINK) - dbInitLink(precord, plink, pdbFldDes->field_type); + dbInitLink(plink, pdbFldDes->field_type); } } @@ -635,8 +634,7 @@ static void doCloseLinks(dbRecordType *pdbRecordType, dbCommon *precord, dbScanLock(precord); locked = 1; } - dbCaRemoveLink(plink); - plink->type = PV_LINK; + dbCaRemoveLink(NULL, plink); } else if (plink->type == DB_LINK) { /* free link, but don't split lockset like dbDbRemoveLink() */ diff --git a/src/std/dev/devAiSoftCallback.c b/src/std/dev/devAiSoftCallback.c index 3744509ed..cd3b7fc41 100644 --- a/src/std/dev/devAiSoftCallback.c +++ b/src/std/dev/devAiSoftCallback.c @@ -110,7 +110,6 @@ static long add_record(dbCommon *pcommon) ppn = &pdevPvt->pn; plink->type = PN_LINK; - plink->value.pv_link.precord = pcommon; plink->value.pv_link.pvlMask &= pvlOptMsMode; /* Severity flags only */ ppn->usrPvt = prec; diff --git a/src/std/dev/devBiSoftCallback.c b/src/std/dev/devBiSoftCallback.c index 02887ebe7..67c15260c 100644 --- a/src/std/dev/devBiSoftCallback.c +++ b/src/std/dev/devBiSoftCallback.c @@ -108,7 +108,6 @@ static long add_record(dbCommon *pcommon) ppn = &pdevPvt->pn; plink->type = PN_LINK; - plink->value.pv_link.precord = pcommon; plink->value.pv_link.pvlMask &= pvlOptMsMode; /* Severity flags only */ ppn->usrPvt = prec; diff --git a/src/std/dev/devLiSoftCallback.c b/src/std/dev/devLiSoftCallback.c index 90bbff311..5530e7089 100644 --- a/src/std/dev/devLiSoftCallback.c +++ b/src/std/dev/devLiSoftCallback.c @@ -108,7 +108,6 @@ static long add_record(dbCommon *pcommon) ppn = &pdevPvt->pn; plink->type = PN_LINK; - plink->value.pv_link.precord = pcommon; plink->value.pv_link.pvlMask &= pvlOptMsMode; /* Severity flags only */ ppn->usrPvt = prec; diff --git a/src/std/dev/devMbbiDirectSoftCallback.c b/src/std/dev/devMbbiDirectSoftCallback.c index 6234a163b..cfcce0ffe 100644 --- a/src/std/dev/devMbbiDirectSoftCallback.c +++ b/src/std/dev/devMbbiDirectSoftCallback.c @@ -108,7 +108,6 @@ static long add_record(dbCommon *pcommon) ppn = &pdevPvt->pn; plink->type = PN_LINK; - plink->value.pv_link.precord = pcommon; plink->value.pv_link.pvlMask &= pvlOptMsMode; /* Severity flags only */ ppn->usrPvt = prec; diff --git a/src/std/dev/devMbbiSoftCallback.c b/src/std/dev/devMbbiSoftCallback.c index 5447b4b6e..fee8d30f0 100644 --- a/src/std/dev/devMbbiSoftCallback.c +++ b/src/std/dev/devMbbiSoftCallback.c @@ -108,7 +108,6 @@ static long add_record(dbCommon *pcommon) ppn = &pdevPvt->pn; plink->type = PN_LINK; - plink->value.pv_link.precord = pcommon; plink->value.pv_link.pvlMask &= pvlOptMsMode; /* Severity flags only */ ppn->usrPvt = prec; diff --git a/src/std/dev/devSiSoftCallback.c b/src/std/dev/devSiSoftCallback.c index e2eff3213..715754218 100644 --- a/src/std/dev/devSiSoftCallback.c +++ b/src/std/dev/devSiSoftCallback.c @@ -110,7 +110,6 @@ static long add_record(dbCommon *pcommon) } plink->type = PN_LINK; - plink->value.pv_link.precord = pcommon; plink->value.pv_link.pvlMask &= pvlOptMsMode; /* Severity flags only */ ppn->usrPvt = prec;