/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* poolstat - report active pool statistics
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <unistd.h>
#include <locale.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>
#include <stddef.h>
#include <pool.h>
#include "utils.h"
#include "poolstat.h"
#include "poolstat_utils.h"
#include "statcommon.h"
#ifndef TEXT_DOMAIN
#endif
#define addrof(s) ((char **)&(s))
/* verify if a field is printable in respect of the current option flags */
/* available field formatters */
static int default_f(char *, int, int, poolstat_field_format_t *, char *);
static int bigno_f(char *, int, int, poolstat_field_format_t *, char *);
static int used_stat_f(char *, int, int, poolstat_field_format_t *, char *);
static int header_f(char *, int, int, poolstat_field_format_t *, char *);
/* statistics bags used to collect data from various provider */
/* formatter objects for pset, defined in a default printing sequence */
/* prt flags,name,header,type,width,minwidth,offset,formatter */
(formatter)used_stat_f },
};
/* formatter objects for pool, defined in a default printing sequence */
/* prt flags,name,header,type,width,minwidth,offset,formatter */
};
/* lists with formatter objects, one for each statistics field */
/* name of pools to be shown */
/*
* type of resources to be shown, currently we only have one type 'pset'
* but, poolstat can be extended to handle new upcoming resource types.
*/
/* a handle to the pool configuration */
/* option flags */
static int rflag;
static int pflag;
static int oflag;
/* operands */
/* data structure handlers */
static poolstat_list_element_t *
create_prt_sequence_list(char *, poolstat_line_format_t *);
static poolstat_list_element_t *
create_args_list(char *, poolstat_list_element_t *, const char *);
/* statistics update function */
static void sa_update(statistic_bag_t *, int);
/* statistics printing function */
static void prt_pool_stats(poolstat_list_element_t *);
static void
usage(void)
{
"Usage:\n"
"poolstat [-p pool-list] [-r rset-list] [-T d|u] [interval [count]]\n"
"poolstat [-p pool-list] [-o format -r rset-list] [-T d|u] [interval [count]]\n"
" \'pool-list\' is a space-separated list of pool IDs or names\n"
" \'rset-list\' is \'all\' or \'pset\'\n"
" \'format\' for all resource types is one or more of:\n"
"\tid pool type rid rset min max size used load\n"));
}
static int
{
int i;
char *q;
errno = 0;
i = strtol(p, &q, 10);
if (errno != 0 || q == p || *q != '\0')
*errp = -1;
else
*errp = 0;
return (i);
}
int
{
char c;
int error = 0;
(void) textdomain(TEXT_DOMAIN);
/* pset_sbag_s is used to collect pset statistics */
sizeof (poolstat_field_format_t);
sizeof (poolstat_field_format_t);
/* Don't let buffering interfere with piped output. */
switch (c) {
case 'p': /* pool name specification */
pflag++;
" \t");
break;
case 'r': { /* resource type */
rflag++;
" \t,");
break;
}
case 'o': { /* format specification */
oflag++;
usage();
break;
}
case 'T':
if (optarg) {
if (*optarg == 'u')
else if (*optarg == 'd')
else
usage();
} else {
usage();
}
break;
case ':': {
usage();
/*NOTREACHED*/
}
default:
usage();
/*NOTREACHED*/
}
}
/* get operands */
usage();
count = -1;
}
usage();
}
usage();
/* check options */
usage();
/* global initializations */
if (!oflag) {
/* create the default print sequences */
}
/* crate a default resource list */
}
!= PO_SUCCESS)
/* initialize statistic adapters */
/* collect and print out statistics */
while (count-- != 0) {
if (timestamp_fmt != NODATE)
(void) printf(
"<<State change>>\n");
if (count != 0) {
if (rflag)
(void) printf("\n");
}
}
return (E_PO_SUCCESS);
}
/*
*/
static poolstat_list_element_t *
{
*arg++ = '\0';
}
/* create first element */
} else {
/* find last and append */
}
}
return (head);
}
/*
* Take the arguments to the -o option, and create a format field list in order
* specified by 'arg'.
* If 'arg' is NULL a list in a default printing order is created.
*/
static poolstat_list_element_t *
{
/*
* Create a default print sequence. It is the sequence defined
* statically in the format list. At the same time mark the fields
* printable according to the current option settings.
*/
int i;
PRINTABLE(i) ? PABLE_FIELD : 0;
}
return (lf->plf_prt_seq);
}
int n; /* no. of chars to strip */
arg += n; /* strip multiples separator */
break;
*arg++ = '\0';
/* search for a named format field */
break;
}
}
/* if the name wasn't found */
name);
usage();
}
/* create first print handle */
} else {
}
}
return (lf->plf_prt_seq);
}
/* update the statistic data by adapters */
static void
{
}
/*
* Format one statistic field and put it into the 'str' buffer. 'ff' contains
* the field formatting parameters. Return the number of used bytes.
*/
static int
{
int used;
case LL: {
int64_t v;
}
break;
case ULL: {
uint64_t v;
};
break;
case FL: {
int pw = 0;
if (v < 10) {
} else if (v < 100) {
} else if (v < 1000) {
}
if (pw < 0)
pw = 0;
};
break;
case STR: {
char *v;
int sl;
/* truncate if it doesn't fit */
ff->pff_header);
*cp-- = 0;
*cp-- = '.';
*cp-- = '.';
*cp-- = '.';
}
v);
}
break;
}
return (used);
}
/* format big numbers */
static int
{
uint64_t v;
char tag;
double pv;
int used;
/*
* the max value can be ULONG_MAX, which is formatted as:
* E P T G M K
* 18 446 744 073 709 551 615
* As a result ULONG_MAX is displayed as 18E
*/
pv = v;
if (v < 1000) {
pw = 0;
} else if (v < KILO * 10) {
tag = 'K';
} else if (v < KILO * 100) {
} else if (v < KILO * 1000) {
} else if (v < MEGA * 10) {
tag = 'M';
} else if (v < MEGA * 100) {
} else if (v < MEGA * 1000) {
} else if (v < GIGA * 10) {
tag = 'G';
} else if (v < GIGA * 100) {
} else if (v < GIGA * 1000) {
} else if (v < TERA * 10) {
tag = 'T';
} else if (v < TERA * 100) {
} else if (v < TERA * 1000) {
} else if (v < PETA * 10) {
tag = 'P';
} else if (v < PETA * 100) {
} else if (v < PETA * 1000) {
} else if (v < EXA * 10) {
tag = 'E';
} else if (v < EXA * 100) {
} else {
}
if (pw < 0)
pw = 0;
if (v < 1000)
else
return (used);
}
/* format usage statistic, if configuration has changed print '-'. */
static int
char *data)
{
int pw = 0;
int used;
} else {
if (v < 10) {
} else if (v < 100) {
} else if (v < 1000) {
}
if (pw < 0)
pw = 0;
}
return (used);
}
/*
* Format one header field and put it into the 'str' buffer.
*/
/*ARGSUSED*/
static int
{
int used = 0;
/* strings are left justified */
else
return (used);
}
/*
* Print one statistic line according to the definitions in 'lf'.
*/
static void
{
char *line;
int used;
/* if the filed is marked to be printed */
/* if field doesn't fit allocate new space */
}
/* separate columns with a space */
left--;
}
}
}
}
/*
* Print a statistics header line for a given resource type.
*/
static void
{
char *line;
/* pool format needs an extra header */
} else {
}
/* if the filed is marked to be printed */
>= left) {
/* if field doesn't fit allocate new space */
}
/* separate columns with a space */
left--;
}
}
}
/* only header line with non space characters should be printed */
pos = 0;
break;
}
pos++;
}
}
/*
* Create a pool value instance and set its name to 'name'.
*/
static pool_value_t *
{
return (NULL);
}
return (NULL);
}
return (pval);
}
/*
* Find all resources of type 'rtype'.
* If 'pool_name' is defined find all resources bound to this pool.
*/
static pool_resource_t **
{
goto on_error;
} else {
}
goto on_error;
goto on_error;
goto on_error;
/* collect resources associated to 'pool_name' */
if ((resources = pool_query_pool_resources(
goto on_error;
} else {
/* collect all resources */
if ((resources =
goto on_error;
}
pool_value_free(pvals[0]);
return (resources);
/*NOTREACHED*/
}
/*
* Print statistics for all resources of type 'rtype' passed in 'resources'.
*/
static void
{
int i;
char *name_prop;
} else {
}
goto on_error;
/* collect and print statistics for the given resources */
goto on_error;
goto on_error;
goto on_error;
}
return;
}
/*
* Update statistics for all resources of type 'rtype' pased in 'resources'.
*/
static void
{
} else {
}
goto on_error;
goto on_error;
goto on_error;
goto on_error;
return;
}
/*
* For each pool in the configuration print statistics of associated resources.
* If the pool name list 'pn' is defined, only print resources of pools
* specified in the list. The list can specify the pool name or its system id.
*/
static void
{
int i;
int error;
goto on_error;
goto on_error;
/* collect all pools */
goto on_error;
} else {
/*
* collect pools specified in the 'pn' list.
* 'poolid' the pool identifier can be a pool name or sys_id.
*/
i++;
if (error == 0) {
/* the pool is identified by sys_id */
} else {
}
}
}
/* print statistic for all pools found */
if (!rflag) {
/* print the common resource header */
/* print statistics for the resources bound to the pools */
== -1)
goto on_error;
goto on_error;
if (pool_get_property(
goto on_error;
if (pool_value_get_int64(
goto on_error;
}
}
} else {
/* print statistic for all resource types defined in rtypes */
if (pool_get_property(
goto on_error;
goto on_error;
if (pool_get_property(
goto on_error;
if (pool_value_get_int64(
goto on_error;
continue;
}
}
}
return;
}