diff --git a/modules/database/src/ioc/db/dbDbLink.c b/modules/database/src/ioc/db/dbDbLink.c index 0fb325f30..0243fde9a 100644 --- a/modules/database/src/ioc/db/dbDbLink.c +++ b/modules/database/src/ioc/db/dbDbLink.c @@ -337,8 +337,8 @@ static long dbDbGetUnits(const struct link *plink, char *units, int unitsSize) return 0; } -static long dbDbGetAlarm(const struct link *plink, epicsEnum16 *status, - epicsEnum16 *severity) +static long dbDbGetAlarmMsg(const struct link *plink, epicsEnum16 *status, + epicsEnum16 *severity, char *msgbuf, size_t msgbuflen) { dbChannel *chan = linkChannel(plink); dbCommon *precord = dbChannelRecord(chan); @@ -346,9 +346,19 @@ static long dbDbGetAlarm(const struct link *plink, epicsEnum16 *status, *status = precord->stat; if (severity) *severity = precord->sevr; + if (msgbuf && msgbuflen) { + strncpy(msgbuf, precord->amsg, msgbuflen-1); + msgbuf[msgbuflen-1] = '\0'; + } return 0; } +static long dbDbGetAlarm(const struct link *plink, epicsEnum16 *status, + epicsEnum16 *severity) +{ + return dbDbGetAlarmMsg(plink, status, severity, NULL, 0u); +} + static long dbDbGetTimeStamp(const struct link *plink, epicsTimeStamp *pstamp) { dbChannel *chan = linkChannel(plink); @@ -403,7 +413,8 @@ static lset dbDb_lset = { dbDbGetPrecision, dbDbGetUnits, dbDbGetAlarm, dbDbGetTimeStamp, dbDbPutValue, NULL, - dbDbScanFwdLink, doLocked + dbDbScanFwdLink, doLocked, + dbDbGetAlarmMsg, }; diff --git a/modules/database/src/ioc/db/dbLink.c b/modules/database/src/ioc/db/dbLink.c index f2e19dbcb..45b5e0f7e 100644 --- a/modules/database/src/ioc/db/dbLink.c +++ b/modules/database/src/ioc/db/dbLink.c @@ -402,14 +402,23 @@ long dbGetUnits(const struct link *plink, char *units, int unitsSize) } long dbGetAlarm(const struct link *plink, epicsEnum16 *status, - epicsEnum16 *severity) + epicsEnum16 *severity) +{ + return dbGetAlarmMsg(plink, status, severity, NULL, 0); +} + +long dbGetAlarmMsg(const struct link *plink, epicsEnum16 *status, + epicsEnum16 *severity, char *msgbuf, size_t msgbuflen) { lset *plset = plink->lset; - if (!plset || !plset->getAlarm) + if (plset && plset->getAlarmMsg) { + return plset->getAlarmMsg(plink, status, severity, msgbuf, msgbuflen); + } else if(plset && plset->getAlarm) { + return plset->getAlarm(plink, status, severity); + } else { return S_db_noLSET; - - return plset->getAlarm(plink, status, severity); + } } long dbGetTimeStamp(const struct link *plink, epicsTimeStamp *pstamp) diff --git a/modules/database/src/ioc/db/dbLink.h b/modules/database/src/ioc/db/dbLink.h index dd7163c8c..c0540271a 100644 --- a/modules/database/src/ioc/db/dbLink.h +++ b/modules/database/src/ioc/db/dbLink.h @@ -282,6 +282,8 @@ typedef struct lset { * @param status where to put the alarm status (or NULL) * @param severity where to put the severity (or NULL) * @returns status value + * + * @note Link types which provide getAlarm should also provided getAlarmMsg(). */ long (*getAlarm)(const struct link *plink, epicsEnum16 *status, epicsEnum16 *severity); @@ -361,6 +363,20 @@ typedef struct lset { * @returns status value */ long (*doLocked)(struct link *plink, dbLinkUserCallback rtn, void *priv); + + /** @brief Extended version of getAlarm + * + * Equivalent of getAlarm() and also copy out alarm message string. + * The msgbuf argument may be NULL and/or msgbuflen==0, in which case + * the call must be the same as a call to getAlarm(). + * + * Implementations must write a trailing nil to msgbuf whenever + * @code msgbuf!=NULL && msgbuflen>0 @endcode . + * + * @since UNRELEASED + */ + long (*getAlarmMsg)(const struct link *plink, epicsEnum16 *status, + epicsEnum16 *severity, char *msgbuf, size_t msgbuflen); } lset; #define dbGetSevr(link, sevr) \ @@ -402,6 +418,14 @@ DBCORE_API long dbGetUnits(const struct link *plink, char *units, int unitsSize); DBCORE_API long dbGetAlarm(const struct link *plink, epicsEnum16 *status, epicsEnum16 *severity); +/** Get link alarm and message string. + * To ensure the complete message string is copied, ensure @code msgbuflen >= sizeof (dbCommon::amsg) @endcode . + * A trailing nil will be added whenever @code msgbuflen > 0 @endcode . + * @since UNRELEASED + */ +DBCORE_API long dbGetAlarmMsg(const struct link *plink, epicsEnum16 *status, + epicsEnum16 *severity, char *msgbuf, size_t msgbuflen); +#define dbGetAlarmMsg(LINK, STAT, SEVR, BUF, BUFLEN) dbGetAlarmMsg(LINK, STAT, SEVR, BUF, BUFLEN) DBCORE_API long dbGetTimeStamp(const struct link *plink, epicsTimeStamp *pstamp); DBCORE_API long dbPutLink(struct link *plink, short dbrType, diff --git a/modules/database/src/std/link/lnkCalc.c b/modules/database/src/std/link/lnkCalc.c index 8d7f72c69..7c3eab722 100644 --- a/modules/database/src/std/link/lnkCalc.c +++ b/modules/database/src/std/link/lnkCalc.c @@ -53,6 +53,7 @@ typedef struct calc_link { } pstate; epicsEnum16 stat; epicsEnum16 sevr; + char amsg[MAX_STRING_SIZE]; short prec; char *expr; char *major; @@ -385,9 +386,10 @@ static void lnkCalc_report(const jlink *pjlink, int level, int indent) if (level > 0) { if (clink->sevr) - printf("%*s Alarm: %s, %s\n", indent, "", + printf("%*s Alarm: %s, %s, \"%s\"\n", indent, "", epicsAlarmSeverityStrings[clink->sevr], - epicsAlarmConditionStrings[clink->stat]); + epicsAlarmConditionStrings[clink->stat], + clink->amsg); if (clink->post_major) printf("%*s Major expression: \"%s\"\n", indent, "", @@ -583,6 +585,7 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer, } clink->stat = 0; clink->sevr = 0; + clink->amsg[0] = '\0'; if (clink->post_expr) { status = calcPerform(clink->arg, &clink->val, clink->post_expr); @@ -604,7 +607,8 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer, if (!status && alval) { clink->stat = LINK_ALARM; clink->sevr = MAJOR_ALARM; - recGblSetSevr(prec, clink->stat, clink->sevr); + strcpy(clink->amsg, "post_major error"); + recGblSetSevrMsg(prec, clink->stat, clink->sevr, "post_major error"); } } @@ -615,7 +619,8 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer, if (!status && alval) { clink->stat = LINK_ALARM; clink->sevr = MINOR_ALARM; - recGblSetSevr(prec, clink->stat, clink->sevr); + strcpy(clink->amsg, "post_minor error"); + recGblSetSevrMsg(prec, clink->stat, clink->sevr, "post_minor error"); } } @@ -659,6 +664,7 @@ static long lnkCalc_putValue(struct link *plink, short dbrType, } clink->stat = 0; clink->sevr = 0; + clink->amsg[0] = '\0'; /* Get the value being output as VAL */ status = conv(pbuffer, &clink->val, NULL); @@ -673,7 +679,8 @@ static long lnkCalc_putValue(struct link *plink, short dbrType, if (!status && alval) { clink->stat = LINK_ALARM; clink->sevr = MAJOR_ALARM; - recGblSetSevr(prec, clink->stat, clink->sevr); + strcpy(clink->amsg, "post_major error"); + recGblSetSevrMsg(prec, clink->stat, clink->sevr, "post_major error"); } } @@ -684,7 +691,8 @@ static long lnkCalc_putValue(struct link *plink, short dbrType, if (!status && alval) { clink->stat = LINK_ALARM; clink->sevr = MINOR_ALARM; - recGblSetSevr(prec, clink->stat, clink->sevr); + strcpy(clink->amsg, "post_major error"); + recGblSetSevrMsg(prec, clink->stat, clink->sevr, "post_minor error"); } } @@ -718,8 +726,8 @@ static long lnkCalc_getUnits(const struct link *plink, char *units, int len) return 0; } -static long lnkCalc_getAlarm(const struct link *plink, epicsEnum16 *status, - epicsEnum16 *severity) +static long lnkCalc_getAlarmMsg(const struct link *plink, epicsEnum16 *status, + epicsEnum16 *severity, char *msgbuf, size_t msgbuflen) { calc_link *clink = CONTAINER(plink->value.json.jlink, struct calc_link, jlink); @@ -728,10 +736,20 @@ static long lnkCalc_getAlarm(const struct link *plink, epicsEnum16 *status, *status = clink->stat; if (severity) *severity = clink->sevr; + if (msgbuf && msgbuflen) { + strncpy(msgbuf, clink->amsg, msgbuflen-1); + msgbuf[msgbuflen-1] = '\0'; + } return 0; } +static long lnkCalc_getAlarm(const struct link *plink, epicsEnum16 *status, + epicsEnum16 *severity) +{ + return lnkCalc_getAlarmMsg(plink, status, severity, NULL, 0u); +} + static long lnkCalc_getTimestamp(const struct link *plink, epicsTimeStamp *pstamp) { calc_link *clink = CONTAINER(plink->value.json.jlink, @@ -763,7 +781,8 @@ static lset lnkCalc_lset = { lnkCalc_getPrecision, lnkCalc_getUnits, lnkCalc_getAlarm, lnkCalc_getTimestamp, lnkCalc_putValue, NULL, - NULL, doLocked + NULL, doLocked, + lnkCalc_getAlarmMsg, }; static jlif lnkCalcIf = {