pass amsg/utag through dbGet() options
This commit is contained in:
@@ -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 )
|
||||
|
||||
@@ -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*/\
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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,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);
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user