From 5ea973151f963c5495518f25c98def2dc0ef7108 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Fri, 27 Apr 2012 13:21:54 -0400 Subject: [PATCH] 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. --- src/ioc/db/dbAccess.c | 16 ++++++------- src/ioc/db/dbEvent.c | 47 +++++++++++++++++++++++++++------------ src/ioc/db/dbEvent.h | 2 ++ src/ioc/db/db_field_log.h | 26 +++++++++++++++++----- 4 files changed, 64 insertions(+), 27 deletions(-) diff --git a/src/ioc/db/dbAccess.c b/src/ioc/db/dbAccess.c index 10dc7f468..7fbfcc458 100644 --- a/src/ioc/db/dbAccess.c +++ b/src/ioc/db/dbAccess.c @@ -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); diff --git a/src/ioc/db/dbEvent.c b/src/ioc/db/dbEvent.c index 66b96b982..6bd27dc35 100644 --- a/src/ioc/db/dbEvent.c +++ b/src/ioc/db/dbEvent.c @@ -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); + } +} diff --git a/src/ioc/db/dbEvent.h b/src/ioc/db/dbEvent.h index 9c46b5f56..92776703d 100644 --- a/src/ioc/db/dbEvent.h +++ b/src/ioc/db/dbEvent.h @@ -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) diff --git a/src/ioc/db/db_field_log.h b/src/ioc/db/db_field_log.h index c38830bd9..8ed545063 100644 --- a/src/ioc/db/db_field_log.h +++ b/src/ioc/db/db_field_log.h @@ -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