Merge ~bhill/epics-base:db-tpro-show-values into epics-base:3.16

Proposed by Bruce Hill
Status: Needs review
Proposed branch: ~bhill/epics-base:db-tpro-show-values
Merge into: epics-base:3.16
Diff against target: 168 lines (+48/-0)
11 files modified
src/std/rec/aSubRecord.c (+2/-0)
src/std/rec/aiRecord.c (+4/-0)
src/std/rec/aoRecord.c (+4/-0)
src/std/rec/biRecord.c (+6/-0)
src/std/rec/boRecord.c (+5/-0)
src/std/rec/calcRecord.c (+5/-0)
src/std/rec/calcoutRecord.c (+5/-0)
src/std/rec/longinRecord.c (+4/-0)
src/std/rec/longoutRecord.c (+4/-0)
src/std/rec/mbbiRecord.c (+4/-0)
src/std/rec/mbboRecord.c (+5/-0)
Reviewer Review Type Date Requested Status
Andrew Johnson Needs Fixing
Ralph Lange Needs Fixing
Review via email: mp+341081@code.launchpad.net

Description of the change

Add diagnostic support for showing record values when TPRO is >= 2

To post a comment you must log in.
Revision history for this message
mdavidsaver (mdavidsaver) wrote :

See previous discussion at https://github.com/epics-base/epics-base/pull/20

I personally like the idea of using TPRO to control debug prints. So much so that I've been adding it to my drivers so the last couple of years.

I don't have a problem with overloading TPRO in this way in Base. I would make the threshold numbers it larger (5 and 10).

As this is Base, maybe we should add a new field instead? Is .DDBG taken (aka Device support DeBuG)?

Revision history for this message
Ralph Lange (ralph-lange) wrote :

I like the idea of separating the Device Support debug setting from Record Support debug setting (as I had stated in the GitHub discussion), so I would be in favor of a new field, and DDBG sounds good as a name.

Larger threshold values sound like a good idea.

