Changed db_field_log types to add support for plugin-created array copies

* db_field_log now is one of rec = use record, val = val inside, ref = reference inside
* add field_type and no_elements (to allow plugins change type and array size)
* add destructor in the ref type (called when deleting the db_field_log)
* change dbEvent.c and dbAccess.c to use the new field log features
This commit is contained in:
Ralph Lange
2012-04-27 13:21:54 -04:00
committed by Michael Davidsaver
parent 5ea973151f
commit b09a9758b0
4 changed files with 90 additions and 59 deletions
+47 -25
View File
@@ -315,28 +315,36 @@ static void get_alarm(DBADDR *paddr, char **ppbuffer,
return;
}
/*
* This code relies on *poriginal being aligned and all increments done by the
* blocks only changing the buffer pointer in a way that does not break alignment.
*/
static void getOptions(DBADDR *paddr, char **poriginal, long *options,
void *pflin)
{
db_field_log *pfl= (db_field_log *)pflin;
struct rset *prset;
short field_type=paddr->field_type;
short field_type;
dbCommon *pcommon;
char *pbuffer = *poriginal;
if (!pfl || pfl->type == dbfl_type_rec)
field_type = paddr->field_type;
else
field_type = pfl->field_type;
prset=dbGetRset(paddr);
/* Process options */
pcommon = paddr->precord;
if( (*options) & DBR_STATUS ) {
unsigned short *pushort = (unsigned short *)pbuffer;
if(pfl!=NULL) {
*pushort++ = pfl->u.v.stat;
*pushort++ = pfl->u.v.sevr;
} else {
if (!pfl || pfl->type == dbfl_type_rec) {
*pushort++ = pcommon->stat;
*pushort++ = pcommon->sevr;
}
} else {
*pushort++ = pfl->stat;
*pushort++ = pfl->sevr;
}
*pushort++ = pcommon->acks;
*pushort++ = pcommon->ackt;
pbuffer = (char *)pushort;
@@ -364,12 +372,12 @@ static void getOptions(DBADDR *paddr, char **poriginal, long *options,
if( (*options) & DBR_TIME ) {
epicsUInt32 *ptime = (epicsUInt32 *)pbuffer;
if(pfl!=NULL) {
*ptime++ = pfl->u.v.time.secPastEpoch;
*ptime++ = pfl->u.v.time.nsec;
} else {
*ptime++ = pcommon->time.secPastEpoch;
*ptime++ = pcommon->time.nsec;
if (!pfl || pfl->type == dbfl_type_rec) {
*ptime++ = pcommon->time.secPastEpoch;
*ptime++ = pcommon->time.nsec;
} else {
*ptime++ = pfl->time.secPastEpoch;
*ptime++ = pfl->time.nsec;
}
pbuffer = (char *)ptime;
}
@@ -778,8 +786,8 @@ long epicsShareAPI dbGet(DBADDR *paddr, short dbrType,
{
char *pbuf = pbuffer;
db_field_log *pfl = (db_field_log *)pflin;
short field_type = paddr->field_type;
long no_elements = paddr->no_elements;
short field_type;
long no_elements;
long offset;
struct rset *prset;
long status = 0;
@@ -789,6 +797,14 @@ long epicsShareAPI dbGet(DBADDR *paddr, short dbrType,
if (nRequest && *nRequest == 0)
return 0;
if (!pfl || pfl->type == dbfl_type_rec) {
field_type = paddr->field_type;
no_elements = paddr->no_elements;
} else {
field_type = pfl->field_type;
no_elements = pfl->no_elements;
}
if (field_type >= DBF_INLINK && field_type <= DBF_FWDLINK)
return getLinkValue(paddr, dbrType, pbuf, nRequest);
@@ -815,15 +831,18 @@ long epicsShareAPI dbGet(DBADDR *paddr, short dbrType,
if (offset == 0 && (!nRequest || no_elements == 1)) {
if (nRequest) *nRequest = 1;
if (pfl != NULL) {
DBADDR localAddr = *paddr; /* Structure copy */
localAddr.pfield = (char *)&pfl->u.v.field;
status = dbFastGetConvertRoutine[field_type][dbrType]
(localAddr.pfield, pbuffer, &localAddr);
} else {
if (!pfl || pfl->type == dbfl_type_rec) {
status = dbFastGetConvertRoutine[field_type][dbrType]
(paddr->pfield, pbuffer, paddr);
} else {
DBADDR localAddr = *paddr; /* Structure copy */
if (pfl->type == dbfl_type_val)
localAddr.pfield = (char *) &pfl->u.v.field;
else
localAddr.pfield = (char *) pfl->u.r.field;
status = dbFastGetConvertRoutine[field_type][dbrType]
(localAddr.pfield, pbuffer, &localAddr);
}
} else {
long n;
@@ -847,13 +866,16 @@ long epicsShareAPI dbGet(DBADDR *paddr, short dbrType,
/* convert database field and place it in the buffer */
if (n <= 0) {
;/*do nothing*/
} else if (pfl) {
} else if (!pfl || pfl->type == dbfl_type_rec) {
status = convert(paddr, pbuffer, n, no_elements, offset);
} else {
DBADDR localAddr = *paddr; /* Structure copy */
localAddr.pfield = (char *)&pfl->u.v.field;
if (pfl->type == dbfl_type_val)
localAddr.pfield = (char *) &pfl->u.v.field;
else
localAddr.pfield = (char *) pfl->u.r.field;
status = convert(&localAddr, pbuffer, n, no_elements, offset);
} else {
status = convert(paddr, pbuffer, n, no_elements, offset);
}
}
return status;
+16 -20
View File
@@ -634,10 +634,12 @@ db_field_log* db_post_single_event_first (struct evSubscrip *pevent)
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;
pLog->type = dbfl_type_val;
pLog->stat = prec->stat;
pLog->sevr = prec->sevr;
pLog->time = prec->time;
pLog->field_type = dbChannelFieldType(chan);
pLog->no_elements = dbChannelElements(chan);
/*
* use memcpy to avoid a bus error on
* union copy of char in the db at an odd
@@ -647,12 +649,7 @@ db_field_log* db_post_single_event_first (struct evSubscrip *pevent)
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;
pLog->type = dbfl_type_rec;
}
}
return pLog;
@@ -677,13 +674,15 @@ void db_post_single_event_final (void *pvt, evSubscrip *pevent, db_field_log *pL
LOCKEVQUE (ev_que)
/*
* if we have an event on the queue and we are
* not saving the current value (because this is a
* string or an array) then ignore duplicate
* events (saving them without the current valuye
* serves no purpose)
* if we have an event on the queue and both the last
* event on the queue and the current event are emtpy
* (i.e. of type dbfl_type_rec), simply ignore duplicate
* events (saving empty events serves no purpose)
*/
if (!pevent->useValque && pevent->npend>0u) {
if (pevent->npend > 0u &&
(*pevent->pLastLog)->type == dbfl_type_rec &&
pLog->type == dbfl_type_rec) {
db_delete_field_log(pLog);
UNLOCKEVQUE (ev_que)
return;
}
@@ -860,9 +859,6 @@ static int event_read ( struct event_que *ev_que )
* communication. (for other types they get whatever happens
* to be there upon wakeup)
*/
if ( !pevent->useValque ) {
pfl = NULL;
}
event_remove ( ev_que, ev_que->getix, EVENTQEMPTY );
ev_que->getix = RNGINC ( ev_que->getix );
@@ -1093,7 +1089,7 @@ 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);
if (pfl->type == dbfl_type_ref && pfl->u.r.dtor) pfl->u.r.dtor(pfl);
/* Free the field log chunk */
freeListFree(dbevFieldLogFreeList, pfl);
}
+23 -11
View File
@@ -46,26 +46,38 @@ union native_value {
* structure to log the state of a data base field at the time
* an event is triggered.
*/
struct db_field_log;
typedef void (dbfl_freeFunc)(struct db_field_log *pfl);
/* Types of db_field_log: rec = use record, val = val inside, ref = reference inside */
typedef enum dbfl_type {
dbfl_type_rec = 0,
dbfl_type_val,
dbfl_type_ref
} dbfl_type;
#define dbflTypeStr(t) (t==dbfl_type_val?"val":t==dbfl_type_rec?"rec":"ref")
struct dbfl_val {
unsigned short stat; /* Alarm Status */
unsigned short sevr; /* Alarm Severity */
epicsTimeStamp time; /* Time stamp */
union native_value field; /* Field value */
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 */
dbfl_freeFunc *dtor; /* Callback to free filter-allocated resources */
void *pvt; /* Private pointer */
void *field; /* Field value */
};
typedef struct db_field_log {
char isValue; /* is a value (*not* string/array) */
enum dbfl_type type; /* type (union) selector */
epicsTimeStamp time; /* Time stamp */
unsigned short stat; /* Alarm Status */
unsigned short sevr; /* Alarm Severity */
short field_type; /* DBF type of data */
long no_elements; /* No of array elements */
union {
struct dbfl_val v;
struct dbfl_ref p;
struct dbfl_ref r;
} u;
} db_field_log;
+4 -3
View File
@@ -22,12 +22,13 @@
#define e_error 0x00000004
#define e_ok 0x00000008
#define e_open 0x00000010
#define e_report 0x00000020
#define e_close 0x00000040
#define e_reg_pre_cb 0x00000020
#define e_report 0x00000040
#define e_close 0x00000080
unsigned int e, c;
#define e_any (e_alloc | e_free | e_error | e_ok | e_open | e_report | e_close)
#define e_any (e_alloc | e_free | e_error | e_ok | e_open | e_reg_pre_cb| e_report | e_close)
typedef struct myStruct {
int sent1;