Fix single-element array problem
An array field with a maximum size of 1 element would not be treated as an array, so the record's rset::get_array_info() routine wasn't being called. Fixed in dbAccess for both dbGet() and dbPut() operations, and in dbEvent for monitors. Fixes lp:1389298
This commit is contained in:
@@ -843,17 +843,15 @@ long dbGet(DBADDR *paddr, short dbrType,
|
||||
return S_db_badDbrtype;
|
||||
}
|
||||
|
||||
/* For array field, the rset function
|
||||
/* For SPC_DBADDR fields, the rset function
|
||||
* get_array_info() is allowed to modify
|
||||
* paddr->pfield. So we store the original
|
||||
* value and restore it later.
|
||||
*/
|
||||
pfieldsave = paddr->pfield;
|
||||
|
||||
/* check for array */
|
||||
if ((!pfl || pfl->type == dbfl_type_rec) &&
|
||||
paddr->pfldDes->special == SPC_DBADDR &&
|
||||
no_elements > 1 &&
|
||||
/* Update field info */
|
||||
if (paddr->pfldDes->special == SPC_DBADDR &&
|
||||
(prset = dbGetRset(paddr)) &&
|
||||
prset->get_array_info) {
|
||||
status = prset->get_array_info(paddr, &no_elements, &offset);
|
||||
@@ -1179,7 +1177,9 @@ long dbPut(DBADDR *paddr, short dbrType,
|
||||
long no_elements = paddr->no_elements;
|
||||
long special = paddr->special;
|
||||
void *pfieldsave = paddr->pfield;
|
||||
struct rset *prset = dbGetRset(paddr);
|
||||
long status = 0;
|
||||
long offset;
|
||||
dbFldDes *pfldDes;
|
||||
int isValueField;
|
||||
|
||||
@@ -1203,31 +1203,32 @@ long dbPut(DBADDR *paddr, short dbrType,
|
||||
if (status) return status;
|
||||
}
|
||||
|
||||
if (paddr->pfldDes->special == SPC_DBADDR &&
|
||||
prset && prset->get_array_info) {
|
||||
long dummy;
|
||||
|
||||
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 {
|
||||
struct rset *prset = dbGetRset(paddr);
|
||||
long offset = 0;
|
||||
if (no_elements < nRequest)
|
||||
nRequest = no_elements;
|
||||
status = dbPutConvertRoutine[dbrType][field_type](paddr, pbuffer,
|
||||
nRequest, no_elements, offset);
|
||||
}
|
||||
if (status) goto done;
|
||||
|
||||
if (paddr->pfldDes->special == SPC_DBADDR &&
|
||||
prset && prset->get_array_info) {
|
||||
long dummy;
|
||||
|
||||
status = prset->get_array_info(paddr, &dummy, &offset);
|
||||
/* paddr->pfield may be modified */
|
||||
}
|
||||
if (no_elements < nRequest) nRequest = no_elements;
|
||||
if (!status)
|
||||
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 (paddr->pfldDes->special == SPC_DBADDR &&
|
||||
prset && prset->put_array_info) {
|
||||
status = prset->put_array_info(paddr, nRequest);
|
||||
}
|
||||
if (status) goto done;
|
||||
|
||||
|
||||
@@ -761,7 +761,7 @@ void dbChannelMakeArrayCopy(void *pvt, db_field_log *pfl, dbChannel *chan)
|
||||
void *p;
|
||||
struct dbCommon *prec = dbChannelRecord(chan);
|
||||
|
||||
if (!pfl->type == dbfl_type_rec) return;
|
||||
if (pfl->type != dbfl_type_rec) return;
|
||||
|
||||
pfl->type = dbfl_type_ref;
|
||||
pfl->stat = prec->stat;
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "dbFldTypes.h"
|
||||
#include "dbLock.h"
|
||||
#include "link.h"
|
||||
#include "special.h"
|
||||
|
||||
#define EVENTSPERQUE 32
|
||||
#define EVENTENTRIES 4 /* the number of que entries for each event */
|
||||
@@ -452,7 +453,8 @@ dbEventSubscription db_add_event (
|
||||
* communication (for other types they get whatever happens to be
|
||||
* there upon wakeup)
|
||||
*/
|
||||
if( dbChannelElements(chan) == 1 &&
|
||||
if (dbChannelElements(chan) == 1 &&
|
||||
dbChannelSpecial(chan) != SPC_DBADDR &&
|
||||
dbChannelFieldSize(chan) <= sizeof(union native_value)) {
|
||||
pevent->useValque = TRUE;
|
||||
}
|
||||
@@ -824,7 +826,7 @@ unsigned int caEventMask
|
||||
|
||||
/*
|
||||
* Only send event msg if they are waiting on the field which
|
||||
* changed or pval==NULL and waiting on alarms and alarms changed
|
||||
* changed or pval==NULL, and are waiting on matching event
|
||||
*/
|
||||
if ( (dbChannelField(pevent->chan) == (void *)pField || pField==NULL) &&
|
||||
(caEventMask & pevent->select)) {
|
||||
|
||||
Reference in New Issue
Block a user