I don't understand why the aSub does not get the VAL printed, and the message might be misleading (as OUTx are the output links, not the output values).
Also, for a debug function, I would expect it to print VALx values independent from the event posting setting. (As with all records that don't have such a setting.)

bi/bo should IMHO always print the numerical value, and add the string if ONAM/ZNAM are defined.

mbbi/mbbo should add the string representation if there is one defined.

For many record types, when used with other than Soft Device Support, the RVAL field is as interesting as the VAL field.

aai/aao/compress/dfanout/event/histogram/int64in/int64out/lsi/lso/mbbiDirect/mbboDirect/permissive/sel/seq/state/stringin/stringout/subArray/sub/waveform are missing.

review: Needs Fixing
Revision history for this message
Andrew Johnson (anj) wrote :

A Google search for "EPICS TPRO" came back with a tech-talk discussion:
  https://epics.anl.gov/tech-talk/2014/msg00129.php
This thread contained a response from me contrary to my github answer:

> I do like the idea of using TPRO > 1 to trigger debug messages from
> record processing, and this could also be used by device support. It
> should be up to the specific record/device support to document its usage
> though.

While writing that response in 2014 I also adjusted the Wiki description at
  https://wiki-ext.aps.anl.gov/epics/index.php/RRM_3-14_dbCommon
to say:

> If this field is non-zero a message is printed whenever this record is
> processed, and when any other record in the same lock-set is processed
> by a database link from this record.

Thus (following the legal principle of stare decisis) I rescind my github objection to the use of TPRO to enable debug messages, but I would like to see some kind of standardization in the values used, either globally or at least by the record type. If we're going to do this though we should also do all the record types in Base, not just the ones we use/like the most.

Question: Should the TPRO value be a verbosity level, page selector, a bit-mask or some combination of the 3?

I support Ralph's comments about the record-specific behaviors. The VAL field of an aSub record holds the status value returned by the subroutine and is less useful than that of a sub record, so I can understand not being interested in seeing that (printing SNAM when it changes would be useful though). The seq record has an even less useful VAL field, and I'm sure there are others like it so I think that what gets printed should be up to the record type.

Setting TPRO on a record also prints the record names of any other records in the same lockset that are processed directly by the record, but it does not change their TPRO fields, so those records will not have their debug print mechanisms triggered (unless they also have TPRO set). This is still reasonable behavior.

Setting TPRO to 255 could be used for a DOS attack if it results in a lot of output. We are probably already serializing all our record processing when TPRO is set though (through printing the record name to stdout in the dbProcess() routine) but this is really just another attack surface of which we already have too many for this to change.

review: Needs Fixing
Revision history for this message
Ralph Lange (ralph-lange) wrote :

> Question: Should the TPRO value be a verbosity level, page selector, a bit-mask or some combination of the 3?

Bit-masks may make sense in device support debugging that is often distributed over multiple layers - see ASYN's trace masks.

Record support is practically always one layer, and I see a verbosity level being more useful.

If we split Device Support debugging to a separate field, each device support can use it as it prefers: mask or page or level. In that case I would support TPRO being a verbosity level.

If TPRO is shared between Record and Device Support, things get messy.

Revision history for this message
mdavidsaver (mdavidsaver) wrote :

> Question: Should the TPRO value be a verbosity level, page selector, a bit-mask or some combination of the 3?

I've only used it as a verbosity level, aka. print if TPRO>=N for some value of N.

Revision history for this message
Bruce Hill (bhill) wrote :

I've found uses of TPRO as a verbosity level in several device support modules along w/ some that just enable
diagnostics for any non-zero tpro value.     That was what I was looking to do w/ this commit.

On 03/13/2018 08:12 AM, mdavidsaver wrote:
>> Question: Should the TPRO value be a verbosity level, page selector, a bit-mask or some combination of the 3?
> I've only used it as a verbosity level, aka. print if TPRO>=N for some value of N.

--
Bruce Hill
Member Technical Staff
SLAC National Accelerator Lab
2575 Sand Hill Road M/S 10
Menlo Park, CA 94025

Revision history for this message
Andrew Johnson (anj) wrote :

Core Meeting: Should be done for (and messages consistent from) all record types; TPRO value of 1 should be reserved for just the current trace processing, values for these messages should be sensible (higher numbers may print more stuff, leave room between numbers for device support, link support etc. to use as well); consider adding another message when beginning/ending an asynchronous I/O operation.

review: Needs Fixing

Unmerged commits

e13659d... by Bruce Hill

Add diagnostic support for showing record values when TPRO is >= 2

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/src/std/rec/aSubRecord.c b/src/std/rec/aSubRecord.c
index b7d2286..608d54b 100644
--- a/src/std/rec/aSubRecord.c
+++ b/src/std/rec/aSubRecord.c
@@ -429,6 +429,8 @@ static void monitor(aSubRecord *prec)
429 if (nev != onv || memcmp(povl, pval, alen)) {429 if (nev != onv || memcmp(povl, pval, alen)) {
430 memcpy(povl, pval, alen);430 memcpy(povl, pval, alen);
431 db_post_events(prec, pval, monitor_mask);431 db_post_events(prec, pval, monitor_mask);
432 if ( prec->tpro >= 5 )
433 printf( "%s.OUT%c changed!\n", prec->name, 'A' + i );
432 if (nev != onv) {434 if (nev != onv) {
433 *ponv = nev;435 *ponv = nev;
434 db_post_events(prec, pnev, monitor_mask);436 db_post_events(prec, pnev, monitor_mask);
diff --git a/src/std/rec/aiRecord.c b/src/std/rec/aiRecord.c
index 81f730f..e7c0377 100644
--- a/src/std/rec/aiRecord.c
+++ b/src/std/rec/aiRecord.c
@@ -167,6 +167,10 @@ static long process(struct dbCommon *pcommon)
167 if (status==0) convert(prec);167 if (status==0) convert(prec);
168 else if (status==2) status=0;168 else if (status==2) status=0;
169169
170 if ( prec->tpro >= 2 )
171 printf( "%s: Process %s, val %f\n",
172 epicsThreadGetNameSelf(), prec->name, prec->val );
173
170 /* check for alarms */174 /* check for alarms */
171 checkAlarms(prec,&timeLast);175 checkAlarms(prec,&timeLast);
172 /* check event list */176 /* check event list */
diff --git a/src/std/rec/aoRecord.c b/src/std/rec/aoRecord.c
index 0d923af..defd6a4 100644
--- a/src/std/rec/aoRecord.c
+++ b/src/std/rec/aoRecord.c
@@ -197,6 +197,10 @@ static long process(struct dbCommon *pcommon)
197 prec->udf = isnan(prec->val);197 prec->udf = isnan(prec->val);
198 }198 }
199199
200 if ( prec->tpro >= 2 )
201 printf( "%s: Process %s, val %f\n",
202 epicsThreadGetNameSelf(), prec->name, prec->val );
203
200 /* check for alarms */204 /* check for alarms */
201 checkAlarms(prec);205 checkAlarms(prec);
202206
diff --git a/src/std/rec/biRecord.c b/src/std/rec/biRecord.c
index 7afea3d..6c22116 100644
--- a/src/std/rec/biRecord.c
+++ b/src/std/rec/biRecord.c
@@ -142,6 +142,12 @@ static long process(struct dbCommon *pcommon)
142 prec->udf = FALSE;142 prec->udf = FALSE;
143 }143 }
144 else if(status==2) status=0;144 else if(status==2) status=0;
145
146 if ( prec->tpro >= 2 )
147 printf( "%s: Process %s, val %s\n",
148 epicsThreadGetNameSelf(), prec->name,
149 ( prec->val ? prec->onam : prec->znam ) );
150
145 /* check for alarms */151 /* check for alarms */
146 checkAlarms(prec);152 checkAlarms(prec);
147 /* check event list */153 /* check event list */
diff --git a/src/std/rec/boRecord.c b/src/std/rec/boRecord.c
index 8f60a0b..214f82d 100644
--- a/src/std/rec/boRecord.c
+++ b/src/std/rec/boRecord.c
@@ -221,6 +221,11 @@ static long process(struct dbCommon *pcommon)
221 } else prec->rval = (epicsUInt32)prec->val;221 } else prec->rval = (epicsUInt32)prec->val;
222 }222 }
223223
224 if ( prec->tpro >= 2 )
225 printf( "%s: Process %s, val %s\n",
226 epicsThreadGetNameSelf(), prec->name,
227 ( prec->val ? prec->onam : prec->znam ) );
228
224 /* check for alarms */229 /* check for alarms */
225 checkAlarms(prec);230 checkAlarms(prec);
226231
diff --git a/src/std/rec/calcRecord.c b/src/std/rec/calcRecord.c
index 12a58d1..a45e879 100644
--- a/src/std/rec/calcRecord.c
+++ b/src/std/rec/calcRecord.c
@@ -125,6 +125,11 @@ static long process(struct dbCommon *pcommon)
125125
126 timeLast = prec->time;126 timeLast = prec->time;
127 recGblGetTimeStamp(prec);127 recGblGetTimeStamp(prec);
128
129 if ( prec->tpro >= 2 )
130 printf( "%s: Process %s, val %f\n",
131 epicsThreadGetNameSelf(), prec->name, prec->val );
132
128 /* check for alarms */133 /* check for alarms */
129 checkAlarms(prec, &timeLast);134 checkAlarms(prec, &timeLast);
130 /* check event list */135 /* check event list */
diff --git a/src/std/rec/calcoutRecord.c b/src/std/rec/calcoutRecord.c
index 8b55255..80071b3 100644
--- a/src/std/rec/calcoutRecord.c
+++ b/src/std/rec/calcoutRecord.c
@@ -249,6 +249,11 @@ static long process(struct dbCommon *pcommon)
249 prec->udf = isnan(prec->val);249 prec->udf = isnan(prec->val);
250 }250 }
251 }251 }
252
253 if ( prec->tpro >= 2 )
254 printf( "%s: Process %s, val %f\n",
255 epicsThreadGetNameSelf(), prec->name, prec->val );
256
252 checkAlarms(prec);257 checkAlarms(prec);
253 /* check for output link execution */258 /* check for output link execution */
254 switch (prec->oopt) {259 switch (prec->oopt) {
diff --git a/src/std/rec/longinRecord.c b/src/std/rec/longinRecord.c
index bd3c24a..40e2242 100644
--- a/src/std/rec/longinRecord.c
+++ b/src/std/rec/longinRecord.c
@@ -152,6 +152,10 @@ static long process(struct dbCommon *pcommon)
152 recGblGetTimeStamp(prec);152 recGblGetTimeStamp(prec);
153 if (status==0) prec->udf = FALSE;153 if (status==0) prec->udf = FALSE;
154154
155 if ( prec->tpro >= 2 )
156 printf( "%s: Process %s, val %d\n",
157 epicsThreadGetNameSelf(), prec->name, prec->val );
158
155 /* check for alarms */159 /* check for alarms */
156 checkAlarms(prec, &timeLast);160 checkAlarms(prec, &timeLast);
157 /* check event list */161 /* check event list */
diff --git a/src/std/rec/longoutRecord.c b/src/std/rec/longoutRecord.c
index 6062ad7..0fba405 100644
--- a/src/std/rec/longoutRecord.c
+++ b/src/std/rec/longoutRecord.c
@@ -154,6 +154,10 @@ static long process(struct dbCommon *pcommon)
154 if (!status) convert(prec,value);154 if (!status) convert(prec,value);
155 }155 }
156156
157 if ( prec->tpro >= 2 )
158 printf( "%s: Process %s, val %d\n",
159 epicsThreadGetNameSelf(), prec->name, prec->val );
160
157 /* check for alarms */161 /* check for alarms */
158 checkAlarms(prec);162 checkAlarms(prec);
159163
diff --git a/src/std/rec/mbbiRecord.c b/src/std/rec/mbbiRecord.c
index ad5a8ce..96d54ab 100644
--- a/src/std/rec/mbbiRecord.c
+++ b/src/std/rec/mbbiRecord.c
@@ -201,6 +201,10 @@ static long process(struct dbCommon *pcommon)
201 else if (status == 2)201 else if (status == 2)
202 status = 0;202 status = 0;
203203
204 if ( prec->tpro >= 2 )
205 printf( "%s: Process %s, val %u\n",
206 epicsThreadGetNameSelf(), prec->name, prec->val );
207
204 checkAlarms(prec, &timeLast);208 checkAlarms(prec, &timeLast);
205 monitor(prec);209 monitor(prec);
206210
diff --git a/src/std/rec/mbboRecord.c b/src/std/rec/mbboRecord.c
index 0ae6a81..d99374a 100644
--- a/src/std/rec/mbboRecord.c
+++ b/src/std/rec/mbboRecord.c
@@ -224,6 +224,11 @@ static long process(struct dbCommon *pcommon)
224 }224 }
225225
226CONTINUE:226CONTINUE:
227
228 if ( prec->tpro >= 2 )
229 printf( "%s: Process %s, val %u\n",
230 epicsThreadGetNameSelf(), prec->name, prec->val );
231
227 /* Check for alarms */232 /* Check for alarms */
228 checkAlarms(prec);233 checkAlarms(prec);
229234

Subscribers

People subscribed via source and target branches