Merge remote-tracking branch 'lp-zimoch/dbChannelForDBLinks' into 7.0

* lp-zimoch/dbChannelForDBLinks: (43 commits)
  add tests for empty array filter results
  Fix linkFilterTest, move Release Notes to the right place
  do not handle empty arrays (undefined behavior)
  Revert "new error code for empty arrays"
  test code beautification
  make db_init_event_freelists private
  remove unnecessary check
  remove needless pointer access
  new error code for empty arrays
  clean up code structure
  Release notes updated
  set number of planned link filter tests
  removed unnecessary recGblSetSevr call
  re-order link filter tests to alternate between success and failure
  unused variable removed
  Revert "fix crash in PINI: use local db_field_log"
  initialize free lists when starting dbChannel
  db link filter tests added
  bugfix: dbGet should not crash because of empty array requests
  fix crash in PINI: use local db_field_log
  ...

# Conflicts:
#	documentation/RELEASE_NOTES.md
This commit is contained in:
Michael Davidsaver
2020-11-18 10:53:50 -08:00
23 changed files with 484 additions and 130 deletions

View File

@@ -946,13 +946,18 @@ long dbGet(DBADDR *paddr, short dbrType,
if (offset == 0 && (!nRequest || no_elements == 1)) {
if (nRequest)
*nRequest = 1;
else if (no_elements < 1) {
status = S_db_onlyOne;
goto done;
}
if (!pfl || pfl->type == dbfl_type_rec) {
status = dbFastGetConvertRoutine[field_type][dbrType]
(paddr->pfield, pbuf, paddr);
} else {
DBADDR localAddr = *paddr; /* Structure copy */
if (pfl->no_elements < 1) {
if (no_elements < 1) {
status = S_db_badField;
goto done;
}
@@ -996,6 +1001,11 @@ long dbGet(DBADDR *paddr, short dbrType,
} else {
DBADDR localAddr = *paddr; /* Structure copy */
if (pfl->no_elements < 1) {
status = S_db_badField;
goto done;
}
localAddr.field_type = pfl->field_type;
localAddr.field_size = pfl->field_size;
localAddr.no_elements = pfl->no_elements;
@@ -1037,7 +1047,7 @@ static long dbPutFieldLink(DBADDR *paddr,
short dbrType, const void *pbuffer, long nRequest)
{
dbLinkInfo link_info;
DBADDR *pdbaddr = NULL;
dbChannel *chan = NULL;
dbCommon *precord = paddr->precord;
dbCommon *lockrecs[2];
dbLocker locker;
@@ -1075,16 +1085,11 @@ static long dbPutFieldLink(DBADDR *paddr,
if (link_info.ltype == PV_LINK &&
(link_info.modifiers & (pvlOptCA | pvlOptCP | pvlOptCPP)) == 0) {
DBADDR tempaddr;
if (dbNameToAddr(link_info.target, &tempaddr)==0) {
/* This will become a DB link. */
pdbaddr = malloc(sizeof(*pdbaddr));
if (!pdbaddr) {
status = S_db_noMemory;
goto cleanup;
}
*pdbaddr = tempaddr; /* struct copy */
chan = dbChannelCreate(link_info.target);
if (chan && dbChannelOpen(chan) != 0) {
errlogPrintf("ERROR: dbPutFieldLink %s.%s=%s: dbChannelOpen() failed\n",
precord->name, pfldDes->name, link_info.target);
goto cleanup;
}
}
@@ -1093,7 +1098,7 @@ static long dbPutFieldLink(DBADDR *paddr,
memset(&locker, 0, sizeof(locker));
lockrecs[0] = precord;
lockrecs[1] = pdbaddr ? pdbaddr->precord : NULL;
lockrecs[1] = chan ? dbChannelRecord(chan) : NULL;
dbLockerPrepare(&locker, lockrecs, 2);
dbScanLockMany(&locker);
@@ -1181,7 +1186,8 @@ static long dbPutFieldLink(DBADDR *paddr,
case PV_LINK:
case CONSTANT:
case JSON_LINK:
dbAddLink(&locker, plink, pfldDes->field_type, pdbaddr);
dbAddLink(&locker, plink, pfldDes->field_type, chan);
chan = NULL; /* don't clean it up */
break;
case DB_LINK:
@@ -1211,6 +1217,8 @@ unlock:
dbScanUnlockMany(&locker);
dbLockerFinalize(&locker);
cleanup:
if (chan)
dbChannelDelete(chan);
free(link_info.target);
return status;
}
@@ -1330,25 +1338,21 @@ long dbPut(DBADDR *paddr, short dbrType,
status = prset->get_array_info(paddr, &dummy, &offset);
/* paddr->pfield may be modified */
if (status) goto done;
} else
offset = 0;
if (no_elements <= 1) {
status = dbFastPutConvertRoutine[dbrType][field_type](pbuffer,
paddr->pfield, paddr);
nRequest = 1;
} else {
if (no_elements < nRequest)
nRequest = no_elements;
status = dbPutConvertRoutine[dbrType][field_type](paddr, pbuffer,
nRequest, no_elements, offset);
}
/* update array info */
if (!status &&
paddr->pfldDes->special == SPC_DBADDR &&
prset && prset->put_array_info) {
status = prset->put_array_info(paddr, nRequest);
/* update array info */
if (!status && prset->put_array_info)
status = prset->put_array_info(paddr, nRequest);
} else {
if (nRequest < 1) {
recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM);
} else {
status = dbFastPutConvertRoutine[dbrType][field_type](pbuffer,
paddr->pfield, paddr);
nRequest = 1;
}
}
/* Always do special processing if needed */

View File

@@ -411,9 +411,15 @@ long dbCaGetLink(struct link *plink, short dbrType, void *pdest,
goto done;
}
newType = dbDBRoldToDBFnew[pca->dbrType];
if (!nelements || *nelements == 1) {
if (!nelements) {
long (*fConvert)(const void *from, void *to, struct dbAddr *paddr);
if (pca->usedelements < 1) {
pca->sevr = INVALID_ALARM;
pca->stat = LINK_ALARM;
status = -1;
goto done;
}
fConvert = dbFastGetConvertRoutine[newType][dbrType];
assert(pca->pgetNative);
status = fConvert(pca->pgetNative, pdest, 0);

View File

@@ -18,6 +18,8 @@
#include <stddef.h>
#include <string.h>
#define EPICS_PRIVATE_API
#include "cantProceed.h"
#include "epicsAssert.h"
#include "epicsString.h"
@@ -68,6 +70,7 @@ void dbChannelInit (void)
freeListInitPvt(&dbChannelFreeList, sizeof(dbChannel), 128);
freeListInitPvt(&chFilterFreeList, sizeof(chFilter), 64);
freeListInitPvt(&dbchStringFreeList, sizeof(epicsOldString), 128);
db_init_event_freelists();
}
static void chf_value(parseContext *parser, parse_result *presult)

View File

@@ -61,6 +61,7 @@
#include "dbConvertFast.h"
#include "dbConvert.h"
#include "db_field_log.h"
#include "db_access_routines.h"
#include "dbFldTypes.h"
#include "dbLink.h"
#include "dbLockPvt.h"
@@ -74,7 +75,7 @@
#include "recSup.h"
#include "special.h"
#include "dbDbLink.h"
#include "dbChannel.h"
/***************************** Database Links *****************************/
@@ -83,45 +84,51 @@ static lset dbDb_lset;
static long processTarget(dbCommon *psrc, dbCommon *pdst);
#define linkChannel(plink) ((dbChannel *) (plink)->value.pv_link.pvt)
long dbDbInitLink(struct link *plink, short dbfType)
{
DBADDR dbaddr;
long status;
DBADDR *pdbAddr;
dbChannel *chan;
dbCommon *precord;
status = dbNameToAddr(plink->value.pv_link.pvname, &dbaddr);
chan = dbChannelCreate(plink->value.pv_link.pvname);
if (!chan)
return S_db_notFound;
status = dbChannelOpen(chan);
if (status)
return status;
precord = dbChannelRecord(chan);
plink->lset = &dbDb_lset;
plink->type = DB_LINK;
pdbAddr = dbCalloc(1, sizeof(struct dbAddr));
*pdbAddr = dbaddr; /* structure copy */
plink->value.pv_link.pvt = pdbAddr;
ellAdd(&dbaddr.precord->bklnk, &plink->value.pv_link.backlinknode);
plink->value.pv_link.pvt = chan;
ellAdd(&precord->bklnk, &plink->value.pv_link.backlinknode);
/* merging into the same lockset is deferred to the caller.
* cf. initPVLinks()
*/
dbLockSetMerge(NULL, plink->precord, dbaddr.precord);
assert(plink->precord->lset->plockSet == dbaddr.precord->lset->plockSet);
dbLockSetMerge(NULL, plink->precord, precord);
assert(plink->precord->lset->plockSet == precord->lset->plockSet);
return 0;
}
void dbDbAddLink(struct dbLocker *locker, struct link *plink, short dbfType,
DBADDR *ptarget)
dbChannel *chan)
{
plink->lset = &dbDb_lset;
plink->type = DB_LINK;
plink->value.pv_link.pvt = ptarget;
ellAdd(&ptarget->precord->bklnk, &plink->value.pv_link.backlinknode);
plink->value.pv_link.pvt = chan;
ellAdd(&dbChannelRecord(chan)->bklnk, &plink->value.pv_link.backlinknode);
/* target record is already locked in dbPutFieldLink() */
dbLockSetMerge(locker, plink->precord, ptarget->precord);
dbLockSetMerge(locker, plink->precord, dbChannelRecord(chan));
}
static void dbDbRemoveLink(struct dbLocker *locker, struct link *plink)
{
DBADDR *pdbAddr = (DBADDR *) plink->value.pv_link.pvt;
dbChannel *chan = linkChannel(plink);
dbCommon *precord = dbChannelRecord(chan);
plink->type = PV_LINK;
@@ -131,10 +138,10 @@ static void dbDbRemoveLink(struct dbLocker *locker, struct link *plink)
plink->value.pv_link.getCvt = 0;
plink->value.pv_link.pvlMask = 0;
plink->value.pv_link.lastGetdbrType = 0;
ellDelete(&pdbAddr->precord->bklnk, &plink->value.pv_link.backlinknode);
dbLockSetSplit(locker, plink->precord, pdbAddr->precord);
ellDelete(&precord->bklnk, &plink->value.pv_link.backlinknode);
dbLockSetSplit(locker, plink->precord, precord);
}
free(pdbAddr);
dbChannelDelete(chan);
}
static int dbDbIsConnected(const struct link *plink)
@@ -144,16 +151,14 @@ static int dbDbIsConnected(const struct link *plink)
static int dbDbGetDBFtype(const struct link *plink)
{
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
return paddr->field_type;
dbChannel *chan = linkChannel(plink);
return dbChannelFinalFieldType(chan);
}
static long dbDbGetElements(const struct link *plink, long *nelements)
{
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
*nelements = paddr->no_elements;
dbChannel *chan = linkChannel(plink);
*nelements = dbChannelFinalElements(chan);
return 0;
}
@@ -161,47 +166,75 @@ static long dbDbGetValue(struct link *plink, short dbrType, void *pbuffer,
long *pnRequest)
{
struct pv_link *ppv_link = &plink->value.pv_link;
DBADDR *paddr = ppv_link->pvt;
dbChannel *chan = linkChannel(plink);
DBADDR *paddr = &chan->addr;
dbCommon *precord = plink->precord;
db_field_log *pfl = NULL;
long status;
/* scan passive records if link is process passive */
if (ppv_link->pvlMask & pvlOptPP) {
status = dbScanPassive(precord, paddr->precord);
status = dbScanPassive(precord, dbChannelRecord(chan));
if (status)
return status;
}
if (ppv_link->getCvt && ppv_link->lastGetdbrType == dbrType) {
status = ppv_link->getCvt(paddr->pfield, pbuffer, paddr);
} else {
unsigned short dbfType = paddr->field_type;
if (ppv_link->getCvt && ppv_link->lastGetdbrType == dbrType)
{
/* shortcut: scalar with known conversion, no filter */
status = ppv_link->getCvt(dbChannelField(chan), pbuffer, paddr);
}
else if (dbChannelFinalElements(chan) == 1 && (!pnRequest || *pnRequest == 1)
&& dbChannelSpecial(chan) != SPC_DBADDR
&& dbChannelSpecial(chan) != SPC_ATTRIBUTE
&& ellCount(&chan->filters) == 0)
{
/* simple scalar: set up shortcut */
unsigned short dbfType = dbChannelFinalFieldType(chan);
if (dbrType < 0 || dbrType > DBR_ENUM || dbfType > DBF_DEVICE)
return S_db_badDbrtype;
if (paddr->no_elements == 1 && (!pnRequest || *pnRequest == 1)
&& paddr->special != SPC_DBADDR
&& paddr->special != SPC_ATTRIBUTE) {
ppv_link->getCvt = dbFastGetConvertRoutine[dbfType][dbrType];
status = ppv_link->getCvt(paddr->pfield, pbuffer, paddr);
} else {
ppv_link->getCvt = NULL;
status = dbGet(paddr, dbrType, pbuffer, NULL, pnRequest, NULL);
}
ppv_link->getCvt = dbFastGetConvertRoutine[dbfType][dbrType];
ppv_link->lastGetdbrType = dbrType;
status = ppv_link->getCvt(dbChannelField(chan), pbuffer, paddr);
}
else
{
/* filter, array, or special */
ppv_link->getCvt = NULL;
if (ellCount(&chan->filters)) {
/* If filters are involved in a read, create field log and run filters */
pfl = db_create_read_log(chan);
if (!pfl)
return S_db_noMemory;
pfl = dbChannelRunPreChain(chan, pfl);
pfl = dbChannelRunPostChain(chan, pfl);
}
status = dbChannelGet(chan, dbrType, pbuffer, NULL, pnRequest, pfl);
if (pfl)
db_delete_field_log(pfl);
if (status)
return status;
}
if (!status && precord != paddr->precord)
if (!status && precord != dbChannelRecord(chan))
recGblInheritSevr(plink->value.pv_link.pvlMask & pvlOptMsMode,
plink->precord, paddr->precord->stat, paddr->precord->sevr);
plink->precord,
dbChannelRecord(chan)->stat, dbChannelRecord(chan)->sevr);
return status;
}
static long dbDbGetControlLimits(const struct link *plink, double *low,
double *high)
{
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
dbChannel *chan = linkChannel(plink);
DBADDR *paddr = &chan->addr;
struct buffer {
DBRctrlDouble
double value;
@@ -222,7 +255,8 @@ static long dbDbGetControlLimits(const struct link *plink, double *low,
static long dbDbGetGraphicLimits(const struct link *plink, double *low,
double *high)
{
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
dbChannel *chan = linkChannel(plink);
DBADDR *paddr = &chan->addr;
struct buffer {
DBRgrDouble
double value;
@@ -243,7 +277,8 @@ static long dbDbGetGraphicLimits(const struct link *plink, double *low,
static long dbDbGetAlarmLimits(const struct link *plink, double *lolo,
double *low, double *high, double *hihi)
{
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
dbChannel *chan = linkChannel(plink);
DBADDR *paddr = &chan->addr;
struct buffer {
DBRalDouble
double value;
@@ -265,7 +300,8 @@ static long dbDbGetAlarmLimits(const struct link *plink, double *lolo,
static long dbDbGetPrecision(const struct link *plink, short *precision)
{
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
dbChannel *chan = linkChannel(plink);
DBADDR *paddr = &chan->addr;
struct buffer {
DBRprecision
double value;
@@ -284,7 +320,8 @@ static long dbDbGetPrecision(const struct link *plink, short *precision)
static long dbDbGetUnits(const struct link *plink, char *units, int unitsSize)
{
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
dbChannel *chan = linkChannel(plink);
DBADDR *paddr = &chan->addr;
struct buffer {
DBRunits
double value;
@@ -304,20 +341,20 @@ static long dbDbGetUnits(const struct link *plink, char *units, int unitsSize)
static long dbDbGetAlarm(const struct link *plink, epicsEnum16 *status,
epicsEnum16 *severity)
{
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
dbChannel *chan = linkChannel(plink);
dbCommon *precord = dbChannelRecord(chan);
if (status)
*status = paddr->precord->stat;
*status = precord->stat;
if (severity)
*severity = paddr->precord->sevr;
*severity = precord->sevr;
return 0;
}
static long dbDbGetTimeStamp(const struct link *plink, epicsTimeStamp *pstamp)
{
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
*pstamp = paddr->precord->time;
dbChannel *chan = linkChannel(plink);
dbCommon *precord = dbChannelRecord(chan);
*pstamp = precord->time;
return 0;
}
@@ -325,9 +362,10 @@ static long dbDbPutValue(struct link *plink, short dbrType,
const void *pbuffer, long nRequest)
{
struct pv_link *ppv_link = &plink->value.pv_link;
dbChannel *chan = linkChannel(plink);
struct dbCommon *psrce = plink->precord;
DBADDR *paddr = (DBADDR *) ppv_link->pvt;
dbCommon *pdest = paddr->precord;
DBADDR *paddr = &chan->addr;
dbCommon *pdest = dbChannelRecord(chan);
long status = dbPut(paddr, dbrType, pbuffer, nRequest);
recGblInheritSevr(ppv_link->pvlMask & pvlOptMsMode, pdest, psrce->nsta,
@@ -335,7 +373,7 @@ static long dbDbPutValue(struct link *plink, short dbrType,
if (status)
return status;
if (paddr->pfield == (void *) &pdest->proc ||
if (dbChannelField(chan) == (void *) &pdest->proc ||
(ppv_link->pvlMask & pvlOptPP && pdest->scan == 0)) {
status = processTarget(psrce, pdest);
}
@@ -346,9 +384,8 @@ static long dbDbPutValue(struct link *plink, short dbrType,
static void dbDbScanFwdLink(struct link *plink)
{
dbCommon *precord = plink->precord;
dbAddr *paddr = (dbAddr *) plink->value.pv_link.pvt;
dbScanPassive(precord, paddr->precord);
dbChannel *chan = linkChannel(plink);
dbScanPassive(precord, dbChannelRecord(chan));
}
static long doLocked(struct link *plink, dbLinkUserCallback rtn, void *priv)

View File

@@ -27,7 +27,7 @@ struct dbLocker;
epicsShareFunc long dbDbInitLink(struct link *plink, short dbfType);
epicsShareFunc void dbDbAddLink(struct dbLocker *locker, struct link *plink,
short dbfType, DBADDR *ptarget);
short dbfType, dbChannel *ptarget);
#ifdef __cplusplus
}

View File

@@ -252,18 +252,15 @@ int dbel ( const char *pname, unsigned level )
}
/*
* DB_INIT_EVENTS()
* DB_INIT_EVENT_FREELISTS()
*
*
* Initialize the event facility for this task. Must be called at least once
* by each task which uses the db event facility
* Initialize the free lists used by the event facility.
* Safe to be called multiple times.
*
* returns: ptr to event user block or NULL if memory can't be allocated
*/
dbEventCtx db_init_events (void)
void db_init_event_freelists (void)
{
struct event_user * evUser;
if (!dbevEventUserFreeList) {
freeListInitPvt(&dbevEventUserFreeList,
sizeof(struct event_user),8);
@@ -280,6 +277,22 @@ dbEventCtx db_init_events (void)
freeListInitPvt(&dbevFieldLogFreeList,
sizeof(struct db_field_log),2048);
}
}
/*
* DB_INIT_EVENTS()
*
*
* Initialize the event facility for this task. Must be called at least once
* by each task which uses the db event facility
*
* returns: ptr to event user block or NULL if memory can't be allocated
*/
dbEventCtx db_init_events (void)
{
struct event_user * evUser;
db_init_event_freelists();
evUser = (struct event_user *)
freeListCalloc(dbevEventUserFreeList);

View File

@@ -66,6 +66,7 @@ epicsShareFunc void db_event_change_priority ( dbEventCtx ctx, unsigned epicsPri
#ifdef EPICS_PRIVATE_API
epicsShareFunc void db_cleanup_events(void);
epicsShareFunc void db_init_event_freelists (void);
#endif
typedef void EVENTFUNC (void *user_arg, struct dbChannel *chan,

View File

@@ -144,7 +144,7 @@ void dbInitLink(struct link *plink, short dbfType)
}
void dbAddLink(struct dbLocker *locker, struct link *plink, short dbfType,
DBADDR *ptarget)
dbChannel *ptarget)
{
struct dbCommon *precord = plink->precord;

View File

@@ -21,6 +21,7 @@
#include "epicsTypes.h"
#include "epicsTime.h"
#include "dbAddr.h"
#include "dbChannel.h"
#ifdef __cplusplus
extern "C" {
@@ -369,7 +370,7 @@ epicsShareFunc const char * dbLinkFieldName(const struct link *plink);
epicsShareFunc void dbInitLink(struct link *plink, short dbfType);
epicsShareFunc void dbAddLink(struct dbLocker *locker, struct link *plink,
short dbfType, DBADDR *ptarget);
short dbfType, dbChannel *ptarget);
epicsShareFunc void dbLinkOpen(struct link *plink);
epicsShareFunc void dbRemoveLink(struct dbLocker *locker, struct link *plink);

View File

@@ -743,14 +743,14 @@ void dbLockSetSplit(dbLocker *locker, dbCommon *pfirst, dbCommon *psecond)
for(i=0; i<rtype->no_links; i++) {
dbFldDes *pdesc = rtype->papFldDes[rtype->link_ind[i]];
DBLINK *plink = (DBLINK*)((char*)prec + pdesc->offset);
DBADDR *ptarget;
dbChannel *chan;
lockRecord *lr;
if(plink->type!=DB_LINK)
continue;
ptarget = plink->value.pv_link.pvt;
lr = ptarget->precord->lset;
chan = plink->value.pv_link.pvt;
lr = dbChannelRecord(chan)->lset;
assert(lr);
if(lr->precord==pfirst) {

View File

@@ -41,6 +41,7 @@
#include "recGbl.h"
#include "recSup.h"
#include "special.h"
#include "dbConvertJSON.h"
#define MAXLINE 80
#define MAXMESS 128
@@ -364,8 +365,9 @@ long dbpf(const char *pname,const char *pvalue)
{
DBADDR addr;
long status;
short dbrType;
size_t n = 1;
short dbrType = DBR_STRING;
long n = 1;
char *array = NULL;
if (!pname || !*pname || !pvalue) {
printf("Usage: dbpf \"pv name\", \"value\"\n");
@@ -380,16 +382,25 @@ long dbpf(const char *pname,const char *pvalue)
return -1;
}
if (addr.no_elements > 1 &&
(addr.dbr_field_type == DBR_CHAR || addr.dbr_field_type == DBR_UCHAR)) {
if (addr.no_elements > 1) {
dbrType = addr.dbr_field_type;
n = strlen(pvalue) + 1;
if (addr.dbr_field_type == DBR_CHAR || addr.dbr_field_type == DBR_UCHAR) {
n = (long)strlen(pvalue) + 1;
} else {
n = addr.no_elements;
array = calloc(n, dbValueSize(dbrType));
if (!array) {
printf("Out of memory\n");
return -1;
}
status = dbPutConvertJSON(pvalue, dbrType, array, &n);
if (status)
return status;
pvalue = array;
}
}
else {
dbrType = DBR_STRING;
}
status = dbPutField(&addr, dbrType, pvalue, (long) n);
status = dbPutField(&addr, dbrType, pvalue, n);
free(array);
dbgf(pname);
return status;
}
@@ -943,13 +954,13 @@ static void printBuffer(
}
/* Now print values */
if (no_elements == 0)
return;
if (no_elements == 1)
sprintf(pmsg, "DBF_%s: ", dbr[dbr_type]);
else
else {
sprintf(pmsg, "DBF_%s[%ld]: ", dbr[dbr_type], no_elements);
if (no_elements == 0)
strcat(pmsg, "(empty)");
}
dbpr_msgOut(pMsgBuff, tab_size);
if (status != 0) {

View File

@@ -61,9 +61,10 @@ static long init_record(dbCommon *pcommon)
}
status = dbLoadLinkArray(plink, prec->ftvl, prec->bptr, &nRequest);
if (!status && nRequest > 0) {
if (!status) {
prec->nord = nRequest;
prec->udf = FALSE;
return status;
}
}
return 0;
@@ -75,7 +76,7 @@ static long readLocked(struct link *pinp, void *dummy)
long nRequest = prec->nelm;
long status = dbGetLink(pinp, prec->ftvl, prec->bptr, 0, &nRequest);
if (!status && nRequest > 0) {
if (!status) {
prec->nord = nRequest;
prec->udf = FALSE;
@@ -90,8 +91,12 @@ static long read_aai(aaiRecord *prec)
{
epicsUInt32 nord = prec->nord;
struct link *pinp = prec->simm == menuYesNoYES ? &prec->siol : &prec->inp;
long status = dbLinkDoLocked(pinp, readLocked, NULL);
long status;
if (dbLinkIsConstant(pinp))
return 0;
status = dbLinkDoLocked(pinp, readLocked, NULL);
if (status == S_db_noLSET)
status = readLocked(pinp, NULL);

View File

@@ -86,9 +86,10 @@ static long read_ai(aiRecord *prec)
prec->udf = FALSE;
prec->dpvt = &devAiSoft; /* Any non-zero value */
return 2;
}
else
prec->dpvt = NULL;
return 2;
return status;
}

View File

@@ -66,7 +66,7 @@ static long init_record(dbCommon *pcommon)
status = dbLoadLinkArray(&prec->inp, prec->ftvl, prec->bptr, &nRequest);
if (!status && nRequest > 0)
if (!status)
subset(prec, nRequest);
return status;
@@ -116,7 +116,7 @@ static long read_sa(subArrayRecord *prec)
status = readLocked(&prec->inp, &rt);
}
if (!status && rt.nRequest > 0) {
if (!status) {
subset(prec, rt.nRequest);
if (nord != prec->nord)

View File

@@ -42,7 +42,7 @@ static long init_record(dbCommon *pcommon)
long nelm = prec->nelm;
long status = dbLoadLinkArray(&prec->inp, prec->ftvl, prec->bptr, &nelm);
if (!status && nelm > 0) {
if (!status) {
prec->nord = nelm;
prec->udf = FALSE;
}
@@ -78,11 +78,14 @@ static long read_wf(waveformRecord *prec)
rt.ptime = (dbLinkIsConstant(&prec->tsel) &&
prec->tse == epicsTimeEventDeviceTime) ? &prec->time : NULL;
if (dbLinkIsConstant(&prec->inp))
return 0;
status = dbLinkDoLocked(&prec->inp, readLocked, &rt);
if (status == S_db_noLSET)
status = readLocked(&prec->inp, &rt);
if (!status && rt.nRequest > 0) {
if (!status) {
prec->nord = rt.nRequest;
prec->udf = FALSE;
if (nord != prec->nord)

View File

@@ -278,10 +278,9 @@ static long fetch_values(aSubRecord *prec)
long nRequest = (&prec->noa)[i];
status = dbGetLink(&(&prec->inpa)[i], (&prec->fta)[i], (&prec->a)[i], 0,
&nRequest);
if (nRequest > 0)
(&prec->nea)[i] = nRequest;
if (status)
return status;
(&prec->nea)[i] = nRequest;
}
return 0;
}