Merge remote-tracking branch 'github/recursion_bug_v2' into PSI-7.0
This commit is contained in:
@ -232,19 +232,41 @@ static long dbDbGetValue(struct link *plink, short dbrType, void *pbuffer,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Some records get options (precsision, units, ...) for some fields
|
||||||
|
* from an input link. We need to catch the case that this link
|
||||||
|
* points back to the same field or we will end in an infinite recursion.
|
||||||
|
*/
|
||||||
|
static long dbDbGetOptionLoopSafe(const struct link *plink, short dbrType,
|
||||||
|
void *pbuffer, long option)
|
||||||
|
{
|
||||||
|
/* We need to cast away const to set the flags.
|
||||||
|
That's ok because we know that plink is never actually readonly.
|
||||||
|
And we reset everything to its original state.
|
||||||
|
*/
|
||||||
|
struct link *mutable_plink = (struct link *)plink;
|
||||||
|
long status = S_dbLib_badLink;
|
||||||
|
dbChannel *chan = linkChannel(plink);
|
||||||
|
DBADDR *paddr = &chan->addr;
|
||||||
|
long number_elements = 0;
|
||||||
|
|
||||||
|
dbScanLock(paddr->precord);
|
||||||
|
if (!(mutable_plink->flags & DBLINK_FLAG_VISITED)) {
|
||||||
|
mutable_plink->flags |= DBLINK_FLAG_VISITED;
|
||||||
|
status = dbGet(paddr, dbrType, pbuffer, &option, &number_elements, NULL);
|
||||||
|
mutable_plink->flags &= ~DBLINK_FLAG_VISITED;
|
||||||
|
}
|
||||||
|
dbScanUnlock(paddr->precord);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
static long dbDbGetControlLimits(const struct link *plink, double *low,
|
static long dbDbGetControlLimits(const struct link *plink, double *low,
|
||||||
double *high)
|
double *high)
|
||||||
{
|
{
|
||||||
dbChannel *chan = linkChannel(plink);
|
|
||||||
DBADDR *paddr = &chan->addr;
|
|
||||||
struct buffer {
|
struct buffer {
|
||||||
DBRctrlDouble
|
DBRctrlDouble
|
||||||
double value;
|
double value;
|
||||||
} buffer;
|
} buffer;
|
||||||
long options = DBR_CTRL_DOUBLE;
|
long status = dbDbGetOptionLoopSafe(plink, DBR_DOUBLE, &buffer, DBR_CTRL_DOUBLE);
|
||||||
long number_elements = 0;
|
|
||||||
long status = dbGet(paddr, DBR_DOUBLE, &buffer, &options, &number_elements,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
@ -257,16 +279,11 @@ static long dbDbGetControlLimits(const struct link *plink, double *low,
|
|||||||
static long dbDbGetGraphicLimits(const struct link *plink, double *low,
|
static long dbDbGetGraphicLimits(const struct link *plink, double *low,
|
||||||
double *high)
|
double *high)
|
||||||
{
|
{
|
||||||
dbChannel *chan = linkChannel(plink);
|
|
||||||
DBADDR *paddr = &chan->addr;
|
|
||||||
struct buffer {
|
struct buffer {
|
||||||
DBRgrDouble
|
DBRgrDouble
|
||||||
double value;
|
double value;
|
||||||
} buffer;
|
} buffer;
|
||||||
long options = DBR_GR_DOUBLE;
|
long status = dbDbGetOptionLoopSafe(plink, DBR_DOUBLE, &buffer, DBR_GR_DOUBLE);
|
||||||
long number_elements = 0;
|
|
||||||
long status = dbGet(paddr, DBR_DOUBLE, &buffer, &options, &number_elements,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
@ -279,16 +296,11 @@ static long dbDbGetGraphicLimits(const struct link *plink, double *low,
|
|||||||
static long dbDbGetAlarmLimits(const struct link *plink, double *lolo,
|
static long dbDbGetAlarmLimits(const struct link *plink, double *lolo,
|
||||||
double *low, double *high, double *hihi)
|
double *low, double *high, double *hihi)
|
||||||
{
|
{
|
||||||
dbChannel *chan = linkChannel(plink);
|
|
||||||
DBADDR *paddr = &chan->addr;
|
|
||||||
struct buffer {
|
struct buffer {
|
||||||
DBRalDouble
|
DBRalDouble
|
||||||
double value;
|
double value;
|
||||||
} buffer;
|
} buffer;
|
||||||
long options = DBR_AL_DOUBLE;
|
long status = dbDbGetOptionLoopSafe(plink, DBR_DOUBLE, &buffer, DBR_AL_DOUBLE);
|
||||||
long number_elements = 0;
|
|
||||||
long status = dbGet(paddr, DBR_DOUBLE, &buffer, &options, &number_elements,
|
|
||||||
0);
|
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
@ -302,16 +314,11 @@ static long dbDbGetAlarmLimits(const struct link *plink, double *lolo,
|
|||||||
|
|
||||||
static long dbDbGetPrecision(const struct link *plink, short *precision)
|
static long dbDbGetPrecision(const struct link *plink, short *precision)
|
||||||
{
|
{
|
||||||
dbChannel *chan = linkChannel(plink);
|
|
||||||
DBADDR *paddr = &chan->addr;
|
|
||||||
struct buffer {
|
struct buffer {
|
||||||
DBRprecision
|
DBRprecision
|
||||||
double value;
|
double value;
|
||||||
} buffer;
|
} buffer;
|
||||||
long options = DBR_PRECISION;
|
long status = dbDbGetOptionLoopSafe(plink, DBR_DOUBLE, &buffer, DBR_PRECISION);
|
||||||
long number_elements = 0;
|
|
||||||
long status = dbGet(paddr, DBR_DOUBLE, &buffer, &options, &number_elements,
|
|
||||||
0);
|
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
@ -322,16 +329,11 @@ static long dbDbGetPrecision(const struct link *plink, short *precision)
|
|||||||
|
|
||||||
static long dbDbGetUnits(const struct link *plink, char *units, int unitsSize)
|
static long dbDbGetUnits(const struct link *plink, char *units, int unitsSize)
|
||||||
{
|
{
|
||||||
dbChannel *chan = linkChannel(plink);
|
|
||||||
DBADDR *paddr = &chan->addr;
|
|
||||||
struct buffer {
|
struct buffer {
|
||||||
DBRunits
|
DBRunits
|
||||||
double value;
|
double value;
|
||||||
} buffer;
|
} buffer;
|
||||||
long options = DBR_UNITS;
|
long status = dbDbGetOptionLoopSafe(plink, DBR_DOUBLE, &buffer, DBR_UNITS);
|
||||||
long number_elements = 0;
|
|
||||||
long status = dbGet(paddr, DBR_DOUBLE, &buffer, &options, &number_elements,
|
|
||||||
0);
|
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
@ -72,6 +72,7 @@ DBCORE_API extern const maplinkType pamaplinkType[LINK_NTYPES];
|
|||||||
/* DBLINK Flag bits */
|
/* DBLINK Flag bits */
|
||||||
#define DBLINK_FLAG_INITIALIZED 1 /* dbInitLink() called */
|
#define DBLINK_FLAG_INITIALIZED 1 /* dbInitLink() called */
|
||||||
#define DBLINK_FLAG_TSELisTIME 2 /* Use TSEL to get timeStamp */
|
#define DBLINK_FLAG_TSELisTIME 2 /* Use TSEL to get timeStamp */
|
||||||
|
#define DBLINK_FLAG_VISITED 4 /* Used in loop detection */
|
||||||
|
|
||||||
struct macro_link {
|
struct macro_link {
|
||||||
char *macroStr;
|
char *macroStr;
|
||||||
|
@ -282,10 +282,10 @@ static void processCallback(epicsCallback *arg)
|
|||||||
static long get_units(DBADDR *paddr, char *units)
|
static long get_units(DBADDR *paddr, char *units)
|
||||||
{
|
{
|
||||||
seqRecord *prec = (seqRecord *) paddr->precord;
|
seqRecord *prec = (seqRecord *) paddr->precord;
|
||||||
int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY1);
|
int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY0);
|
||||||
|
|
||||||
if (fieldOffset >= 0)
|
if (fieldOffset >= 0)
|
||||||
switch (fieldOffset & 2) {
|
switch (fieldOffset & 3) {
|
||||||
case 0: /* DLYn */
|
case 0: /* DLYn */
|
||||||
strcpy(units, "s");
|
strcpy(units, "s");
|
||||||
break;
|
break;
|
||||||
@ -299,11 +299,11 @@ static long get_units(DBADDR *paddr, char *units)
|
|||||||
static long get_precision(const DBADDR *paddr, long *pprecision)
|
static long get_precision(const DBADDR *paddr, long *pprecision)
|
||||||
{
|
{
|
||||||
seqRecord *prec = (seqRecord *) paddr->precord;
|
seqRecord *prec = (seqRecord *) paddr->precord;
|
||||||
int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY1);
|
int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY0);
|
||||||
short precision;
|
short precision;
|
||||||
|
|
||||||
if (fieldOffset >= 0)
|
if (fieldOffset >= 0)
|
||||||
switch (fieldOffset & 2) {
|
switch (fieldOffset & 3) {
|
||||||
case 0: /* DLYn */
|
case 0: /* DLYn */
|
||||||
*pprecision = seqDLYprecision;
|
*pprecision = seqDLYprecision;
|
||||||
return 0;
|
return 0;
|
||||||
@ -321,10 +321,10 @@ static long get_precision(const DBADDR *paddr, long *pprecision)
|
|||||||
static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
|
static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
|
||||||
{
|
{
|
||||||
seqRecord *prec = (seqRecord *) paddr->precord;
|
seqRecord *prec = (seqRecord *) paddr->precord;
|
||||||
int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY1);
|
int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY0);
|
||||||
|
|
||||||
if (fieldOffset >= 0)
|
if (fieldOffset >= 0)
|
||||||
switch (fieldOffset & 2) {
|
switch (fieldOffset & 3) {
|
||||||
case 0: /* DLYn */
|
case 0: /* DLYn */
|
||||||
pgd->lower_disp_limit = 0.0;
|
pgd->lower_disp_limit = 0.0;
|
||||||
pgd->lower_disp_limit = 10.0;
|
pgd->lower_disp_limit = 10.0;
|
||||||
@ -341,9 +341,9 @@ static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
|
|||||||
|
|
||||||
static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
|
static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
|
||||||
{
|
{
|
||||||
int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY1);
|
int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY0);
|
||||||
|
|
||||||
if (fieldOffset >= 0 && (fieldOffset & 2) == 0) { /* DLYn */
|
if (fieldOffset >= 0 && (fieldOffset & 3) == 0) { /* DLYn */
|
||||||
pcd->lower_ctrl_limit = 0.0;
|
pcd->lower_ctrl_limit = 0.0;
|
||||||
pcd->upper_ctrl_limit = seqDLYlimit;
|
pcd->upper_ctrl_limit = seqDLYlimit;
|
||||||
}
|
}
|
||||||
@ -355,9 +355,9 @@ static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
|
|||||||
static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
|
static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
|
||||||
{
|
{
|
||||||
seqRecord *prec = (seqRecord *) paddr->precord;
|
seqRecord *prec = (seqRecord *) paddr->precord;
|
||||||
int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY1);
|
int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY0);
|
||||||
|
|
||||||
if (fieldOffset >= 0 && (fieldOffset & 2) == 2) /* DOn */
|
if (fieldOffset >= 0 && (fieldOffset & 3) == 2) /* DOn */
|
||||||
dbGetAlarmLimits(get_dol(prec, fieldOffset),
|
dbGetAlarmLimits(get_dol(prec, fieldOffset),
|
||||||
&pad->lower_alarm_limit, &pad->lower_warning_limit,
|
&pad->lower_alarm_limit, &pad->lower_warning_limit,
|
||||||
&pad->upper_warning_limit, &pad->upper_alarm_limit);
|
&pad->upper_warning_limit, &pad->upper_alarm_limit);
|
||||||
|
Reference in New Issue
Block a user