library: provide for validating result type references

During development, we now have a means for validating
that a type referenced in application code matches the
actual type set by the library. The new feature can be
activated through either of the following two methods:

1) ./configure CFLAGS='-DXTRA_PROCPS_DEBUG' (all pgms)

2) an #include <proc/xtra-procps-debug.h> (single pgm)

[ in the future, one could add a formal configure.ac ]
[ provision. but for now a manual approach is safer. ]

Lastly, for any module which provides a sort function,
the handling for both 'noop' & 'extra' enumerators was
made consistent. Now, 'noop' is not sorted and 'extra'
will be sorted as that module's widest supported type.

Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
Jim Warner
2016-08-05 00:00:00 -05:00
committed by Craig Small
parent e0515e23e7
commit e3270d463d
10 changed files with 1103 additions and 567 deletions

View File

@ -206,6 +206,9 @@ typedef void (*SET_t)(struct diskstats_result *, struct dev_node *);
typedef int (*QSR_t)(const void *, const void *, void *);
#define QS(t) (QSR_t)srtNAME(t)
#define TS(t) STRINGIFY(t)
#define TS_noop ""
/*
* Need it be said?
* This table must be kept in the exact same order as
@ -213,43 +216,44 @@ typedef int (*QSR_t)(const void *, const void *, void *);
static struct {
SET_t setsfunc; // the actual result setting routine
QSR_t sortfunc; // sort cmp func for a specific type
char *type2str; // the result type as a string value
} Item_table[] = {
/* setsfunc sortfunc
---------------------------------- --------- */
{ RS(noop), QS(ul_int) },
{ RS(extra), QS(noop) },
/* setsfunc sortfunc type2str
---------------------------------- ----------- ---------- */
{ RS(noop), QS(noop), TS_noop },
{ RS(extra), QS(ul_int), TS_noop },
{ RS(DISKSTATS_NAME), QS(str) },
{ RS(DISKSTATS_TYPE), QS(s_int) },
{ RS(DISKSTATS_MAJOR), QS(s_int) },
{ RS(DISKSTATS_MINOR), QS(s_int) },
{ RS(DISKSTATS_NAME), QS(str), TS(str) },
{ RS(DISKSTATS_TYPE), QS(s_int), TS(s_int) },
{ RS(DISKSTATS_MAJOR), QS(s_int), TS(s_int) },
{ RS(DISKSTATS_MINOR), QS(s_int), TS(s_int) },
{ RS(DISKSTATS_READS), QS(ul_int) },
{ RS(DISKSTATS_READS_MERGED), QS(ul_int) },
{ RS(DISKSTATS_READ_SECTORS), QS(ul_int) },
{ RS(DISKSTATS_READ_TIME), QS(ul_int) },
{ RS(DISKSTATS_WRITES), QS(ul_int) },
{ RS(DISKSTATS_WRITES_MERGED), QS(ul_int) },
{ RS(DISKSTATS_WRITE_SECTORS), QS(ul_int) },
{ RS(DISKSTATS_WRITE_TIME), QS(ul_int) },
{ RS(DISKSTATS_IO_TIME), QS(ul_int) },
{ RS(DISKSTATS_IO_WTIME), QS(ul_int) },
{ RS(DISKSTATS_READS), QS(ul_int), TS(ul_int) },
{ RS(DISKSTATS_READS_MERGED), QS(ul_int), TS(ul_int) },
{ RS(DISKSTATS_READ_SECTORS), QS(ul_int), TS(ul_int) },
{ RS(DISKSTATS_READ_TIME), QS(ul_int), TS(ul_int) },
{ RS(DISKSTATS_WRITES), QS(ul_int), TS(ul_int) },
{ RS(DISKSTATS_WRITES_MERGED), QS(ul_int), TS(ul_int) },
{ RS(DISKSTATS_WRITE_SECTORS), QS(ul_int), TS(ul_int) },
{ RS(DISKSTATS_WRITE_TIME), QS(ul_int), TS(ul_int) },
{ RS(DISKSTATS_IO_TIME), QS(ul_int), TS(ul_int) },
{ RS(DISKSTATS_IO_WTIME), QS(ul_int), TS(ul_int) },
{ RS(DISKSTATS_IO_INPROGRESS), QS(s_int) },
{ RS(DISKSTATS_IO_INPROGRESS), QS(s_int), TS(s_int) },
{ RS(DISKSTATS_DELTA_READS), QS(s_int) },
{ RS(DISKSTATS_DELTA_READS_MERGED), QS(s_int) },
{ RS(DISKSTATS_DELTA_READ_SECTORS), QS(s_int) },
{ RS(DISKSTATS_DELTA_READ_TIME), QS(s_int) },
{ RS(DISKSTATS_DELTA_WRITES), QS(s_int) },
{ RS(DISKSTATS_DELTA_WRITES_MERGED), QS(s_int) },
{ RS(DISKSTATS_DELTA_WRITE_SECTORS), QS(s_int) },
{ RS(DISKSTATS_DELTA_WRITE_TIME), QS(s_int) },
{ RS(DISKSTATS_DELTA_IO_TIME), QS(s_int) },
{ RS(DISKSTATS_DELTA_IO_WTIME), QS(s_int) },
{ RS(DISKSTATS_DELTA_READS), QS(s_int), TS(s_int) },
{ RS(DISKSTATS_DELTA_READS_MERGED), QS(s_int), TS(s_int) },
{ RS(DISKSTATS_DELTA_READ_SECTORS), QS(s_int), TS(s_int) },
{ RS(DISKSTATS_DELTA_READ_TIME), QS(s_int), TS(s_int) },
{ RS(DISKSTATS_DELTA_WRITES), QS(s_int), TS(s_int) },
{ RS(DISKSTATS_DELTA_WRITES_MERGED), QS(s_int), TS(s_int) },
{ RS(DISKSTATS_DELTA_WRITE_SECTORS), QS(s_int), TS(s_int) },
{ RS(DISKSTATS_DELTA_WRITE_TIME), QS(s_int), TS(s_int) },
{ RS(DISKSTATS_DELTA_IO_TIME), QS(s_int), TS(s_int) },
{ RS(DISKSTATS_DELTA_IO_WTIME), QS(s_int), TS(s_int) },
// dummy entry corresponding to DISKSTATS_logical_end ...
{ NULL, NULL }
{ NULL, NULL, NULL }
};
/* please note,
@ -974,3 +978,57 @@ PROCPS_EXPORT struct diskstats_stack **procps_diskstats_sort (
qsort_r(stacks, numstacked, sizeof(void *), (QSR_t)Item_table[p->item].sortfunc, &parms);
return stacks;
} // end: procps_diskstats_sort
// --- special debugging function(s) ------------------------------------------
/*
* The following isn't part of the normal programming interface. Rather,
* it exists to validate result types referenced in application programs.
*
* It's used only when:
* 1) the 'XTRA_PROCPS_DEBUG' has been defined, or
* 2) the '#include <proc/xtra-procps-debug.h>' used
*/
PROCPS_EXPORT struct diskstats_result *xtra_diskstats_get (
struct diskstats_info *info,
const char *name,
enum diskstats_item actual_enum,
const char *typestr,
const char *file,
int lineno)
{
struct diskstats_result *r = procps_diskstats_get(info, name, actual_enum);
if (r) {
char *str = Item_table[r->item].type2str;
if (str[0]
&& (strcmp(typestr, str)))
fprintf(stderr, "%s line %d: was %s, expected %s\n", file, lineno, typestr, str);
}
return r;
} // end: xtra_diskstats_get_
PROCPS_EXPORT void xtra_diskstats_val (
int relative_enum,
const char *typestr,
const struct diskstats_stack *stack,
struct diskstats_info *info,
const char *file,
int lineno)
{
struct diskstats_result *r;
char *str;
r = &stack->head[relative_enum];
if (r->item < 0 || r->item >= DISKSTATS_logical_end) {
fprintf(stderr, "%s line %d: invalid item = %d, relative_enum = %d, type = %s\n"
, file, lineno, r->item, relative_enum, typestr);
return;
}
str = Item_table[r->item].type2str;
if (str[0]
&& (strcmp(typestr, str)))
fprintf(stderr, "%s line %d: was %s, expected %s\n", file, lineno, typestr, str);
} // end: xtra_diskstats_val