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:
Andrew Johnson
2014-11-18 11:10:01 -06:00
parent 9e63a51707
commit 60a5c476b3
3 changed files with 31 additions and 28 deletions

View File

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

View File

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

View File

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