From 633859d7abfd5d61e24351f0922c887aa8f76e96 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Wed, 15 Apr 2020 20:26:37 -0700 Subject: [PATCH] pass amsg/utag through dbGet() options --- modules/database/src/ioc/db/dbAccess.c | 11 ++ modules/database/src/ioc/db/dbAccessDefs.h | 7 +- modules/database/src/ioc/db/dbEvent.c | 3 + modules/database/src/ioc/db/db_field_log.h | 2 + modules/database/test/ioc/db/dbPutGetTest.c | 179 ++++++++++++++++++- modules/database/test/ioc/db/dbPutGetTest.db | 2 + modules/database/test/ioc/db/xRecord.c | 77 +++++++- modules/database/test/ioc/db/xRecord.dbd | 4 + 8 files changed, 281 insertions(+), 4 deletions(-) diff --git a/modules/database/src/ioc/db/dbAccess.c b/modules/database/src/ioc/db/dbAccess.c index 6c418f968..ac4cec958 100644 --- a/modules/database/src/ioc/db/dbAccess.c +++ b/modules/database/src/ioc/db/dbAccess.c @@ -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 ) diff --git a/modules/database/src/ioc/db/dbAccessDefs.h b/modules/database/src/ioc/db/dbAccessDefs.h index bcd8d15df..32778451f 100644 --- a/modules/database/src/ioc/db/dbAccessDefs.h +++ b/modules/database/src/ioc/db/dbAccessDefs.h @@ -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*/\ diff --git a/modules/database/src/ioc/db/dbEvent.c b/modules/database/src/ioc/db/dbEvent.c index 6de565236..7342a0852 100644 --- a/modules/database/src/ioc/db/dbEvent.c +++ b/modules/database/src/ioc/db/dbEvent.c @@ -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); diff --git a/modules/database/src/ioc/db/db_field_log.h b/modules/database/src/ioc/db/db_field_log.h index f9b7cfbd4..1b759eb20 100644 --- a/modules/database/src/ioc/db/db_field_log.h +++ b/modules/database/src/ioc/db/db_field_log.h @@ -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 */ diff --git a/modules/database/test/ioc/db/dbPutGetTest.c b/modules/database/test/ioc/db/dbPutGetTest.c index 742318e3a..7de087043 100644 --- a/modules/database/test/ioc/db/dbPutGetTest.c +++ b/modules/database/test/ioc/db/dbPutGetTest.c @@ -7,12 +7,184 @@ #include #include +#include #include #include #include +#include +#include #include #include +#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(); diff --git a/modules/database/test/ioc/db/dbPutGetTest.db b/modules/database/test/ioc/db/dbPutGetTest.db index 816dc73f0..68485e4ba 100644 --- a/modules/database/test/ioc/db/dbPutGetTest.db +++ b/modules/database/test/ioc/db/dbPutGetTest.db @@ -44,3 +44,5 @@ record(arr, "arr") { field(FTVL, "ULONG") field(NELM, "10") } + +record(x, "recmeta") {} diff --git a/modules/database/test/ioc/db/xRecord.c b/modules/database/test/ioc/db/xRecord.c index 7cbcf1508..83ca9b15c 100644 --- a/modules/database/test/ioc/db/xRecord.c +++ b/modules/database/test/ioc/db/xRecord.c @@ -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); diff --git a/modules/database/test/ioc/db/xRecord.dbd b/modules/database/test/ioc/db/xRecord.dbd index 25013c042..13fcb3f3e 100644 --- a/modules/database/test/ioc/db/xRecord.dbd +++ b/modules/database/test/ioc/db/xRecord.dbd @@ -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) + } }