Implement compute_stats() in terms of devstat_compute_statistics(). This

gets rid of the duplicated code in compute_stats().

Add a new DSM_SKIP statistic type for devstat_compute_statistics() that
causes the subsequent variable argument to be skipped.

Thanks to Sergey Osokin for coding up my idea/code fragment.

Submitted by:	"Sergey A. Osokin" <osa@freebsd.org.ru>
This commit is contained in:
Kenneth D. Merry 2001-08-18 05:46:59 +00:00
parent 29b7fbd17f
commit 884539f701
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=81883
3 changed files with 41 additions and 104 deletions

View File

@ -762,6 +762,18 @@ and
.Va current .
As above, this is not the true number of milliseconds per transaction, but
rather the average rate of write transaction completion.
.It DSM_SKIP
type: N/A
.Pp
If you do not need a result from
.Fn devstat_compute_statistics ,
just put
.Va DSM_SKIP
as first (type) parameter and
.Va NULL
as second parameter.
This can be useful in scenarios where the statistics to be calculated
are determined at run time.
.El
.Pp
.Fn compute_stats

View File

@ -49,7 +49,8 @@
typedef enum {
DEVSTAT_ARG_NOTYPE,
DEVSTAT_ARG_UINT64,
DEVSTAT_ARG_LD
DEVSTAT_ARG_LD,
DEVSTAT_ARG_SKIP
} devstat_arg_type;
char devstat_errbuf[DEVSTAT_ERRBUF_SIZE];
@ -109,7 +110,8 @@ struct devstat_args {
{ DSM_BLOCKS_PER_SECOND_WRITE, DEVSTAT_ARG_LD },
{ DSM_MS_PER_TRANSACTION, DEVSTAT_ARG_LD },
{ DSM_MS_PER_TRANSACTION_READ, DEVSTAT_ARG_LD },
{ DSM_MS_PER_TRANSACTION_WRITE, DEVSTAT_ARG_LD }
{ DSM_MS_PER_TRANSACTION_WRITE, DEVSTAT_ARG_LD },
{ DSM_SKIP, DEVSTAT_ARG_SKIP }
};
static char *namelist[] = {
@ -1129,89 +1131,24 @@ compute_stats(struct devstat *current, struct devstat *previous,
long double *mb_per_second, long double *blocks_per_second,
long double *ms_per_transaction)
{
u_int64_t totalbytes, totaltransfers, totalblocks;
char *func_name = "compute_stats";
/*
* current is the only mandatory field.
*/
if (current == NULL) {
snprintf(devstat_errbuf, sizeof(devstat_errbuf),
"%s: current stats structure was NULL",
func_name);
return(-1);
}
totalbytes = (current->bytes_written + current->bytes_read) -
((previous) ? (previous->bytes_written +
previous->bytes_read) : 0);
if (total_bytes)
*total_bytes = totalbytes;
totaltransfers = (current->num_reads +
current->num_writes +
current->num_other) -
((previous) ?
(previous->num_reads +
previous->num_writes +
previous->num_other) : 0);
if (total_transfers)
*total_transfers = totaltransfers;
if (transfers_per_second) {
if (etime > 0.0) {
*transfers_per_second = totaltransfers;
*transfers_per_second /= etime;
} else
*transfers_per_second = 0.0;
}
if (kb_per_transfer) {
*kb_per_transfer = totalbytes;
*kb_per_transfer /= 1024;
if (totaltransfers > 0)
*kb_per_transfer /= totaltransfers;
else
*kb_per_transfer = 0.0;
}
if (mb_per_second) {
*mb_per_second = totalbytes;
*mb_per_second /= 1024 * 1024;
if (etime > 0.0)
*mb_per_second /= etime;
else
*mb_per_second = 0.0;
}
totalblocks = totalbytes;
if (current->block_size > 0)
totalblocks /= current->block_size;
else
totalblocks /= 512;
if (total_blocks)
*total_blocks = totalblocks;
if (blocks_per_second) {
*blocks_per_second = totalblocks;
if (etime > 0.0)
*blocks_per_second /= etime;
else
*blocks_per_second = 0.0;
}
if (ms_per_transaction) {
if (totaltransfers > 0) {
*ms_per_transaction = etime;
*ms_per_transaction /= totaltransfers;
*ms_per_transaction *= 1000;
} else
*ms_per_transaction = 0.0;
}
return(0);
return(devstat_compute_statistics(current, previous, etime,
total_bytes ? DSM_TOTAL_BYTES : DSM_SKIP,
total_bytes,
total_transfers ? DSM_TOTAL_TRANSFERS : DSM_SKIP,
total_transfers,
total_blocks ? DSM_TOTAL_BLOCKS : DSM_SKIP,
total_blocks,
kb_per_transfer ? DSM_KB_PER_TRANSFER : DSM_SKIP,
kb_per_transfer,
transfers_per_second ? DSM_TRANSFERS_PER_SECOND : DSM_SKIP,
transfers_per_second,
mb_per_second ? DSM_MB_PER_SECOND : DSM_SKIP,
mb_per_second,
blocks_per_second ? DSM_BLOCKS_PER_SECOND : DSM_SKIP,
blocks_per_second,
ms_per_transaction ? DSM_MS_PER_TRANSACTION : DSM_SKIP,
ms_per_transaction,
DSM_NONE));
}
long double
@ -1309,35 +1246,22 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous,
switch (devstat_arg_list[metric].argtype) {
case DEVSTAT_ARG_UINT64:
destu64 = (u_int64_t *)va_arg(ap, u_int64_t *);
if (destu64 == NULL) {
snprintf(devstat_errbuf, sizeof(devstat_errbuf),
"%s: argument type not u_int64_t * or "
"argument type missing", func_name);
retval = -1;
goto bailout;
break; /* NOTREACHED */
}
break;
case DEVSTAT_ARG_LD:
destld = (long double *)va_arg(ap, long double *);
if (destld == NULL) {
snprintf(devstat_errbuf, sizeof(devstat_errbuf),
"%s: argument type not long double * "
"or argument type missing", func_name);
retval = -1;
goto bailout;
break; /* NOTREACHED */
}
break;
case DEVSTAT_ARG_SKIP:
destld = (long double *)va_arg(ap, long double *);
break;
default:
snprintf(devstat_errbuf, sizeof(devstat_errbuf),
"%s: unknown argument type %d", func_name,
devstat_arg_list[metric].argtype);
retval = -1;
goto bailout;
break; /* NOTREACHED */
}
if (devstat_arg_list[metric].argtype == DEVSTAT_ARG_SKIP)
continue;
switch (metric) {
case DSM_TOTAL_BYTES:
*destu64 = totalbytes;

View File

@ -74,6 +74,7 @@ typedef enum {
DSM_MS_PER_TRANSACTION,
DSM_MS_PER_TRANSACTION_READ,
DSM_MS_PER_TRANSACTION_WRITE,
DSM_SKIP,
DSM_MAX
} devstat_metric;