pass amsg/utag through dbGet() options

This commit is contained in:
Michael Davidsaver
2020-04-15 20:26:37 -07:00
parent aad3476c04
commit 633859d7ab
8 changed files with 281 additions and 4 deletions
+11
View File
@@ -359,6 +359,14 @@ static void getOptions(DBADDR *paddr, char **poriginal, long *options,
*pushort++ = pcommon->acks;
*pushort++ = pcommon->ackt;
pbuffer = (char *)pushort;
if (!pfl || pfl->type == dbfl_type_rec) {
STATIC_ASSERT(sizeof(pcommon->amsg)==sizeof(pfl->amsg));
strncpy(pbuffer, pcommon->amsg, sizeof(pcommon->amsg)-1);
} else {
strncpy(pbuffer, pfl->amsg,sizeof(pfl->amsg)-1);
}
pbuffer[sizeof(pcommon->amsg)-1] = '\0';
pbuffer += sizeof(pcommon->amsg);
}
if( (*options) & DBR_UNITS ) {
memset(pbuffer,'\0',dbr_units_size);
@@ -386,10 +394,13 @@ static void getOptions(DBADDR *paddr, char **poriginal, long *options,
if (!pfl) {
*ptime++ = pcommon->time.secPastEpoch;
*ptime++ = pcommon->time.nsec;
*ptime++ = pcommon->utag;
} else {
*ptime++ = pfl->time.secPastEpoch;
*ptime++ = pfl->time.nsec;
*ptime++ = pfl->utag;
}
*ptime++ = 0; /* padding */
pbuffer = (char *)ptime;
}
if( (*options) & DBR_ENUM_STRS )
+5 -2
View File
@@ -99,7 +99,8 @@ DBCORE_API extern int dbAccessDebugPUTF;
epicsUInt16 status; /* alarm status */\
epicsUInt16 severity; /* alarm severity*/\
epicsUInt16 acks; /* alarm ack severity*/\
epicsUInt16 ackt; /* Acknowledge transient alarms?*/
epicsUInt16 ackt; /* Acknowledge transient alarms?*/\
char amsg[40];
#define DB_UNITS_SIZE 16
#define DBRunits \
char units[DB_UNITS_SIZE]; /* units */
@@ -112,7 +113,9 @@ DBCORE_API extern int dbAccessDebugPUTF;
* too late to change now. DBRprecision must be padded to
* maintain 8-byte alignment. */
#define DBRtime \
epicsTimeStamp time; /* time stamp*/
epicsTimeStamp time; /* time stamp*/\
epicsInt32 utag;\
epicsInt32 padTime;
#define DBRenumStrs \
epicsUInt32 no_str; /* number of strings*/\
epicsInt32 padenumStrs; /*padding to force 8 byte align*/\
+3
View File
@@ -675,7 +675,10 @@ static db_field_log* db_create_field_log (struct dbChannel *chan, int use_val)
struct dbCommon *prec = dbChannelRecord(chan);
pLog->stat = prec->stat;
pLog->sevr = prec->sevr;
strncpy(pLog->amsg, prec->amsg, sizeof(pLog->amsg)-1);
pLog->amsg[sizeof(pLog->amsg)-1] = '\0';
pLog->time = prec->time;
pLog->utag = prec->utag;
pLog->field_type = dbChannelFieldType(chan);
pLog->field_size = dbChannelFieldSize(chan);
pLog->no_elements = dbChannelElements(chan);
@@ -113,8 +113,10 @@ typedef struct db_field_log {
unsigned char mask; /* DBE_* mask */
/* the following are used for value and reference types */
epicsTimeStamp time; /* Time stamp */
epicsInt32 utag;
unsigned short stat; /* Alarm Status */
unsigned short sevr; /* Alarm Severity */
char amsg[40];
short field_type; /* DBF type of data */
short field_size; /* Size of a single element */
long no_elements; /* No of valid array elements */
+178 -1
View File
@@ -7,12 +7,184 @@
#include <string.h>
#include <errlog.h>
#include <alarm.h>
#include <dbAccess.h>
#include <dbStaticLib.h>
#include <dbStaticPvt.h>
#include <dbChannel.h>
#include <dbEvent.h>
#include <dbUnitTest.h>
#include <testMain.h>
#include "xRecord.h"
typedef struct {
DBRstatus
DBRunits
DBRprecision
DBRtime
DBRgrDouble
DBRctrlDouble
DBRalDouble
} dbMetaDouble;
enum {dbMetaDoubleMask = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_TIME | DBR_GR_DOUBLE | DBR_CTRL_DOUBLE | DBR_AL_DOUBLE};
static
void testdbMetaDoubleSizes(void)
{
dbMetaDouble meta;
size_t pos=0;
testDiag("dbMetaDouble may not have padding");
#define testOffset(FLD) do {\
testOk(offsetof(dbMetaDouble, FLD)==pos, "offset(meta, " #FLD "), %u == %u", (unsigned)offsetof(dbMetaDouble, FLD), (unsigned)pos); \
pos += sizeof(meta.FLD); \
}while(0)
testOffset(status);
testOffset(severity);
testOffset(acks);
testOffset(ackt);
testOffset(amsg);
testOffset(units);
testOffset(precision);
testOffset(time);
testOffset(utag);
testOffset(padTime);
testOffset(upper_disp_limit);
testOffset(lower_disp_limit);
testOffset(upper_ctrl_limit);
testOffset(lower_ctrl_limit);
testOffset(upper_alarm_limit);
testOffset(upper_warning_limit);
testOffset(lower_warning_limit);
testOffset(lower_alarm_limit);
#undef testOffset
testOk(sizeof(dbMetaDouble)==pos, "sizeof(dbMetaDouble), %u == %u", (unsigned)sizeof(dbMetaDouble), (unsigned)pos);
}
static
void checkDoubleGet(dbChannel *chan, db_field_log* pfl)
{
dbMetaDouble meta;
long options = (long)dbMetaDoubleMask;
long nReq = 0;
long status;
status=dbChannelGet(chan, DBF_DOUBLE, &meta, &options, &nReq, pfl);
testOk(status==0, "dbGet OTST : %ld", status);
testOk1(meta.severity==INVALID_ALARM);
testOk1(meta.status==UDF_ALARM);
testOk1(meta.acks==MAJOR_ALARM);
testOk1(meta.ackt==1);
testOk1(strncmp(meta.amsg, "oops", DB_UNITS_SIZE)==0);
testOk1(meta.time.secPastEpoch==0x12345678);
testOk1(meta.time.nsec==0x90abcdef);
testOk1(meta.utag==0x10203040);
testOk1(meta.precision.dp==0x12345678);
testOk1(strncmp(meta.units, "arbitrary", DB_UNITS_SIZE)==0);
#define limitEq(UL, FL, VAL) testOk(meta.UL ## _ ## FL ## _limit == (VAL), #UL "_" #FL "_limit (%f) == %f", meta.UL ## _ ## FL ## _limit, VAL)
limitEq(lower, disp, 10000000.0-1.0);
limitEq(upper, disp, 10000000.0+1.0);
limitEq(lower, ctrl, 10000000.0-2.0);
limitEq(upper, ctrl, 10000000.0+2.0);
limitEq(lower, alarm, 10000000.0-3.0);
limitEq(lower, warning, 10000000.0-4.0);
limitEq(upper, warning, 10000000.0+4.0);
limitEq(upper, alarm, 10000000.0+3.0);
#undef limitEq
}
static
void testdbMetaDoubleGet(void)
{
xRecord* prec = (xRecord*)testdbRecordPtr("recmeta");
dbChannel *chan = dbChannelCreate("recmeta.OTST");
db_field_log *pfl;
evSubscrip evsub;
long status;
dbMetaDouble meta;
STATIC_ASSERT(sizeof(meta.amsg)==sizeof(prec->amsg));
STATIC_ASSERT(sizeof(meta.amsg)==sizeof(pfl->amsg));
if(!chan)
testAbort("Missing recmeta OTST");
if((status=dbChannelOpen(chan))!=0)
testAbort("can't open recmeta OTST : %ld", status);
dbScanLock((dbCommon*)prec);
/* ensure that all meta-data has different non-zero values */
prec->otst = 10000000.0;
prec->sevr = INVALID_ALARM;
prec->stat = UDF_ALARM;
strcpy(prec->amsg, "oops");
prec->acks = MAJOR_ALARM;
prec->time.secPastEpoch = 0x12345678;
prec->time.nsec = 0x90abcdef;
prec->utag = 0x10203040;
testDiag("dbGet directly from record");
checkDoubleGet(chan, NULL);
testDiag("dbGet from field log");
/* bare minimum init for db_create_event_log() */
memset(&evsub, 0, sizeof(evsub));
evsub.chan = chan;
evsub.useValque = 1;
pfl = db_create_event_log(&evsub);
/* spoil things which should now come from field log */
prec->sevr = 0;
prec->stat = 0;
strcpy(prec->amsg, "invalid");
prec->time.secPastEpoch = 0xdeadbeef;
prec->time.nsec = 0xdeadbeef;
prec->utag = 0xdeadbeef;
/* never any filters, so skip pre/post */
checkDoubleGet(chan, pfl);
db_delete_field_log(pfl);
dbScanUnlock((dbCommon*)prec);
}
typedef struct {
DBRstatus
DBRtime
DBRenumStrs
} dbMetaEnum;
static
void testdbMetaEnumSizes(void)
{
dbMetaEnum meta;
size_t pos=0;
testDiag("dbMetaEnum may not have implicit padding");
#define testOffset(FLD) do {\
testOk(offsetof(dbMetaEnum, FLD)==pos, "offset(meta, " #FLD "), %u == %u", (unsigned)offsetof(dbMetaEnum, FLD), (unsigned)pos); \
pos += sizeof(meta.FLD); \
}while(0)
testOffset(status);
testOffset(severity);
testOffset(acks);
testOffset(ackt);
testOffset(amsg);
testOffset(time);
testOffset(utag);
testOffset(padTime);
testOffset(no_str);
testOffset(padenumStrs);
testOffset(strs);
#undef testOffset
testOk(sizeof(dbMetaEnum)==pos, "sizeof(dbMetaEnum), %u == %u", (unsigned)sizeof(dbMetaEnum), (unsigned)pos);
}
static
void testdbGetStringEqual(const char *pv, const char *expected)
{
@@ -143,9 +315,12 @@ void dbTestIoc_registerRecordDeviceDriver(struct dbBase *);
MAIN(dbPutGet)
{
testPlan(44);
testPlan(113);
testdbPrepare();
testdbMetaDoubleSizes();
testdbMetaEnumSizes();
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
dbTestIoc_registerRecordDeviceDriver(pdbbase);
testdbReadDatabase("dbPutGetTest.db", NULL, NULL);
@@ -158,6 +333,8 @@ MAIN(dbPutGet)
testIocInitOk();
eltc(1);
testdbMetaDoubleGet();
testLongLink();
testLongAttr();
testLongField();
@@ -44,3 +44,5 @@ record(arr, "arr") {
field(FTVL, "ULONG")
field(NELM, "10")
}
record(x, "recmeta") {}
+76 -1
View File
@@ -76,7 +76,82 @@ static long process(struct dbCommon *pcommon)
return ret;
}
long get_units(struct dbAddr *paddr, char *units)
{
if(dbGetFieldIndex(paddr)==xRecordOTST) {
strncpy(units, "arbitrary", DB_UNITS_SIZE);
}
return 0;
}
long get_precision(const struct dbAddr *paddr, long *precision)
{
if(dbGetFieldIndex(paddr)==xRecordOTST) {
*precision = 0x12345678;
}
return 0;
}
long get_graphic_double(struct dbAddr *paddr, struct dbr_grDouble *p)
{
xRecord *prec = (xRecord *)paddr->precord;
if(dbGetFieldIndex(paddr)==xRecordOTST) {
p->lower_disp_limit = prec->otst-1.0;
p->upper_disp_limit = prec->otst+1.0;
}
return 0;
}
long get_control_double(struct dbAddr *paddr, struct dbr_ctrlDouble *p)
{
xRecord *prec = (xRecord *)paddr->precord;
if(dbGetFieldIndex(paddr)==xRecordOTST) {
p->lower_ctrl_limit = prec->otst-2.0;
p->upper_ctrl_limit = prec->otst+2.0;
}
return 0;
}
long get_alarm_double(struct dbAddr *paddr, struct dbr_alDouble *p)
{
xRecord *prec = (xRecord *)paddr->precord;
if(dbGetFieldIndex(paddr)==xRecordOTST) {
p->lower_alarm_limit = prec->otst-3.0;
p->lower_warning_limit = prec->otst-4.0;
p->upper_warning_limit = prec->otst+4.0;
p->upper_alarm_limit = prec->otst+3.0;
}
return 0;
}
#define report NULL
#define initialize NULL
#define special NULL
#define get_value NULL
#define cvt_dbaddr NULL
#define get_array_info NULL
#define put_array_info NULL
#define get_enum_str NULL
#define get_enum_strs NULL
#define put_enum_str NULL
static rset xRSET = {
RSETNUMBER, NULL, NULL, init_record, process
RSETNUMBER,
report,
initialize,
init_record,
process,
special,
get_value,
cvt_dbaddr,
get_array_info,
put_array_info,
get_units,
get_precision,
get_enum_str,
get_enum_strs,
put_enum_str,
get_graphic_double,
get_control_double,
get_alarm_double
};
epicsExportAddress(rset,xRSET);
+4
View File
@@ -46,4 +46,8 @@ recordtype(x) {
special(SPC_NOMOD)
extra("void (*clbk)(struct xRecord*)")
}
field(OTST, DBF_DOUBLE) {
prompt("dbGet() options test")
special(SPC_NOMOD)
}
}