Fixed numerous bugs
This commit is contained in:
@@ -968,6 +968,9 @@ long dbPutField(DBADDR *paddr,short dbrType,void *pbuffer,long nRequest)
|
||||
|
||||
plink->type = CA_LINK;
|
||||
plink->value.pv_link.precord = precord;
|
||||
if(pfldDes->field_type==DBF_INLINK) {
|
||||
plink->value.pv_link.pvlMask |= pvlOptInpNative;
|
||||
}
|
||||
dbCaAddLink(plink);
|
||||
if(pfldDes->field_type==DBF_FWDLINK) {
|
||||
pperiod = strrchr(plink->value.pv_link.pvname,
|
||||
@@ -1078,7 +1081,7 @@ long dbPut(DBADDR *paddr,short dbrType,void *pbuffer,long nRequest)
|
||||
status = putSpecial(paddr,0);
|
||||
if(status) return(status);
|
||||
}
|
||||
if((no_elements<=1) && (!prset || !(prset->put_array_info))) {
|
||||
if(no_elements<=1) {
|
||||
status = (*dbFastPutConvertRoutine[dbrType][field_type])
|
||||
(pbuffer,paddr->pfield, paddr);
|
||||
} else {
|
||||
|
||||
350
src/db/dbCa.c
350
src/db/dbCa.c
@@ -47,8 +47,30 @@ void scanOnce(void *precord);
|
||||
static ELLLIST caList; /* Work list for dbCaTask */
|
||||
static SEM_ID caListSem; /*Mutual exclusions semaphores for caList*/
|
||||
static SEM_ID caWakeupSem; /*wakeup semaphore for dbCaTask*/
|
||||
void dbCaTask(); /*The Channel Access Task*/
|
||||
void dbCaTask(void); /*The Channel Access Task*/
|
||||
|
||||
/* caLink locking
|
||||
* 1) dbCaTask never locks because ca_xxx calls can block
|
||||
* 2) Everything else locks.
|
||||
* The above means that everything MUST be ok while dbCaTask is executing
|
||||
* Key to making things work is as follows
|
||||
* 1) pcaLink->link_action only read/changed while caListSem held
|
||||
* 2) If any void *p fields in caLink need to be changed free entire caLink
|
||||
* and allocate a brand new one.
|
||||
*/
|
||||
|
||||
static void addAction(caLink *pca, short link_action)
|
||||
{
|
||||
int callAdd = FALSE;
|
||||
|
||||
semTake(caListSem,WAIT_FOREVER);
|
||||
if(pca->link_action==0) callAdd = TRUE;
|
||||
pca->link_action |= link_action;
|
||||
if(callAdd) ellAdd(&caList,&pca->node);
|
||||
semGive(caListSem);
|
||||
if(callAdd) semGive(caWakeupSem);
|
||||
}
|
||||
|
||||
void dbCaLinkInit(void)
|
||||
{
|
||||
ellInit(&caList);
|
||||
@@ -75,28 +97,25 @@ void dbCaAddLink( struct link *plink)
|
||||
printf("dbCaAddLink: semBCreate failed\n");
|
||||
taskSuspend(0);
|
||||
}
|
||||
semTake(caListSem,WAIT_FOREVER);
|
||||
pca->link_action = CA_CONNECT;
|
||||
ellAdd(&caList,&pca->node);
|
||||
semGive(caListSem);
|
||||
semGive(caWakeupSem);
|
||||
addAction(pca,CA_CONNECT);
|
||||
return;
|
||||
}
|
||||
|
||||
void dbCaRemoveLink( struct link *plink)
|
||||
{
|
||||
caLink *pca = (caLink *)plink->value.pv_link.pvt;
|
||||
caLink *pca = (caLink *)plink->value.pv_link.pvt;
|
||||
STATUS semStatus;
|
||||
|
||||
if(!pca) return;
|
||||
semTake(caListSem,WAIT_FOREVER);
|
||||
pca->link_action = CA_DELETE;
|
||||
if(!pca->link_action){/*If not on work list add it*/
|
||||
ellAdd(&caList,&pca->node);
|
||||
}
|
||||
plink->value.pv_link.pvt = 0;
|
||||
pca->plink = 0;
|
||||
semGive(caListSem);
|
||||
semGive(caWakeupSem);
|
||||
if(!pca) return;
|
||||
semStatus = semTake(pca->lock,WAIT_FOREVER);
|
||||
if(semStatus!=OK) {
|
||||
epicsPrintf("dbCaRemoveLink: semStatus!OK\n");
|
||||
return;
|
||||
}
|
||||
pca->plink = 0;
|
||||
plink->value.pv_link.pvt = 0;
|
||||
semGive(pca->lock);
|
||||
addAction(pca,CA_DELETE);
|
||||
}
|
||||
|
||||
|
||||
@@ -107,6 +126,7 @@ long dbCaGetLink(struct link *plink,short dbrType, char *pdest,
|
||||
long status = 0;
|
||||
long (*pconvert)();
|
||||
STATUS semStatus;
|
||||
short link_action = 0;
|
||||
|
||||
if(!pca) {
|
||||
epicsPrintf("dbCaGetLink: record %s pv_link.pvt is NULL\n",
|
||||
@@ -116,9 +136,9 @@ long dbCaGetLink(struct link *plink,short dbrType, char *pdest,
|
||||
semStatus = semTake(pca->lock,WAIT_FOREVER);
|
||||
if(semStatus!=OK) {
|
||||
epicsPrintf("dbCaGetLink: semStatus!OK\n");
|
||||
taskSuspend(0);
|
||||
return(-1);
|
||||
}
|
||||
if(ca_field_type(pca->chid) == TYPENOTCONN){
|
||||
if(ca_state(pca->chid) != cs_conn) {
|
||||
pca->sevr = INVALID_ALARM;
|
||||
goto done;
|
||||
}
|
||||
@@ -126,24 +146,11 @@ long dbCaGetLink(struct link *plink,short dbrType, char *pdest,
|
||||
pca->sevr = INVALID_ALARM;
|
||||
goto done;
|
||||
}
|
||||
if((pca->dbrType == DBR_ENUM)
|
||||
&& (dbDBRnewToDBRold[dbrType] == DBR_STRING)) {
|
||||
if((pca->dbrType == DBR_ENUM) && (dbDBRnewToDBRold[dbrType] == DBR_STRING)){
|
||||
/*Must ask server for DBR_STRING*/
|
||||
if(!pca->pgetString) {
|
||||
pca->pgetString = dbCalloc(MAX_STRING_SIZE,sizeof(char));
|
||||
semGive(pca->lock);
|
||||
semTake(caListSem,WAIT_FOREVER);
|
||||
if(!pca->link_action){/*If not on work list add it*/
|
||||
pca->link_action = CA_MONITOR_STRING;
|
||||
ellAdd(&caList,&pca->node);
|
||||
}
|
||||
semGive(caListSem);
|
||||
semGive(caWakeupSem);
|
||||
semStatus = semTake(pca->lock,WAIT_FOREVER);
|
||||
if(semStatus!=OK) {
|
||||
epicsPrintf("dbCaGetLink: semStatus!OK\n");
|
||||
taskSuspend(0);
|
||||
}
|
||||
plink->value.pv_link.pvlMask |= pvlOptInpString;
|
||||
link_action |= CA_MONITOR_STRING;
|
||||
}
|
||||
if(!pca->gotInString) {
|
||||
pca->sevr = INVALID_ALARM;
|
||||
@@ -154,6 +161,10 @@ long dbCaGetLink(struct link *plink,short dbrType, char *pdest,
|
||||
status = (*(pconvert))(pca->pgetString, pdest, 0);
|
||||
goto done;
|
||||
}
|
||||
if(!pca->pgetNative) {
|
||||
plink->value.pv_link.pvlMask |= pvlOptInpNative;
|
||||
link_action |= CA_MONITOR_NATIVE;
|
||||
}
|
||||
if(!pca->gotInNative){
|
||||
pca->sevr = INVALID_ALARM;
|
||||
goto done;
|
||||
@@ -161,7 +172,6 @@ long dbCaGetLink(struct link *plink,short dbrType, char *pdest,
|
||||
if(!nelements || *nelements == 1){
|
||||
pconvert=
|
||||
dbFastGetConvertRoutine[dbDBRoldToDBFnew[pca->dbrType]][dbrType];
|
||||
/*Ignore error routine*/
|
||||
(*(pconvert))(pca->pgetNative, pdest, 0);
|
||||
}else{
|
||||
unsigned long ntoget = *nelements;
|
||||
@@ -174,12 +184,13 @@ long dbCaGetLink(struct link *plink,short dbrType, char *pdest,
|
||||
dbAddr.pfield = pca->pgetNative;
|
||||
/*Following will only be used for pca->dbrType == DBR_STRING*/
|
||||
dbAddr.field_size = MAX_STRING_SIZE;
|
||||
/*Ignore error routine*/
|
||||
/*Ignore error return*/
|
||||
(*(pconvert))(&dbAddr,pdest,ntoget,ntoget,0);
|
||||
}
|
||||
done:
|
||||
if(psevr) *psevr = pca->sevr;
|
||||
semGive(pca->lock);
|
||||
if(link_action) addAction(pca,link_action);
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -190,7 +201,7 @@ long dbCaPutLink(struct link *plink,short dbrType,
|
||||
long (*pconvert)();
|
||||
long status = 0;
|
||||
STATUS semStatus;
|
||||
short link_action;
|
||||
short link_action = 0;
|
||||
|
||||
if(!pca) {
|
||||
epicsPrintf("dbCaPutLink: record %s pv_link.pvt is NULL\n",
|
||||
@@ -201,22 +212,30 @@ long dbCaPutLink(struct link *plink,short dbrType,
|
||||
semStatus = semTake(pca->lock,WAIT_FOREVER);
|
||||
if(semStatus!=OK) {
|
||||
epicsPrintf("dbCaGetLink: semStatus!OK\n");
|
||||
taskSuspend(0);
|
||||
return(-1);
|
||||
}
|
||||
if(ca_state(pca->chid) != cs_conn) {
|
||||
semGive(pca->lock);
|
||||
return(-1);
|
||||
}
|
||||
if((pca->dbrType == DBR_ENUM)
|
||||
&& (dbDBRnewToDBRold[dbrType] == DBR_STRING)) {
|
||||
if((pca->dbrType == DBR_ENUM) && (dbDBRnewToDBRold[dbrType] == DBR_STRING)){
|
||||
/*Must send DBR_STRING*/
|
||||
if(!pca->pputString)
|
||||
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;
|
||||
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]];
|
||||
@@ -231,20 +250,13 @@ long dbCaPutLink(struct link *plink,short dbrType,
|
||||
dbAddr.field_size = MAX_STRING_SIZE;
|
||||
status = (*(pconvert))(&dbAddr,psource,nelements,pca->nelements,0);
|
||||
}
|
||||
link_action = CA_WRITE_NATIVE;
|
||||
link_action |= CA_WRITE_NATIVE;
|
||||
pca->gotOutNative = TRUE;
|
||||
if(pca->newOutNative) pca->nNoWrite++;
|
||||
pca->newOutNative = TRUE;
|
||||
}
|
||||
if(pca->newWrite) pca->nNoWrite++;
|
||||
pca->newWrite = TRUE;
|
||||
semGive(pca->lock);
|
||||
/* link it into the action list */
|
||||
semTake(caListSem,WAIT_FOREVER);
|
||||
if(!pca->link_action && ca_write_access(pca->chid)){
|
||||
pca->link_action = link_action;
|
||||
ellAdd(&caList,&pca->node);
|
||||
}
|
||||
semGive(caListSem);
|
||||
semGive(caWakeupSem);
|
||||
addAction(pca,link_action);
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -253,16 +265,22 @@ static void eventCallback(struct event_handler_args arg)
|
||||
caLink *pca = (caLink *)arg.usr;
|
||||
struct link *plink;
|
||||
long size;
|
||||
STATUS semStatus;
|
||||
dbCommon *precord = 0;
|
||||
|
||||
if(!pca) {
|
||||
epicsPrintf("eventCallback why was arg.usr NULL\n");
|
||||
return;
|
||||
}
|
||||
semStatus = semTake(pca->lock,WAIT_FOREVER);
|
||||
if(semStatus!=OK) {
|
||||
epicsPrintf("dbCa eventTask: semStatus!OK\n");
|
||||
return;
|
||||
}
|
||||
plink = pca->plink;
|
||||
if(!plink) goto done;
|
||||
precord = (dbCommon *)plink->value.pv_link.precord;
|
||||
if(arg.status != ECA_NORMAL) {
|
||||
dbCommon *precord = 0;
|
||||
|
||||
if(plink) precord = (dbCommon *)plink->value.pv_link.precord;
|
||||
if(precord) {
|
||||
if(arg.status!=ECA_NORDACCESS)
|
||||
epicsPrintf("dbCa: eventCallback record %s error %s\n",
|
||||
@@ -271,16 +289,14 @@ static void eventCallback(struct event_handler_args arg)
|
||||
epicsPrintf("dbCa: eventCallback error %s\n",
|
||||
ca_message(arg.status));
|
||||
}
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
if(!arg.dbr) {
|
||||
epicsPrintf("eventCallback why was arg.dbr NULL\n");
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
semTake(pca->lock,WAIT_FOREVER);
|
||||
size = arg.count * dbr_value_size[arg.type];
|
||||
if((arg.type==DBR_STS_STRING)
|
||||
&& (ca_field_type(pca->chid)==DBR_ENUM)) {
|
||||
if((arg.type==DBR_STS_STRING) && (ca_field_type(pca->chid)==DBR_ENUM)) {
|
||||
memcpy(pca->pgetString,dbr_value_ptr(arg.dbr,arg.type),size);
|
||||
pca->gotInString = TRUE;
|
||||
} else switch (arg.type){
|
||||
@@ -299,17 +315,14 @@ static void eventCallback(struct event_handler_args arg)
|
||||
break;
|
||||
}
|
||||
pca->sevr=(unsigned short)((struct dbr_sts_double *)arg.dbr)->severity;
|
||||
plink = pca->plink;
|
||||
if(plink) {
|
||||
if(precord) {
|
||||
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((ppv_link->pvlMask&pvlOptCP)
|
||||
|| ((ppv_link->pvlMask&pvlOptCPP)&&(precord->scan==0)))
|
||||
scanOnce(precord);
|
||||
}
|
||||
done:
|
||||
semGive(pca->lock);
|
||||
}
|
||||
|
||||
@@ -317,12 +330,19 @@ static void accessRightsCallback(struct access_rights_handler_args arg)
|
||||
{
|
||||
caLink *pca = (caLink *)ca_puser(arg.chid);
|
||||
struct link *plink;
|
||||
STATUS semStatus;
|
||||
|
||||
if(!pca) {
|
||||
epicsPrintf("accessRightsCallback why was arg.usr NULL\n");
|
||||
return;
|
||||
}
|
||||
if(ca_read_access(arg.chid) || ca_write_access(arg.chid)) return;
|
||||
if(ca_state(pca->chid) != cs_conn) return;/*connectionCallback will handle*/
|
||||
semStatus = semTake(pca->lock,WAIT_FOREVER);
|
||||
if(semStatus!=OK) {
|
||||
epicsPrintf("dbCa accessRightsCallback: semStatus!OK\n");
|
||||
return;
|
||||
}
|
||||
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);
|
||||
@@ -331,65 +351,72 @@ static void accessRightsCallback(struct access_rights_handler_args arg)
|
||||
if(precord) {
|
||||
if((ppv_link->pvlMask&pvlOptCP)
|
||||
|| ((ppv_link->pvlMask&pvlOptCPP)&&(precord->scan==0)))
|
||||
scanOnce(precord);
|
||||
scanOnce(precord);
|
||||
}
|
||||
}
|
||||
done:
|
||||
semGive(pca->lock);
|
||||
}
|
||||
|
||||
static void connectionCallback(struct connection_handler_args arg)
|
||||
{
|
||||
caLink *pca;
|
||||
int status;
|
||||
short link_action = 0;
|
||||
struct link *plink;
|
||||
STATUS semStatus;
|
||||
|
||||
pca = ca_puser(arg.chid);
|
||||
if(!pca) return;
|
||||
if(ca_state(arg.chid) != cs_conn){
|
||||
pca->nDisconnect++;
|
||||
semStatus = semTake(pca->lock,WAIT_FOREVER);
|
||||
if(semStatus!=OK) {
|
||||
epicsPrintf("dbCa connectionCallback: semStatus!OK\n");
|
||||
return;
|
||||
}
|
||||
semTake(pca->lock,WAIT_FOREVER);
|
||||
if((pca->nelements != ca_element_count(arg.chid))
|
||||
|| (pca->dbrType != ca_field_type(arg.chid))){
|
||||
DBLINK *plink = pca->plink;
|
||||
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;
|
||||
|
||||
if(plink) plink->value.pv_link.getCvt = 0;
|
||||
free(pca->pgetNative);
|
||||
free(pca->pputNative);
|
||||
pca->pgetNative = NULL;
|
||||
pca->pputNative = NULL;
|
||||
pca->gotInNative = FALSE;
|
||||
pca->gotOutNative = FALSE;
|
||||
pca->gotInString = FALSE;
|
||||
pca->nDisconnect++;
|
||||
if(precord) {
|
||||
if((ppv_link->pvlMask&pvlOptCP)
|
||||
|| ((ppv_link->pvlMask&pvlOptCPP)&&(precord->scan==0)))
|
||||
scanOnce(precord);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
if(pca->pgetNative == NULL){
|
||||
short element_size;
|
||||
|
||||
pca->nelements = ca_element_count(arg.chid);
|
||||
pca->dbrType = ca_field_type(arg.chid);
|
||||
element_size = dbr_value_size[ca_field_type(arg.chid)];
|
||||
pca->pgetNative = dbCalloc(pca->nelements,element_size);
|
||||
pca->pputNative = dbCalloc(pca->nelements,element_size);
|
||||
status = ca_add_array_event(
|
||||
ca_field_type(arg.chid)+DBR_STS_STRING, ca_element_count(arg.chid),
|
||||
arg.chid, eventCallback,pca,0.0,0.0,0.0,0);
|
||||
if(status!=ECA_NORMAL)
|
||||
epicsPrintf("dbCaTask ca_search_and_connect %s\n",
|
||||
ca_message(status));
|
||||
if(pca->pgetString) {
|
||||
status = ca_add_array_event(DBR_STS_STRING,1,
|
||||
arg.chid, eventCallback,pca,0.0,0.0,0.0,0);
|
||||
if(status!=ECA_NORMAL)
|
||||
epicsPrintf("dbCaTask ca_search_and_connect %s\n",
|
||||
ca_message(status));
|
||||
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;
|
||||
semGive(pca->lock);
|
||||
addAction(pca,CA_DELETE);
|
||||
dbCaAddLink(plink);
|
||||
return;
|
||||
}
|
||||
}
|
||||
semGive(pca->lock);
|
||||
semTake(caListSem,WAIT_FOREVER);
|
||||
if(pca->gotOutNative && !pca->link_action) {
|
||||
pca->link_action = CA_WRITE_NATIVE;
|
||||
ellAdd(&caList,&pca->node);
|
||||
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;
|
||||
}
|
||||
semGive(caListSem);
|
||||
if((plink->value.pv_link.pvlMask & pvlOptInpString) && (!pca->pgetString)){
|
||||
link_action |= CA_MONITOR_STRING;
|
||||
}
|
||||
if((plink->value.pv_link.pvlMask & pvlOptOutNative) && (pca->gotOutNative)){
|
||||
link_action |= CA_WRITE_NATIVE;
|
||||
}
|
||||
if((plink->value.pv_link.pvlMask & pvlOptOutString) && (pca->gotOutString)){
|
||||
link_action |= CA_WRITE_STRING;
|
||||
}
|
||||
done:
|
||||
semGive(pca->lock);
|
||||
if(link_action) addAction(pca,link_action);
|
||||
}
|
||||
|
||||
void dbCaTask()
|
||||
@@ -409,24 +436,7 @@ void dbCaTask()
|
||||
link_action = pca->link_action;
|
||||
pca->link_action = 0;
|
||||
semGive(caListSem); /*Give it back immediately*/
|
||||
switch(link_action) {
|
||||
case CA_CONNECT:
|
||||
status = ca_search_and_connect(
|
||||
pca->plink->value.pv_link.pvname,
|
||||
&(pca->chid),
|
||||
connectionCallback,(void *)pca);
|
||||
if(status!=ECA_NORMAL) {
|
||||
epicsPrintf("dbCaTask ca_search_and_connect %s\n",
|
||||
ca_message(status));
|
||||
break;
|
||||
}
|
||||
status = ca_replace_access_rights_event(pca->chid,
|
||||
accessRightsCallback);
|
||||
if(status!=ECA_NORMAL)
|
||||
epicsPrintf("dbCaTask ca_replace_access_rights_event %s\n",
|
||||
ca_message(status));
|
||||
break;
|
||||
case CA_DELETE:
|
||||
if(link_action&CA_DELETE) {/*This must be first*/
|
||||
if(pca->chid) ca_clear_channel(pca->chid);
|
||||
free(pca->pgetNative);
|
||||
free(pca->pputNative);
|
||||
@@ -434,42 +444,66 @@ void dbCaTask()
|
||||
free(pca->pputString);
|
||||
semDelete(pca->lock);
|
||||
free(pca);
|
||||
break;
|
||||
case CA_WRITE_NATIVE:
|
||||
if(ca_state(pca->chid) == cs_conn){
|
||||
status = ca_array_put(
|
||||
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) {
|
||||
epicsPrintf("dbCaTask ca_search_and_connect %s\n",
|
||||
ca_message(status));
|
||||
continue;
|
||||
}
|
||||
status = ca_replace_access_rights_event(pca->chid,
|
||||
accessRightsCallback);
|
||||
if(status!=ECA_NORMAL)
|
||||
epicsPrintf("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->newWrite = FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CA_WRITE_STRING:
|
||||
if(ca_state(pca->chid) == cs_conn){
|
||||
status = ca_array_put(
|
||||
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->newWrite = FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CA_MONITOR_STRING:
|
||||
if(ca_state(pca->chid) == cs_conn){
|
||||
status = ca_add_array_event(DBR_STS_STRING,1,
|
||||
pca->chid, eventCallback,pca,0.0,0.0,0.0,0);
|
||||
if(status!=ECA_NORMAL)
|
||||
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_STS_STRING,
|
||||
ca_element_count(pca->chid),
|
||||
pca->chid, eventCallback,pca,0.0,0.0,0.0,
|
||||
0);
|
||||
if(status!=ECA_NORMAL)
|
||||
epicsPrintf("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_STS_STRING,1,
|
||||
pca->chid, eventCallback,pca,0.0,0.0,0.0,
|
||||
0);
|
||||
if(status!=ECA_NORMAL)
|
||||
epicsPrintf("dbCaTask ca_add_array_event %s\n",
|
||||
ca_message(status));
|
||||
}
|
||||
break;
|
||||
}/*switch*/
|
||||
} else {
|
||||
}
|
||||
} else { /* caList was empty */
|
||||
semGive(caListSem);
|
||||
break; /*caList is empty*/
|
||||
}
|
||||
}
|
||||
SEVCHK(ca_flush_io(),0);
|
||||
SEVCHK(ca_flush_io(),"dbCaTask");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,15 +20,16 @@ of this distribution.
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 08APR96 mrk Made separate module for dbcal
|
||||
* .01 08APR96 mrk Made separate module for dbcar
|
||||
****************************************************************/
|
||||
|
||||
/* for input links */
|
||||
#define CA_CONNECT 1
|
||||
#define CA_DELETE 2
|
||||
#define CA_WRITE_NATIVE 3
|
||||
#define CA_WRITE_STRING 4
|
||||
#define CA_MONITOR_STRING 5
|
||||
/* link_action mask */
|
||||
#define CA_DELETE 0x1
|
||||
#define CA_CONNECT 0x2
|
||||
#define CA_WRITE_NATIVE 0x4
|
||||
#define CA_WRITE_STRING 0x8
|
||||
#define CA_MONITOR_NATIVE 0x10
|
||||
#define CA_MONITOR_STRING 0x20
|
||||
typedef struct caLink
|
||||
{
|
||||
ELLNODE node;
|
||||
@@ -49,5 +50,7 @@ typedef struct caLink
|
||||
char gotOutNative;
|
||||
char gotInString;
|
||||
char gotOutString;
|
||||
char newWrite;
|
||||
char newOutNative;
|
||||
char newOutString;
|
||||
char gotFirstConnection;
|
||||
}caLink;
|
||||
|
||||
@@ -1556,8 +1556,6 @@ static long getFloatString(
|
||||
if(paddr) prset = dbGetRset(paddr);
|
||||
if(prset && (prset->get_precision))
|
||||
status = (*prset->get_precision)(paddr,&precision);
|
||||
else
|
||||
status=S_db_precision;
|
||||
if(nRequest==1 && offset==0) {
|
||||
cvtFloatToString(*psrc,pbuffer,precision);
|
||||
return(status);
|
||||
@@ -1758,8 +1756,6 @@ static long getDoubleString(
|
||||
if(paddr) prset = dbGetRset(paddr);
|
||||
if(prset && (prset->get_precision))
|
||||
status = (*prset->get_precision)(paddr,&precision);
|
||||
else
|
||||
status=S_db_precision;
|
||||
if(nRequest==1 && offset==0) {
|
||||
cvtDoubleToString(*psrc,pbuffer,precision);
|
||||
return(status);
|
||||
@@ -3768,9 +3764,6 @@ static long putFloatString(
|
||||
if(paddr) prset = dbGetRset(paddr);
|
||||
if(prset && (prset->get_precision))
|
||||
status = (*prset->get_precision)(paddr,&precision);
|
||||
else
|
||||
status=S_db_precision;
|
||||
|
||||
if(nRequest==1 && offset==0) {
|
||||
cvtFloatToString(*pbuffer,pdest,precision);
|
||||
return(status);
|
||||
@@ -3972,9 +3965,6 @@ static long putDoubleString(
|
||||
if(paddr) prset = dbGetRset(paddr);
|
||||
if(prset && (prset->get_precision))
|
||||
status = (*prset->get_precision)(paddr,&precision);
|
||||
else
|
||||
status=S_db_precision;
|
||||
|
||||
if(nRequest==1 && offset==0) {
|
||||
cvtDoubleToString(*pbuffer,pdest,precision);
|
||||
return(status);
|
||||
|
||||
@@ -781,8 +781,6 @@ static long cvt_f_st(
|
||||
|
||||
if (prset && prset->get_precision)
|
||||
status = (*prset->get_precision)(paddr, &precision);
|
||||
else
|
||||
status = S_db_precision;
|
||||
cvtFloatToString(*from, to, precision);
|
||||
return(status);
|
||||
}
|
||||
@@ -864,8 +862,6 @@ static long cvt_d_st(
|
||||
|
||||
if (prset && prset->get_precision)
|
||||
status = (*prset->get_precision)(paddr, &precision);
|
||||
else
|
||||
status = S_db_precision;
|
||||
cvtDoubleToString(*from, to, precision);
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ long dbcar(char *precordname,int level)
|
||||
if(!ca_read_access(pca->chid)) noReadAccess++;
|
||||
if(!ca_write_access(pca->chid)) noWriteAccess++;
|
||||
if(level>1) {
|
||||
printf(" connected");
|
||||
printf(" connected ");
|
||||
printf("%s",ca_host_name(pca->chid));
|
||||
if(!ca_read_access(pca->chid))
|
||||
printf(" no_read_access");
|
||||
@@ -95,15 +95,21 @@ long dbcar(char *precordname,int level)
|
||||
precord->name,
|
||||
pdbFldDes->name,
|
||||
plink->value.pv_link.pvname);
|
||||
printf(" nDisconnect %lu nNoWrite %lu\n",
|
||||
pca->nDisconnect,pca->nNoWrite);
|
||||
if(nDisconnect)
|
||||
printf(" nDisconnect %lu",pca->nDisconnect);
|
||||
if(nNoWrite)
|
||||
printf(" nNoWrite %lu",pca->nNoWrite);
|
||||
printf("\n");
|
||||
}
|
||||
} else {
|
||||
if(level>0) {
|
||||
printf("not_connected %s.%s",
|
||||
precord->name,pdbFldDes->name);
|
||||
printf(" nDisconnect %lu nNoWrite %lu\n",
|
||||
pca->nDisconnect,pca->nNoWrite);
|
||||
if(nDisconnect)
|
||||
printf(" nDisconnect %lu",pca->nDisconnect);
|
||||
if(nNoWrite)
|
||||
printf(" nNoWrite %lu",pca->nNoWrite);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,6 +468,9 @@ LOCAL long initDatabase(void)
|
||||
} else {/*It is a CA link*/
|
||||
char *pperiod;
|
||||
|
||||
if(pdbFldDes->field_type==DBF_INLINK) {
|
||||
plink->value.pv_link.pvlMask |= pvlOptInpNative;
|
||||
}
|
||||
dbCaAddLink(plink);
|
||||
if(pdbFldDes->field_type==DBF_FWDLINK) {
|
||||
pperiod = strrchr(plink->value.pv_link.pvname,'.');
|
||||
|
||||
@@ -193,9 +193,13 @@ static long putParmString(char **pparm,char *pstring)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
size = strlen(pstring) + 1;
|
||||
if(size>=MAX_STRING_SIZE) return(S_dbLib_badLink);
|
||||
if(*pparm && (*pparm != pNullString)) free((void *)(*pparm));
|
||||
if(!pstring) return(0);
|
||||
if(!(pstring = strchr(pstring,'@'))) return(0);
|
||||
pstring++;
|
||||
size = strlen(pstring) + 1;
|
||||
if(size==1) return(0);
|
||||
if(size>=MAX_STRING_SIZE) return(S_dbLib_badLink);
|
||||
*pparm = dbCalloc(size, sizeof(char *));
|
||||
strcpy(*pparm,pstring);
|
||||
return(0);
|
||||
@@ -1909,6 +1913,7 @@ char *dbVerify(DBENTRY *pdbentry,char *pstring)
|
||||
if(!pflddes->ftPvt) dbInitDeviceMenu(pdbentry);
|
||||
pdbDeviceMenu = (dbDeviceMenu *)pflddes->ftPvt;
|
||||
if(!pdbDeviceMenu) return(NULL);
|
||||
if(pdbDeviceMenu->nChoice == 0) return(NULL);
|
||||
for (i = 0; i < pdbDeviceMenu->nChoice; i++) {
|
||||
if (!(pchoice = pdbDeviceMenu->papChoice[i]))
|
||||
continue;
|
||||
|
||||
@@ -227,6 +227,7 @@ int dbIsDefaultValue(DBENTRY *pdbentry)
|
||||
if(!plink) return(FALSE);
|
||||
if(plink->type!=CONSTANT) return(FALSE);
|
||||
if(plink->value.constantStr == 0) return(TRUE);
|
||||
if(!pflddes->initial) return(FALSE);
|
||||
if(strcmp(plink->value.constantStr,pflddes->initial)==0)
|
||||
return(TRUE);
|
||||
return(FALSE);
|
||||
|
||||
@@ -408,6 +408,7 @@ int dbIsDefaultValue(DBENTRY *pdbentry)
|
||||
if(!plink) return(FALSE);
|
||||
if(plink->type!=CONSTANT) return(FALSE);
|
||||
if(plink->value.constantStr == 0) return(TRUE);
|
||||
if(!pflddes->initial) return(FALSE);
|
||||
if(strcmp(plink->value.constantStr,pflddes->initial)==0)
|
||||
return(TRUE);
|
||||
return(FALSE);
|
||||
|
||||
@@ -93,6 +93,11 @@ maplinkType pamaplinkType[LINK_NTYPES] = {
|
||||
#define pvlOptCP 0x8 /*CA + process on monitor*/
|
||||
#define pvlOptCPP 0x10 /*CA + process passive record on monitor*/
|
||||
#define pvlOptFWD 0x20 /*Generate ca_put for forward link*/
|
||||
#define pvlOptInpNative 0x40 /*Input native*/
|
||||
#define pvlOptInpString 0x80 /*Input as string*/
|
||||
#define pvlOptOutNative 0x100 /*Output native*/
|
||||
#define pvlOptOutString 0x200 /*Output as string*/
|
||||
|
||||
typedef long (*LINKCVT)();
|
||||
struct pv_link {
|
||||
char *pvname; /*pvname to link to*/
|
||||
|
||||
Reference in New Issue
Block a user