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:
committed by
Michael Davidsaver
parent
5ea973151f
commit
b09a9758b0
+47
-25
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user