Make reference (array/string) updates use a reference type db_field_log.
* Redefine db_field_log to be a union between a "value" type (as before) and a "reference" type (pointers to values, dtor for plugin array copies). * Add db_delete_field_log function that correctly destructs a db_field_log.
This commit is contained in:
committed by
Michael Davidsaver
parent
4dd42383ef
commit
5ea973151f
@@ -331,11 +331,11 @@ static void getOptions(DBADDR *paddr, char **poriginal, long *options,
|
||||
unsigned short *pushort = (unsigned short *)pbuffer;
|
||||
|
||||
if(pfl!=NULL) {
|
||||
*pushort++ = pfl->stat;
|
||||
*pushort++ = pfl->sevr;
|
||||
*pushort++ = pfl->u.v.stat;
|
||||
*pushort++ = pfl->u.v.sevr;
|
||||
} else {
|
||||
*pushort++ = pcommon->stat;
|
||||
*pushort++ = pcommon->sevr;
|
||||
*pushort++ = pcommon->stat;
|
||||
*pushort++ = pcommon->sevr;
|
||||
}
|
||||
*pushort++ = pcommon->acks;
|
||||
*pushort++ = pcommon->ackt;
|
||||
@@ -365,8 +365,8 @@ static void getOptions(DBADDR *paddr, char **poriginal, long *options,
|
||||
epicsUInt32 *ptime = (epicsUInt32 *)pbuffer;
|
||||
|
||||
if(pfl!=NULL) {
|
||||
*ptime++ = pfl->time.secPastEpoch;
|
||||
*ptime++ = pfl->time.nsec;
|
||||
*ptime++ = pfl->u.v.time.secPastEpoch;
|
||||
*ptime++ = pfl->u.v.time.nsec;
|
||||
} else {
|
||||
*ptime++ = pcommon->time.secPastEpoch;
|
||||
*ptime++ = pcommon->time.nsec;
|
||||
@@ -818,7 +818,7 @@ long epicsShareAPI dbGet(DBADDR *paddr, short dbrType,
|
||||
if (pfl != NULL) {
|
||||
DBADDR localAddr = *paddr; /* Structure copy */
|
||||
|
||||
localAddr.pfield = (char *)&pfl->field;
|
||||
localAddr.pfield = (char *)&pfl->u.v.field;
|
||||
status = dbFastGetConvertRoutine[field_type][dbrType]
|
||||
(localAddr.pfield, pbuffer, &localAddr);
|
||||
} else {
|
||||
@@ -850,7 +850,7 @@ long epicsShareAPI dbGet(DBADDR *paddr, short dbrType,
|
||||
} else if (pfl) {
|
||||
DBADDR localAddr = *paddr; /* Structure copy */
|
||||
|
||||
localAddr.pfield = (char *)&pfl->field;
|
||||
localAddr.pfield = (char *)&pfl->u.v.field;
|
||||
status = convert(&localAddr, pbuffer, n, no_elements, offset);
|
||||
} else {
|
||||
status = convert(paddr, pbuffer, n, no_elements, offset);
|
||||
|
||||
@@ -628,25 +628,31 @@ int epicsShareAPI db_post_extra_labor (dbEventCtx ctx)
|
||||
*/
|
||||
db_field_log* db_post_single_event_first (struct evSubscrip *pevent)
|
||||
{
|
||||
db_field_log *pLog = NULL;
|
||||
|
||||
if (pevent->useValque) {
|
||||
pLog = (db_field_log *) freeListCalloc(dbevFieldLogFreeList);
|
||||
if (pLog) {
|
||||
struct dbChannel *chan = pevent->chan;
|
||||
struct dbCommon *prec = dbChannelRecord(chan);
|
||||
pLog->stat = prec->stat;
|
||||
pLog->sevr = prec->sevr;
|
||||
pLog->time = prec->time;
|
||||
db_field_log *pLog = (db_field_log *) freeListCalloc(dbevFieldLogFreeList);;
|
||||
|
||||
if (pLog) {
|
||||
struct dbChannel *chan = pevent->chan;
|
||||
struct dbCommon *prec = dbChannelRecord(chan);
|
||||
if (pevent->useValque) {
|
||||
pLog->isValue = 1;
|
||||
pLog->u.v.stat = prec->stat;
|
||||
pLog->u.v.sevr = prec->sevr;
|
||||
pLog->u.v.time = prec->time;
|
||||
/*
|
||||
* use memcpy to avoid a bus error on
|
||||
* union copy of char in the db at an odd
|
||||
* address
|
||||
*/
|
||||
memcpy(&pLog->field,
|
||||
memcpy(&pLog->u.v.field,
|
||||
dbChannelField(chan),
|
||||
dbChannelElementSize(chan));
|
||||
} else {
|
||||
pLog->isValue = 0;
|
||||
pLog->u.p.stat = &prec->stat;
|
||||
pLog->u.p.sevr = &prec->sevr;
|
||||
pLog->u.p.time = &prec->time;
|
||||
pLog->u.p.field = dbChannelField(chan);
|
||||
pLog->u.p.freeFld = NULL;
|
||||
}
|
||||
}
|
||||
return pLog;
|
||||
@@ -698,7 +704,7 @@ void db_post_single_event_final (void *pvt, evSubscrip *pevent, db_field_log *pL
|
||||
* replace last event if no space is left
|
||||
*/
|
||||
if (*pevent->pLastLog) {
|
||||
freeListFree(dbevFieldLogFreeList, *pevent->pLastLog);
|
||||
db_delete_field_log(*pevent->pLastLog);
|
||||
*pevent->pLastLog = pLog;
|
||||
}
|
||||
pevent->nreplace++;
|
||||
@@ -840,7 +846,7 @@ static int event_read ( struct event_que *ev_que )
|
||||
if ( pevent == &canceledEvent ) {
|
||||
ev_que->evque[ev_que->getix] = EVENTQEMPTY;
|
||||
if (ev_que->valque[ev_que->getix]) {
|
||||
freeListFree(dbevFieldLogFreeList, ev_que->valque[ev_que->getix]);
|
||||
db_delete_field_log(ev_que->valque[ev_que->getix]);
|
||||
ev_que->valque[ev_que->getix] = NULL;
|
||||
}
|
||||
ev_que->getix = RNGINC ( ev_que->getix );
|
||||
@@ -909,7 +915,7 @@ static int event_read ( struct event_que *ev_que )
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pfl) freeListFree (dbevFieldLogFreeList, pfl);
|
||||
db_delete_field_log(pfl);
|
||||
}
|
||||
|
||||
UNLOCKEVQUE (ev_que)
|
||||
@@ -1079,3 +1085,16 @@ void epicsShareAPI db_event_flow_ctrl_mode_off (dbEventCtx ctx)
|
||||
printf("fc off %lu\n", tickGet());
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* db_delete_field_log()
|
||||
*/
|
||||
void epicsShareAPI db_delete_field_log (db_field_log *pfl)
|
||||
{
|
||||
if (pfl) {
|
||||
/* Free field if reference type field log and dtor is set */
|
||||
if (!pfl->isValue && pfl->u.p.freeFld) pfl->u.p.freeFld(pfl->u.p.field);
|
||||
/* Free the field log chunk */
|
||||
freeListFree(dbevFieldLogFreeList, pfl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,8 @@ epicsShareFunc void epicsShareAPI db_event_enable (dbEventSubscription es);
|
||||
epicsShareFunc void epicsShareAPI db_event_disable (dbEventSubscription es);
|
||||
epicsShareFunc void epicsShareAPI db_post_single_event_final (void *pvt, struct evSubscrip *pevent, struct db_field_log *pLog);
|
||||
|
||||
epicsShareFunc void epicsShareAPI db_delete_field_log (struct db_field_log *pfl);
|
||||
|
||||
#define DB_EVENT_OK 0
|
||||
#define DB_EVENT_ERROR (-1)
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ extern "C" {
|
||||
* will most likely change infrequently.
|
||||
*
|
||||
*/
|
||||
union native_value{
|
||||
union native_value {
|
||||
short dbf_int;
|
||||
short dbf_short;
|
||||
float dbf_float;
|
||||
@@ -46,11 +46,27 @@ union native_value{
|
||||
* structure to log the state of a data base field at the time
|
||||
* an event is triggered.
|
||||
*/
|
||||
struct dbfl_val {
|
||||
unsigned short stat; /* Alarm Status */
|
||||
unsigned short sevr; /* Alarm Severity */
|
||||
epicsTimeStamp time; /* Time stamp */
|
||||
union native_value field; /* Field value */
|
||||
};
|
||||
|
||||
struct dbfl_ref {
|
||||
unsigned short *stat; /* Alarm Status */
|
||||
unsigned short *sevr; /* Alarm Severity */
|
||||
epicsTimeStamp *time; /* Time stamp */
|
||||
void (*freeFld)(void*); /* Callback to free a filter-allocated field */
|
||||
void *field; /* Field value */
|
||||
};
|
||||
|
||||
typedef struct db_field_log {
|
||||
unsigned short stat; /* Alarm Status */
|
||||
unsigned short sevr; /* Alarm Severity */
|
||||
epicsTimeStamp time; /* time stamp */
|
||||
union native_value field; /* field value */
|
||||
char isValue; /* is a value (*not* string/array) */
|
||||
union {
|
||||
struct dbfl_val v;
|
||||
struct dbfl_ref p;
|
||||
} u;
|
||||
} db_field_log;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
Reference in New Issue
Block a user