hold lock while changing fields
This commit is contained in:
+294
-289
@@ -13,15 +13,15 @@ of this distribution.
|
||||
|
||||
/****************************************************************
|
||||
*
|
||||
* Current Author: Bob Dalesio
|
||||
* Contributing Author: Marty Kraimer
|
||||
* Date: 26MAR96
|
||||
* Current Author: Bob Dalesio
|
||||
* Contributing Author: Marty Kraimer
|
||||
* Date: 26MAR96
|
||||
*
|
||||
* Complete replacement for dbCaDblink.c dbCaLink.c (Nicholas T. Karonis)
|
||||
* Complete replacement for dbCaDblink.c dbCaLink.c (Nicholas T. Karonis)
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 26MAR96 lrd rewritten for simplicity, robustness and flexibility
|
||||
* .01 26MAR96 lrd rewritten for simplicity, robustness and flexibility
|
||||
****************************************************************/
|
||||
|
||||
#include <stddef.h>
|
||||
@@ -43,6 +43,7 @@ of this distribution.
|
||||
#include "epicsPrint.h"
|
||||
#include "dbCommon.h"
|
||||
#include "cadef.h"
|
||||
#include "epicsAssert.h"
|
||||
/*following because we cant include dbStaticLib.h*/
|
||||
epicsShareFunc void * epicsShareAPI dbCalloc(size_t nobj,size_t size);
|
||||
#define epicsExportSharedSymbols
|
||||
@@ -52,7 +53,7 @@ epicsShareFunc void * epicsShareAPI dbCalloc(size_t nobj,size_t size);
|
||||
#include "dbCa.h"
|
||||
#include "dbCaPvt.h"
|
||||
|
||||
static ELLLIST caList; /* Work list for dbCaTask */
|
||||
static ELLLIST caList; /* Work list for dbCaTask */
|
||||
static epicsMutexId caListSem; /*Mutual exclusions semaphores for caList*/
|
||||
static epicsEventId caWakeupSem; /*wakeup semaphore for dbCaTask*/
|
||||
void dbCaTask(void); /*The Channel Access Task*/
|
||||
@@ -82,29 +83,32 @@ static void addAction(caLink *pca, short link_action)
|
||||
void epicsShareAPI dbCaLinkInit(void)
|
||||
{
|
||||
dbServiceIOInit();
|
||||
ellInit(&caList);
|
||||
caListSem = epicsMutexMustCreate();
|
||||
caWakeupSem = epicsEventMustCreate(epicsEventEmpty);
|
||||
epicsThreadCreate("dbCaLink", epicsThreadPriorityMedium,
|
||||
epicsThreadGetStackSize(epicsThreadStackBig), (EPICSTHREADFUNC) dbCaTask,0);
|
||||
ellInit(&caList);
|
||||
caListSem = epicsMutexMustCreate();
|
||||
caWakeupSem = epicsEventMustCreate(epicsEventEmpty);
|
||||
epicsThreadCreate("dbCaLink", epicsThreadPriorityMedium,
|
||||
epicsThreadGetStackSize(epicsThreadStackBig),
|
||||
(EPICSTHREADFUNC) dbCaTask,0);
|
||||
}
|
||||
|
||||
void epicsShareAPI dbCaAddLink( struct link *plink)
|
||||
{
|
||||
caLink *pca;
|
||||
caLink *pca;
|
||||
|
||||
pca = (caLink*)dbCalloc(1,sizeof(caLink));
|
||||
pca->plink = plink;
|
||||
plink->type = CA_LINK;
|
||||
plink->value.pv_link.pvt = pca;
|
||||
pca->lock = epicsMutexMustCreate();
|
||||
addAction(pca,CA_CONNECT);
|
||||
return;
|
||||
pca = (caLink*)dbCalloc(1,sizeof(caLink));
|
||||
pca->lock = epicsMutexMustCreate();
|
||||
epicsMutexMustLock(pca->lock);
|
||||
pca->plink = plink;
|
||||
plink->type = CA_LINK;
|
||||
plink->value.pv_link.pvt = pca;
|
||||
epicsMutexUnlock(pca->lock);
|
||||
addAction(pca,CA_CONNECT);
|
||||
return;
|
||||
}
|
||||
|
||||
void epicsShareAPI dbCaRemoveLink( struct link *plink)
|
||||
{
|
||||
caLink *pca = (caLink *)plink->value.pv_link.pvt;
|
||||
caLink *pca = (caLink *)plink->value.pv_link.pvt;
|
||||
|
||||
if(!pca) return;
|
||||
epicsMutexMustLock(pca->lock);
|
||||
@@ -116,67 +120,67 @@ void epicsShareAPI dbCaRemoveLink( struct link *plink)
|
||||
|
||||
|
||||
long epicsShareAPI dbCaGetLink(struct link *plink,short dbrType, void *pdest,
|
||||
unsigned short *psevr,long *nelements)
|
||||
unsigned short *psevr,long *nelements)
|
||||
{
|
||||
caLink *pca = (caLink *)plink->value.pv_link.pvt;
|
||||
long status = 0;
|
||||
long (*pconvert)();
|
||||
short link_action = 0;
|
||||
caLink *pca = (caLink *)plink->value.pv_link.pvt;
|
||||
long status = 0;
|
||||
long (*pconvert)();
|
||||
short link_action = 0;
|
||||
|
||||
if(!pca) {
|
||||
errlogPrintf("dbCaGetLink: record %s pv_link.pvt is NULL\n",
|
||||
plink->value.pv_link.precord);
|
||||
return(-1);
|
||||
errlogPrintf("dbCaGetLink: record %s pv_link.pvt is NULL\n",
|
||||
plink->value.pv_link.precord);
|
||||
return(-1);
|
||||
}
|
||||
epicsMutexMustLock(pca->lock);
|
||||
if(!pca->chid || ca_state(pca->chid) != cs_conn) {
|
||||
pca->sevr = INVALID_ALARM;
|
||||
goto done;
|
||||
pca->sevr = INVALID_ALARM;
|
||||
goto done;
|
||||
}
|
||||
if(!ca_read_access(pca->chid)) {
|
||||
pca->sevr = INVALID_ALARM;
|
||||
goto done;
|
||||
pca->sevr = INVALID_ALARM;
|
||||
goto done;
|
||||
}
|
||||
if((pca->dbrType == DBR_ENUM) && (dbDBRnewToDBRold[dbrType] == DBR_STRING)){
|
||||
/*Must ask server for DBR_STRING*/
|
||||
if(!pca->pgetString) {
|
||||
plink->value.pv_link.pvlMask |= pvlOptInpString;
|
||||
link_action |= CA_MONITOR_STRING;
|
||||
}
|
||||
if(!pca->gotInString) {
|
||||
pca->sevr = INVALID_ALARM;
|
||||
goto done;
|
||||
}
|
||||
if(nelements) *nelements = 1;
|
||||
pconvert=dbFastGetConvertRoutine[dbDBRoldToDBFnew[DBR_STRING]][dbrType];
|
||||
status = (*(pconvert))(pca->pgetString, pdest, 0);
|
||||
goto done;
|
||||
/*Must ask server for DBR_STRING*/
|
||||
if(!pca->pgetString) {
|
||||
plink->value.pv_link.pvlMask |= pvlOptInpString;
|
||||
link_action |= CA_MONITOR_STRING;
|
||||
}
|
||||
if(!pca->gotInString) {
|
||||
pca->sevr = INVALID_ALARM;
|
||||
goto done;
|
||||
}
|
||||
if(nelements) *nelements = 1;
|
||||
pconvert=dbFastGetConvertRoutine[dbDBRoldToDBFnew[DBR_STRING]][dbrType];
|
||||
status = (*(pconvert))(pca->pgetString, pdest, 0);
|
||||
goto done;
|
||||
}
|
||||
if(!pca->pgetNative) {
|
||||
plink->value.pv_link.pvlMask |= pvlOptInpNative;
|
||||
link_action |= CA_MONITOR_NATIVE;
|
||||
plink->value.pv_link.pvlMask |= pvlOptInpNative;
|
||||
link_action |= CA_MONITOR_NATIVE;
|
||||
}
|
||||
if(!pca->gotInNative){
|
||||
pca->sevr = INVALID_ALARM;
|
||||
goto done;
|
||||
pca->sevr = INVALID_ALARM;
|
||||
goto done;
|
||||
}
|
||||
if(!nelements || *nelements == 1){
|
||||
pconvert=
|
||||
dbFastGetConvertRoutine[dbDBRoldToDBFnew[pca->dbrType]][dbrType];
|
||||
(*(pconvert))(pca->pgetNative, pdest, 0);
|
||||
pconvert=
|
||||
dbFastGetConvertRoutine[dbDBRoldToDBFnew[pca->dbrType]][dbrType];
|
||||
(*(pconvert))(pca->pgetNative, pdest, 0);
|
||||
}else{
|
||||
unsigned long ntoget = *nelements;
|
||||
struct dbAddr dbAddr;
|
||||
unsigned long ntoget = *nelements;
|
||||
struct dbAddr dbAddr;
|
||||
|
||||
if(ntoget > pca->nelements) ntoget = pca->nelements;
|
||||
*nelements = ntoget;
|
||||
pconvert = dbGetConvertRoutine[dbDBRoldToDBFnew[pca->dbrType]][dbrType];
|
||||
memset((void *)&dbAddr,0,sizeof(dbAddr));
|
||||
dbAddr.pfield = pca->pgetNative;
|
||||
/*Following will only be used for pca->dbrType == DBR_STRING*/
|
||||
dbAddr.field_size = MAX_STRING_SIZE;
|
||||
/*Ignore error return*/
|
||||
(*(pconvert))(&dbAddr,pdest,ntoget,ntoget,0);
|
||||
if(ntoget > pca->nelements) ntoget = pca->nelements;
|
||||
*nelements = ntoget;
|
||||
pconvert = dbGetConvertRoutine[dbDBRoldToDBFnew[pca->dbrType]][dbrType];
|
||||
memset((void *)&dbAddr,0,sizeof(dbAddr));
|
||||
dbAddr.pfield = pca->pgetNative;
|
||||
/*Following will only be used for pca->dbrType == DBR_STRING*/
|
||||
dbAddr.field_size = MAX_STRING_SIZE;
|
||||
/*Ignore error return*/
|
||||
(*(pconvert))(&dbAddr,pdest,ntoget,ntoget,0);
|
||||
}
|
||||
done:
|
||||
if(psevr) *psevr = pca->sevr;
|
||||
@@ -186,60 +190,60 @@ done:
|
||||
}
|
||||
|
||||
long epicsShareAPI dbCaPutLink(struct link *plink,short dbrType,
|
||||
const void *psource,long nelements)
|
||||
const void *psource,long nelements)
|
||||
{
|
||||
caLink *pca = (caLink *)plink->value.pv_link.pvt;
|
||||
long (*pconvert)();
|
||||
long status = 0;
|
||||
short link_action = 0;
|
||||
caLink *pca = (caLink *)plink->value.pv_link.pvt;
|
||||
long (*pconvert)();
|
||||
long status = 0;
|
||||
short link_action = 0;
|
||||
|
||||
if(!pca) {
|
||||
errlogPrintf("dbCaPutLink: record %s pv_link.pvt is NULL\n",
|
||||
plink->value.pv_link.precord);
|
||||
return(-1);
|
||||
errlogPrintf("dbCaPutLink: record %s pv_link.pvt is NULL\n",
|
||||
plink->value.pv_link.precord);
|
||||
return(-1);
|
||||
}
|
||||
/* put the new value in */
|
||||
epicsMutexMustLock(pca->lock);
|
||||
if(!pca->chid || ca_state(pca->chid) != cs_conn) {
|
||||
epicsMutexUnlock(pca->lock);
|
||||
return(-1);
|
||||
epicsMutexUnlock(pca->lock);
|
||||
return(-1);
|
||||
}
|
||||
if((pca->dbrType == DBR_ENUM) && (dbDBRnewToDBRold[dbrType] == DBR_STRING)){
|
||||
/*Must send DBR_STRING*/
|
||||
if(!pca->pputString) {
|
||||
pca->pputString = dbCalloc(MAX_STRING_SIZE,sizeof(char));
|
||||
plink->value.pv_link.pvlMask |= pvlOptOutString;
|
||||
}
|
||||
pconvert=dbFastPutConvertRoutine[dbrType][dbDBRoldToDBFnew[DBR_STRING]];
|
||||
status = (*(pconvert))(psource,pca->pputString, 0);
|
||||
link_action |= CA_WRITE_STRING;
|
||||
pca->gotOutString = TRUE;
|
||||
if(pca->newOutString) pca->nNoWrite++;
|
||||
pca->newOutString = TRUE;
|
||||
/*Must send DBR_STRING*/
|
||||
if(!pca->pputString) {
|
||||
pca->pputString = dbCalloc(MAX_STRING_SIZE,sizeof(char));
|
||||
plink->value.pv_link.pvlMask |= pvlOptOutString;
|
||||
}
|
||||
pconvert=dbFastPutConvertRoutine[dbrType][dbDBRoldToDBFnew[DBR_STRING]];
|
||||
status = (*(pconvert))(psource,pca->pputString, 0);
|
||||
link_action |= CA_WRITE_STRING;
|
||||
pca->gotOutString = TRUE;
|
||||
if(pca->newOutString) pca->nNoWrite++;
|
||||
pca->newOutString = TRUE;
|
||||
} else {
|
||||
if(!pca->pputNative) {
|
||||
pca->pputNative = dbCalloc(pca->nelements,
|
||||
dbr_value_size[ca_field_type(pca->chid)]);
|
||||
plink->value.pv_link.pvlMask |= pvlOptOutString;
|
||||
}
|
||||
if(nelements == 1){
|
||||
pconvert = dbFastPutConvertRoutine
|
||||
[dbrType][dbDBRoldToDBFnew[pca->dbrType]];
|
||||
status = (*(pconvert))(psource,pca->pputNative, 0);
|
||||
}else{
|
||||
struct dbAddr dbAddr;
|
||||
pconvert = dbPutConvertRoutine
|
||||
[dbrType][dbDBRoldToDBFnew[pca->dbrType]];
|
||||
memset((void *)&dbAddr,0,sizeof(dbAddr));
|
||||
dbAddr.pfield = pca->pputNative;
|
||||
/*Following only used for DBF_STRING*/
|
||||
dbAddr.field_size = MAX_STRING_SIZE;
|
||||
status = (*(pconvert))(&dbAddr,psource,nelements,pca->nelements,0);
|
||||
}
|
||||
link_action |= CA_WRITE_NATIVE;
|
||||
pca->gotOutNative = TRUE;
|
||||
if(pca->newOutNative) pca->nNoWrite++;
|
||||
pca->newOutNative = TRUE;
|
||||
if(!pca->pputNative) {
|
||||
pca->pputNative = dbCalloc(pca->nelements,
|
||||
dbr_value_size[ca_field_type(pca->chid)]);
|
||||
plink->value.pv_link.pvlMask |= pvlOptOutString;
|
||||
}
|
||||
if(nelements == 1){
|
||||
pconvert = dbFastPutConvertRoutine
|
||||
[dbrType][dbDBRoldToDBFnew[pca->dbrType]];
|
||||
status = (*(pconvert))(psource,pca->pputNative, 0);
|
||||
}else{
|
||||
struct dbAddr dbAddr;
|
||||
pconvert = dbPutConvertRoutine
|
||||
[dbrType][dbDBRoldToDBFnew[pca->dbrType]];
|
||||
memset((void *)&dbAddr,0,sizeof(dbAddr));
|
||||
dbAddr.pfield = pca->pputNative;
|
||||
/*Following only used for DBF_STRING*/
|
||||
dbAddr.field_size = MAX_STRING_SIZE;
|
||||
status = (*(pconvert))(&dbAddr,psource,nelements,pca->nelements,0);
|
||||
}
|
||||
link_action |= CA_WRITE_NATIVE;
|
||||
pca->gotOutNative = TRUE;
|
||||
if(pca->newOutNative) pca->nNoWrite++;
|
||||
pca->newOutNative = TRUE;
|
||||
}
|
||||
epicsMutexUnlock(pca->lock);
|
||||
addAction(pca,link_action);
|
||||
@@ -247,27 +251,27 @@ long epicsShareAPI dbCaPutLink(struct link *plink,short dbrType,
|
||||
}
|
||||
|
||||
long epicsShareAPI dbCaGetAttributes(const struct link *plink,
|
||||
void (*callback)(void *usrPvt),void *usrPvt)
|
||||
void (*callback)(void *usrPvt),void *usrPvt)
|
||||
{
|
||||
caLink *pca;
|
||||
long status = 0;
|
||||
short link_action = 0;
|
||||
caLink *pca;
|
||||
long status = 0;
|
||||
short link_action = 0;
|
||||
caAttributes *pcaAttributes;
|
||||
|
||||
if(!plink || (plink->type!=CA_LINK)) {
|
||||
errlogPrintf("dbCaGetAttributes: called for non CA_LINK\n");
|
||||
return(-1);
|
||||
errlogPrintf("dbCaGetAttributes: called for non CA_LINK\n");
|
||||
return(-1);
|
||||
}
|
||||
pca = (caLink *)plink->value.pv_link.pvt;
|
||||
if(!pca) {
|
||||
errlogPrintf("dbCaGetAttributes: record %s pv_link.pvt is NULL\n",
|
||||
plink->value.pv_link.precord);
|
||||
return(-1);
|
||||
errlogPrintf("dbCaGetAttributes: record %s pv_link.pvt is NULL\n",
|
||||
plink->value.pv_link.precord);
|
||||
return(-1);
|
||||
}
|
||||
if(pca->pcaAttributes) {
|
||||
errlogPrintf("dbCaGetAttributes: record %s duplicate call\n",
|
||||
plink->value.pv_link.precord);
|
||||
return(-1);
|
||||
errlogPrintf("dbCaGetAttributes: record %s duplicate call\n",
|
||||
plink->value.pv_link.precord);
|
||||
return(-1);
|
||||
}
|
||||
pcaAttributes = dbCalloc(1,sizeof(caAttributes));
|
||||
pcaAttributes->callback = callback;
|
||||
@@ -282,7 +286,7 @@ long epicsShareAPI dbCaGetAttributes(const struct link *plink,
|
||||
|
||||
caAttributes *getpcaAttributes(const struct link *plink)
|
||||
{
|
||||
caLink *pca;
|
||||
caLink *pca;
|
||||
|
||||
if(!plink || (plink->type!=CA_LINK)) return(NULL);
|
||||
pca = (caLink *)plink->value.pv_link.pvt;
|
||||
@@ -355,7 +359,7 @@ long epicsShareAPI dbCaGetUnits(
|
||||
long epicsShareAPI dbCaGetNelements(
|
||||
const struct link *plink,long *nelements)
|
||||
{
|
||||
caLink *pca;
|
||||
caLink *pca;
|
||||
|
||||
if(!plink) return(-1);
|
||||
if(plink->type != CA_LINK) return(-1);
|
||||
@@ -368,7 +372,7 @@ long epicsShareAPI dbCaGetNelements(
|
||||
long epicsShareAPI dbCaGetSevr(
|
||||
const struct link *plink,short *severity)
|
||||
{
|
||||
caLink *pca;
|
||||
caLink *pca;
|
||||
|
||||
if(!plink) return(-1);
|
||||
if(plink->type != CA_LINK) return(-1);
|
||||
@@ -381,7 +385,7 @@ long epicsShareAPI dbCaGetSevr(
|
||||
long epicsShareAPI dbCaGetTimeStamp(
|
||||
const struct link *plink,epicsTimeStamp *pstamp)
|
||||
{
|
||||
caLink *pca;
|
||||
caLink *pca;
|
||||
|
||||
if(!plink) return(-1);
|
||||
if(plink->type != CA_LINK) return(-1);
|
||||
@@ -394,7 +398,7 @@ long epicsShareAPI dbCaGetTimeStamp(
|
||||
int epicsShareAPI dbCaIsLinkConnected(
|
||||
const struct link *plink)
|
||||
{
|
||||
caLink *pca;
|
||||
caLink *pca;
|
||||
|
||||
if(!plink) return(FALSE);
|
||||
if(plink->type != CA_LINK) return(FALSE);
|
||||
@@ -404,10 +408,11 @@ int epicsShareAPI dbCaIsLinkConnected(
|
||||
if(ca_state(pca->chid)==cs_conn) return(TRUE);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
int epicsShareAPI dbCaGetLinkDBFtype(
|
||||
const struct link *plink)
|
||||
{
|
||||
caLink *pca;
|
||||
caLink *pca;
|
||||
|
||||
if(!plink) return(-1);
|
||||
if(plink->type != CA_LINK) return(-1);
|
||||
@@ -415,16 +420,16 @@ int epicsShareAPI dbCaGetLinkDBFtype(
|
||||
if(!pca) return(-1);
|
||||
if(!pca->chid) return(-1);
|
||||
if(ca_state(pca->chid)==cs_conn)
|
||||
return(dbDBRoldToDBFnew[ca_field_type(pca->chid)]);
|
||||
return(dbDBRoldToDBFnew[ca_field_type(pca->chid)]);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
static void exceptionCallback(struct exception_handler_args args)
|
||||
{
|
||||
chid chid = args.chid;
|
||||
chid chid = args.chid;
|
||||
long stat = args.stat; /* Channel access status code*/
|
||||
const char *channel;
|
||||
const char *channel;
|
||||
const char *context;
|
||||
static char *unknown = "unknown";
|
||||
const char *nativeType;
|
||||
@@ -453,7 +458,7 @@ static void exceptionCallback(struct exception_handler_args args)
|
||||
(readAccess ? "readAccess" : "noReadAccess"),
|
||||
(writeAccess ? "writeAccess" : "noWriteAccess"));
|
||||
}
|
||||
|
||||
|
||||
static void eventCallback(struct event_handler_args arg)
|
||||
{
|
||||
caLink *pca = (caLink *)arg.usr;
|
||||
@@ -474,10 +479,10 @@ static void eventCallback(struct event_handler_args arg)
|
||||
if(precord) {
|
||||
if((arg.status!=ECA_NORDACCESS) && (arg.status!=ECA_GETFAIL))
|
||||
errlogPrintf("dbCa: eventCallback record %s error %s\n",
|
||||
precord->name,ca_message(arg.status));
|
||||
precord->name,ca_message(arg.status));
|
||||
} else {
|
||||
errlogPrintf("dbCa: eventCallback error %s\n",
|
||||
ca_message(arg.status));
|
||||
ca_message(arg.status));
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
@@ -515,69 +520,69 @@ static void eventCallback(struct event_handler_args arg)
|
||||
scanOnce(precord);
|
||||
}
|
||||
done:
|
||||
epicsMutexUnlock(pca->lock);
|
||||
epicsMutexUnlock(pca->lock);
|
||||
}
|
||||
|
||||
static void getAttribEventCallback(struct event_handler_args arg)
|
||||
{
|
||||
caLink *pca = (caLink *)arg.usr;
|
||||
struct link *plink;
|
||||
caLink *pca = (caLink *)arg.usr;
|
||||
struct link *plink;
|
||||
const struct dbr_ctrl_double *dbr;
|
||||
caAttributes *pcaAttributes = NULL;
|
||||
caAttributes *pcaAttributes = NULL;
|
||||
|
||||
if(!pca) {
|
||||
errlogPrintf("getAttribEventCallback why was arg.usr NULL\n");
|
||||
return;
|
||||
}
|
||||
epicsMutexMustLock(pca->lock);
|
||||
plink = pca->plink;
|
||||
if(!plink) goto done;
|
||||
if(!arg.dbr) {
|
||||
errlogPrintf("getAttribEventCallback why was arg.dbr NULL\n");
|
||||
goto done;
|
||||
}
|
||||
dbr = arg.dbr;
|
||||
pcaAttributes = pca->pcaAttributes;
|
||||
if(!pcaAttributes) goto done;
|
||||
pcaAttributes->data = *dbr; /*copy entire structure*/
|
||||
pcaAttributes->gotData = TRUE;
|
||||
(pcaAttributes->callback)(pcaAttributes->usrPvt);
|
||||
if(!pca) {
|
||||
errlogPrintf("getAttribEventCallback why was arg.usr NULL\n");
|
||||
return;
|
||||
}
|
||||
epicsMutexMustLock(pca->lock);
|
||||
plink = pca->plink;
|
||||
if(!plink) goto done;
|
||||
if(!arg.dbr) {
|
||||
errlogPrintf("getAttribEventCallback why was arg.dbr NULL\n");
|
||||
goto done;
|
||||
}
|
||||
dbr = arg.dbr;
|
||||
pcaAttributes = pca->pcaAttributes;
|
||||
if(!pcaAttributes) goto done;
|
||||
pcaAttributes->data = *dbr; /*copy entire structure*/
|
||||
pcaAttributes->gotData = TRUE;
|
||||
(pcaAttributes->callback)(pcaAttributes->usrPvt);
|
||||
done:
|
||||
epicsMutexUnlock(pca->lock);
|
||||
epicsMutexUnlock(pca->lock);
|
||||
}
|
||||
|
||||
static void accessRightsCallback(struct access_rights_handler_args arg)
|
||||
{
|
||||
caLink *pca = (caLink *)ca_puser(arg.chid);
|
||||
struct link *plink;
|
||||
caLink *pca = (caLink *)ca_puser(arg.chid);
|
||||
struct link *plink;
|
||||
|
||||
if(!pca) {
|
||||
errlogPrintf("accessRightsCallback why was arg.usr NULL\n");
|
||||
return;
|
||||
}
|
||||
if(ca_state(pca->chid) != cs_conn) return;/*connectionCallback will handle*/
|
||||
epicsMutexMustLock(pca->lock);
|
||||
if(ca_read_access(arg.chid) || ca_write_access(arg.chid)) goto done;
|
||||
plink = pca->plink;
|
||||
if(plink) {
|
||||
struct pv_link *ppv_link = &(plink->value.pv_link);
|
||||
dbCommon *precord = ppv_link->precord;
|
||||
if(!pca) {
|
||||
errlogPrintf("accessRightsCallback why was arg.usr NULL\n");
|
||||
return;
|
||||
}
|
||||
if(ca_state(pca->chid) != cs_conn) return;/*connectionCallback will handle*/
|
||||
epicsMutexMustLock(pca->lock);
|
||||
if(ca_read_access(arg.chid) || ca_write_access(arg.chid)) goto done;
|
||||
plink = pca->plink;
|
||||
if(plink) {
|
||||
struct pv_link *ppv_link = &(plink->value.pv_link);
|
||||
dbCommon *precord = ppv_link->precord;
|
||||
|
||||
if(precord) {
|
||||
if((ppv_link->pvlMask&pvlOptCP)
|
||||
|| ((ppv_link->pvlMask&pvlOptCPP)&&(precord->scan==0)))
|
||||
scanOnce(precord);
|
||||
}
|
||||
}
|
||||
if(precord) {
|
||||
if((ppv_link->pvlMask&pvlOptCP)
|
||||
|| ((ppv_link->pvlMask&pvlOptCPP)&&(precord->scan==0)))
|
||||
scanOnce(precord);
|
||||
}
|
||||
}
|
||||
done:
|
||||
epicsMutexUnlock(pca->lock);
|
||||
epicsMutexUnlock(pca->lock);
|
||||
}
|
||||
|
||||
static void connectionCallback(struct connection_handler_args arg)
|
||||
{
|
||||
caLink *pca;
|
||||
short link_action = 0;
|
||||
struct link *plink;
|
||||
caLink *pca;
|
||||
short link_action = 0;
|
||||
struct link *plink;
|
||||
|
||||
pca = ca_puser(arg.chid);
|
||||
if(!pca) return;
|
||||
@@ -585,44 +590,44 @@ static void connectionCallback(struct connection_handler_args arg)
|
||||
plink = pca->plink;
|
||||
if(!plink) goto done;
|
||||
if(ca_state(arg.chid) != cs_conn){
|
||||
struct pv_link *ppv_link = &(plink->value.pv_link);
|
||||
dbCommon *precord = ppv_link->precord;
|
||||
struct pv_link *ppv_link = &(plink->value.pv_link);
|
||||
dbCommon *precord = ppv_link->precord;
|
||||
|
||||
pca->nDisconnect++;
|
||||
if(precord) {
|
||||
if((ppv_link->pvlMask&pvlOptCP)
|
||||
|| ((ppv_link->pvlMask&pvlOptCPP)&&(precord->scan==0)))
|
||||
scanOnce(precord);
|
||||
}
|
||||
goto done;
|
||||
pca->nDisconnect++;
|
||||
if(precord) {
|
||||
if((ppv_link->pvlMask&pvlOptCP)
|
||||
|| ((ppv_link->pvlMask&pvlOptCPP)&&(precord->scan==0)))
|
||||
scanOnce(precord);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
if(pca->gotFirstConnection) {
|
||||
if((pca->nelements != ca_element_count(arg.chid))
|
||||
|| (pca->dbrType != ca_field_type(arg.chid))){
|
||||
/* field type or nelements changed */
|
||||
/*Only safe thing is to delete old caLink and allocate a new one*/
|
||||
pca->plink = 0;
|
||||
plink->value.pv_link.pvt = 0;
|
||||
epicsMutexUnlock(pca->lock);
|
||||
addAction(pca,CA_DELETE);
|
||||
dbCaAddLink(plink);
|
||||
return;
|
||||
}
|
||||
if((pca->nelements != ca_element_count(arg.chid))
|
||||
|| (pca->dbrType != ca_field_type(arg.chid))){
|
||||
/* field type or nelements changed */
|
||||
/*Only safe thing is to delete old caLink and allocate a new one*/
|
||||
pca->plink = 0;
|
||||
plink->value.pv_link.pvt = 0;
|
||||
epicsMutexUnlock(pca->lock);
|
||||
addAction(pca,CA_DELETE);
|
||||
dbCaAddLink(plink);
|
||||
return;
|
||||
}
|
||||
}
|
||||
pca->gotFirstConnection = TRUE;
|
||||
pca->nelements = ca_element_count(arg.chid);
|
||||
pca->dbrType = ca_field_type(arg.chid);
|
||||
if((plink->value.pv_link.pvlMask & pvlOptInpNative) && (!pca->pgetNative)){
|
||||
link_action |= CA_MONITOR_NATIVE;
|
||||
link_action |= CA_MONITOR_NATIVE;
|
||||
}
|
||||
if((plink->value.pv_link.pvlMask & pvlOptInpString) && (!pca->pgetString)){
|
||||
link_action |= CA_MONITOR_STRING;
|
||||
link_action |= CA_MONITOR_STRING;
|
||||
}
|
||||
if((plink->value.pv_link.pvlMask & pvlOptOutNative) && (pca->gotOutNative)){
|
||||
link_action |= CA_WRITE_NATIVE;
|
||||
link_action |= CA_WRITE_NATIVE;
|
||||
}
|
||||
if((plink->value.pv_link.pvlMask & pvlOptOutString) && (pca->gotOutString)){
|
||||
link_action |= CA_WRITE_STRING;
|
||||
link_action |= CA_WRITE_STRING;
|
||||
}
|
||||
if(pca->pcaAttributes) link_action |= CA_GET_ATTRIBUTES;
|
||||
done:
|
||||
@@ -633,103 +638,103 @@ done:
|
||||
void dbCaTask()
|
||||
{
|
||||
static const int enablePreemption = 1u;
|
||||
caLink *pca;
|
||||
short link_action;
|
||||
int status;
|
||||
caLink *pca;
|
||||
short link_action;
|
||||
int status;
|
||||
|
||||
taskwdInsert(epicsThreadGetIdSelf(),NULL,NULL);
|
||||
SEVCHK(ca_context_create(enablePreemption),
|
||||
"dbCaTask calling ca_context_create");
|
||||
SEVCHK(ca_add_exception_event(exceptionCallback,NULL),
|
||||
"ca_add_exception_event");
|
||||
"ca_add_exception_event");
|
||||
/*Dont do anything until iocInit initializes database*/
|
||||
while(!interruptAccept) epicsThreadSleep(.1);
|
||||
/* channel access event loop */
|
||||
while (TRUE){
|
||||
epicsEventMustWait(caWakeupSem);
|
||||
while(TRUE) { /* process all requests in caList*/
|
||||
epicsMutexMustLock(caListSem);
|
||||
if((pca = (caLink *)ellFirst(&caList))){/*Take off list head*/
|
||||
ellDelete(&caList,&pca->node);
|
||||
link_action = pca->link_action;
|
||||
pca->link_action = 0;
|
||||
epicsMutexUnlock(caListSem); /*Give it back immediately*/
|
||||
if(link_action&CA_DELETE) {/*This must be first*/
|
||||
if(pca->chid) ca_clear_channel(pca->chid);
|
||||
free(pca->pgetNative);
|
||||
free(pca->pputNative);
|
||||
free(pca->pgetString);
|
||||
free(pca->pputString);
|
||||
free(pca->pcaAttributes);
|
||||
epicsMutexDestroy(pca->lock);
|
||||
free(pca);
|
||||
continue; /*No other link_action makes sense*/
|
||||
}
|
||||
if(link_action&CA_CONNECT) {
|
||||
status = ca_search_and_connect(
|
||||
pca->plink->value.pv_link.pvname,
|
||||
&(pca->chid),
|
||||
connectionCallback,(void *)pca);
|
||||
if(status!=ECA_NORMAL) {
|
||||
errlogPrintf("dbCaTask ca_search_and_connect %s\n",
|
||||
ca_message(status));
|
||||
continue;
|
||||
}
|
||||
status = ca_replace_access_rights_event(pca->chid,
|
||||
accessRightsCallback);
|
||||
if(status!=ECA_NORMAL)
|
||||
errlogPrintf("dbCaTask replace_access_rights_event %s\n",
|
||||
ca_message(status));
|
||||
continue; /*Other options must wait until connect*/
|
||||
}
|
||||
if(ca_state(pca->chid) != cs_conn) continue;
|
||||
if(link_action&CA_WRITE_NATIVE) {
|
||||
status = ca_array_put(
|
||||
pca->dbrType,pca->nelements,
|
||||
pca->chid,pca->pputNative);
|
||||
if(status==ECA_NORMAL) pca->newOutNative = FALSE;
|
||||
}
|
||||
if(link_action&CA_WRITE_STRING) {
|
||||
status = ca_array_put(
|
||||
DBR_STRING,1,
|
||||
pca->chid,pca->pputString);
|
||||
if(status==ECA_NORMAL) pca->newOutString = FALSE;
|
||||
}
|
||||
if(link_action&CA_MONITOR_NATIVE) {
|
||||
short element_size;
|
||||
|
||||
element_size = dbr_value_size[ca_field_type(pca->chid)];
|
||||
pca->pgetNative = dbCalloc(pca->nelements,element_size);
|
||||
status = ca_add_array_event(
|
||||
ca_field_type(pca->chid)+DBR_TIME_STRING,
|
||||
ca_element_count(pca->chid),
|
||||
pca->chid, eventCallback,pca,0.0,0.0,0.0,
|
||||
0);
|
||||
if(status!=ECA_NORMAL)
|
||||
errlogPrintf("dbCaTask ca_add_array_event %s\n",
|
||||
ca_message(status));
|
||||
}
|
||||
if(link_action&CA_MONITOR_STRING) {
|
||||
pca->pgetString = dbCalloc(MAX_STRING_SIZE,sizeof(char));
|
||||
status = ca_add_array_event(DBR_TIME_STRING,1,
|
||||
pca->chid, eventCallback,pca,0.0,0.0,0.0,
|
||||
0);
|
||||
if(status!=ECA_NORMAL)
|
||||
errlogPrintf("dbCaTask ca_add_array_event %s\n",
|
||||
ca_message(status));
|
||||
}
|
||||
if(link_action&CA_GET_ATTRIBUTES) {
|
||||
status = ca_get_callback(DBR_CTRL_DOUBLE,
|
||||
pca->chid,getAttribEventCallback,pca);
|
||||
if(status!=ECA_NORMAL)
|
||||
errlogPrintf("dbCaTask ca_add_array_event %s\n",
|
||||
ca_message(status));
|
||||
}
|
||||
} else { /* caList was empty */
|
||||
epicsMutexUnlock(caListSem);
|
||||
break; /*caList is empty*/
|
||||
}
|
||||
}
|
||||
SEVCHK(ca_flush_io(),"dbCaTask");
|
||||
epicsEventMustWait(caWakeupSem);
|
||||
while(TRUE) { /* process all requests in caList*/
|
||||
epicsMutexMustLock(caListSem);
|
||||
if((pca = (caLink *)ellFirst(&caList))){/*Take off list head*/
|
||||
ellDelete(&caList,&pca->node);
|
||||
link_action = pca->link_action;
|
||||
pca->link_action = 0;
|
||||
epicsMutexUnlock(caListSem); /*Give it back immediately*/
|
||||
if(link_action&CA_DELETE) {/*This must be first*/
|
||||
if(pca->chid) ca_clear_channel(pca->chid);
|
||||
free(pca->pgetNative);
|
||||
free(pca->pputNative);
|
||||
free(pca->pgetString);
|
||||
free(pca->pputString);
|
||||
free(pca->pcaAttributes);
|
||||
epicsMutexDestroy(pca->lock);
|
||||
free(pca);
|
||||
continue; /*No other link_action makes sense*/
|
||||
}
|
||||
if(link_action&CA_CONNECT) {
|
||||
status = ca_search_and_connect(
|
||||
pca->plink->value.pv_link.pvname,
|
||||
&(pca->chid),
|
||||
connectionCallback,(void *)pca);
|
||||
if(status!=ECA_NORMAL) {
|
||||
errlogPrintf("dbCaTask ca_search_and_connect %s\n",
|
||||
ca_message(status));
|
||||
continue;
|
||||
}
|
||||
status = ca_replace_access_rights_event(pca->chid,
|
||||
accessRightsCallback);
|
||||
if(status!=ECA_NORMAL)
|
||||
errlogPrintf("dbCaTask replace_access_rights_event %s\n",
|
||||
ca_message(status));
|
||||
continue; /*Other options must wait until connect*/
|
||||
}
|
||||
if(ca_state(pca->chid) != cs_conn) continue;
|
||||
if(link_action&CA_WRITE_NATIVE) {
|
||||
status = ca_array_put(
|
||||
pca->dbrType,pca->nelements,
|
||||
pca->chid,pca->pputNative);
|
||||
if(status==ECA_NORMAL) pca->newOutNative = FALSE;
|
||||
}
|
||||
if(link_action&CA_WRITE_STRING) {
|
||||
status = ca_array_put(
|
||||
DBR_STRING,1,
|
||||
pca->chid,pca->pputString);
|
||||
if(status==ECA_NORMAL) pca->newOutString = FALSE;
|
||||
}
|
||||
if(link_action&CA_MONITOR_NATIVE) {
|
||||
short element_size;
|
||||
|
||||
element_size = dbr_value_size[ca_field_type(pca->chid)];
|
||||
pca->pgetNative = dbCalloc(pca->nelements,element_size);
|
||||
status = ca_add_array_event(
|
||||
ca_field_type(pca->chid)+DBR_TIME_STRING,
|
||||
ca_element_count(pca->chid),
|
||||
pca->chid, eventCallback,pca,0.0,0.0,0.0,
|
||||
0);
|
||||
if(status!=ECA_NORMAL)
|
||||
errlogPrintf("dbCaTask ca_add_array_event %s\n",
|
||||
ca_message(status));
|
||||
}
|
||||
if(link_action&CA_MONITOR_STRING) {
|
||||
pca->pgetString = dbCalloc(MAX_STRING_SIZE,sizeof(char));
|
||||
status = ca_add_array_event(DBR_TIME_STRING,1,
|
||||
pca->chid, eventCallback,pca,0.0,0.0,0.0,
|
||||
0);
|
||||
if(status!=ECA_NORMAL)
|
||||
errlogPrintf("dbCaTask ca_add_array_event %s\n",
|
||||
ca_message(status));
|
||||
}
|
||||
if(link_action&CA_GET_ATTRIBUTES) {
|
||||
status = ca_get_callback(DBR_CTRL_DOUBLE,
|
||||
pca->chid,getAttribEventCallback,pca);
|
||||
if(status!=ECA_NORMAL)
|
||||
errlogPrintf("dbCaTask ca_add_array_event %s\n",
|
||||
ca_message(status));
|
||||
}
|
||||
} else { /* caList was empty */
|
||||
epicsMutexUnlock(caListSem);
|
||||
break; /*caList is empty*/
|
||||
}
|
||||
}
|
||||
SEVCHK(ca_flush_io(),"dbCaTask");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user