Move closer to having pluggable link types.

All link types now have a plink->precord pointer.
Add link support entry tables for const, DB and CA link types.
Route all link I/O options through the new plink->lset.
This commit is contained in:
Andrew Johnson
2015-07-22 14:56:48 -05:00
16 changed files with 316 additions and 280 deletions

View File

@@ -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:

View File

@@ -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));

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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)

View File

@@ -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");

View File

@@ -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;

View File

@@ -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() */

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;