#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
#define TEXT_DOMAIN "SYS_TEST"
#endif
#define addrof(s) ((char **)&(s))
#define PRINTABLE(i) ((lf->plf_ffs[(i)].pff_prt & D_FIELD) || \
(lf->plf_ffs[(i)].pff_prt & X_FIELD))
typedef int (* formatter) (char *, int, int, poolstat_field_format_t *, char *);
static uint_t timestamp_fmt = NODATE;
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 *);
static statistic_bag_t pool_sbag_s;
static statistic_bag_t pset_sbag_s;
static statistic_bag_t *pool_sbag = &pool_sbag_s;
static statistic_bag_t *pset_sbag = &pset_sbag_s;
static poolstat_field_format_t pset_ffs[] = {
{ DX_FIELD, "id", "id", LL, 3, 1, addrof(pool_sbag),
offsetof(statistic_bag_t, sb_sysid),
(formatter)default_f },
{ DX_FIELD, "pool", "pool", STR, 20, 14, addrof(pool_sbag),
offsetof(statistic_bag_t, sb_name),
(formatter)default_f },
{ DX_FIELD, "type", "type", STR, 4, 5, addrof(pset_sbag),
offsetof(statistic_bag_t, sb_type),
(formatter)default_f },
{ D_FIELD, "rid", "rid", LL, 3, 1, addrof(pset_sbag_s.bag),
offsetof(pset_statistic_bag_t, pset_sb_sysid),
(formatter)default_f },
{ DX_FIELD, "rset", "rset", STR, 20, 14, addrof(pset_sbag),
offsetof(statistic_bag_t, sb_name),
(formatter)default_f },
{ DX_FIELD, "min", "min", ULL, 4, 1, addrof(pset_sbag_s.bag),
offsetof(pset_statistic_bag_t, pset_sb_min),
(formatter)bigno_f },
{ DX_FIELD, "max", "max", ULL, 4, 1, addrof(pset_sbag_s.bag),
offsetof(pset_statistic_bag_t, pset_sb_max),
(formatter)bigno_f },
{ DX_FIELD, "size", "size", ULL, 4, 1, addrof(pset_sbag_s.bag),
offsetof(pset_statistic_bag_t, pset_sb_size),
(formatter)default_f },
{ DX_FIELD, "used", "used", FL, 4, -1, addrof(pset_sbag_s.bag),
offsetof(pset_statistic_bag_t, pset_sb_used),
(formatter)used_stat_f },
{ DX_FIELD, "load", "load", FL, 4, -1, addrof(pset_sbag_s.bag),
offsetof(pset_statistic_bag_t, pset_sb_load),
(formatter)default_f }
};
static poolstat_field_format_t pool_ffs[] = {
{ D_FIELD, "id", "id", LL, 3, 1, addrof(pool_sbag),
offsetof(statistic_bag_t, sb_sysid),
(formatter)default_f },
{ D_FIELD, "pool", "pool", STR, 20, 13, addrof(pool_sbag),
offsetof(statistic_bag_t, sb_name),
(formatter)default_f },
{ D_FIELD, "p_size", "size", ULL, 4, 1, addrof(pset_sbag_s.bag),
offsetof(pset_statistic_bag_t, pset_sb_size),
(formatter)default_f },
{ D_FIELD, "p_used", "used", FL, 4, -1, addrof(pset_sbag_s.bag),
offsetof(pset_statistic_bag_t, pset_sb_used),
(formatter)default_f },
{ D_FIELD, "p_load", "load", FL, 4, -1, addrof(pset_sbag_s.bag),
offsetof(pset_statistic_bag_t, pset_sb_load),
(formatter)default_f },
};
static poolstat_line_format_t pool_lf;
static poolstat_line_format_t pset_lf;
static poolstat_list_element_t *pnames;
static poolstat_list_element_t *rtypes;
static pool_conf_t *conf;
static int rflag;
static int pflag;
static int oflag;
static int interval = 0;
static long count = 1;
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 *);
static void sa_update(statistic_bag_t *, int);
static void prt_pool_stats(poolstat_list_element_t *);
static void usage(void) __NORETURN;
static void
usage(void)
{
(void) fprintf(stderr, gettext(
"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"));
(void) exit(E_USAGE);
}
static int
Atoi(char *p, int *errp)
{
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
main(int argc, char *argv[])
{
int c;
int error = 0;
(void) getpname(argv[0]);
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
pset_sbag_s.sb_type = PSET_TYPE_NAME;
pset_sbag_s.bag = ZALLOC(sizeof (pset_statistic_bag_t));
pool_sbag_s.sb_type = POOL_TYPE_NAME;
pset_lf.plf_ffs = pset_ffs;
pset_lf.plf_ff_len = sizeof (pset_ffs) /
sizeof (poolstat_field_format_t);
pool_lf.plf_ffs = pool_ffs;
pool_lf.plf_ff_len = sizeof (pool_ffs) /
sizeof (poolstat_field_format_t);
(void) setvbuf(stdout, NULL, _IOLBF, 0);
while ((c = getopt(argc, argv, ":p:r:o:T:")) != EOF) {
switch (c) {
case 'p':
pflag++;
pnames = create_args_list(optarg, pnames,
" \t");
break;
case 'r': {
rflag++;
rtypes = create_args_list(optarg, rtypes,
" \t,");
break;
}
case 'o': {
oflag++;
if (create_prt_sequence_list(optarg, &pset_lf) == NULL)
usage();
break;
}
case 'T':
if (optarg) {
if (*optarg == 'u')
timestamp_fmt = UDATE;
else if (*optarg == 'd')
timestamp_fmt = DDATE;
else
usage();
} else {
usage();
}
break;
case ':': {
(void) fprintf(stderr,
gettext(ERR_OPTION_ARGS), optopt);
usage();
}
default:
(void) fprintf(stderr, gettext(ERR_OPTION), optopt);
usage();
}
}
if (argc > optind) {
if ((interval = Atoi(argv[optind++], &error)) < 1 || error != 0)
usage();
count = -1;
}
if (argc > optind) {
if ((count = Atoi(argv[optind++], &error)) < 1 || error != 0)
usage();
}
if (argc > optind)
usage();
if (oflag && !rflag)
usage();
if (!oflag) {
(void) create_prt_sequence_list(NULL, &pool_lf);
(void) create_prt_sequence_list(NULL, &pset_lf);
}
if (rtypes == NULL || strcmp(rtypes->ple_obj, "all") == 0) {
FREE(rtypes);
rtypes = create_args_list("pset", NULL, " \t,");
}
if ((conf = pool_conf_alloc()) == NULL)
die(gettext(ERR_NOMEM));
if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY)
!= PO_SUCCESS)
die(gettext(ERR_OPEN_DYNAMIC), get_errstr());
sa_libpool_init(conf);
sa_kstat_init(NULL);
while (count-- != 0) {
sa_update(pool_sbag, SA_REFRESH);
if (timestamp_fmt != NODATE)
print_timestamp(timestamp_fmt);
if (pool_sbag->sb_changed & POU_POOL)
(void) printf(
"<<State change>>\n");
prt_pool_stats(pnames);
if (count != 0) {
(void) sleep(interval);
if (rflag)
(void) printf("\n");
}
}
return (E_PO_SUCCESS);
}
static poolstat_list_element_t *
create_args_list(char *arg, poolstat_list_element_t *le, const char *delim)
{
poolstat_list_element_t *head = le;
while (arg != NULL && *arg != '\0') {
char *name = arg;
arg = strpbrk(arg, delim);
if (arg != NULL) {
*arg++ = '\0';
}
if (le == NULL) {
NEW0(le);
head = le;
} else {
while (le->ple_next != NULL)
le = le->ple_next;
NEW0(le->ple_next);
le = le->ple_next;
}
le->ple_obj = (void *)name;
}
return (head);
}
static poolstat_list_element_t *
create_prt_sequence_list(char *arg, poolstat_line_format_t *lf)
{
if (arg == NULL) {
int i;
NEW0(lf->plf_prt_seq);
lf->plf_ffs[0].pff_prt |= PRINTABLE(0) ? PABLE_FIELD : 0;
lf->plf_last = lf->plf_prt_seq;
lf->plf_last->ple_obj = &(lf->plf_ffs[0]);
for (i = 1; i < lf->plf_ff_len; i++) {
lf->plf_ffs[i].pff_prt |=
PRINTABLE(i) ? PABLE_FIELD : 0;
NEW0(lf->plf_last->ple_next);
lf->plf_last = lf->plf_last->ple_next;
lf->plf_last->ple_obj = &(lf->plf_ffs[i]);
}
return (lf->plf_prt_seq);
}
while (arg != NULL && *arg != '\0') {
poolstat_field_format_t *ff;
int ffIdx;
char *name;
int n;
n = strspn(arg, " ,\t\r\v\f\n");
arg += n;
name = arg;
if (strlen(name) < 1)
break;
if ((arg = strpbrk(arg, " ,\t\r\v\f\n")) != NULL)
*arg++ = '\0';
for (ffIdx = 0; ffIdx < lf->plf_ff_len; ffIdx++) {
ff = lf->plf_ffs + ffIdx;
if (strcmp(ff->pff_name, name) == 0) {
ff->pff_prt |= PABLE_FIELD;
break;
}
}
if (ffIdx == lf->plf_ff_len) {
(void) fprintf(stderr, gettext(ERR_UNSUPP_STAT_FIELD),
name);
usage();
}
if (lf->plf_last == NULL) {
NEW0(lf->plf_prt_seq);
lf->plf_last = lf->plf_prt_seq;
} else {
NEW0(lf->plf_last->ple_next);
lf->plf_last = lf->plf_last->ple_next;
}
lf->plf_last->ple_obj = ff;
}
return (lf->plf_prt_seq);
}
static void
sa_update(statistic_bag_t *sbag, int flags)
{
sa_libpool_update(sbag, flags);
sa_kstat_update(sbag, flags);
}
static int
default_f(char *str, int pos, int left, poolstat_field_format_t *ff, char *data)
{
int used;
switch (ff->pff_type) {
case LL: {
int64_t v;
v = *((int64_t *)(void *)(data + ff->pff_offset));
used = snprintf(str + pos, left, "%*.*lld",
ff->pff_width, ff->pff_minwidth, v);
}
break;
case ULL: {
uint64_t v;
v = *((uint64_t *)(void *)(data + ff->pff_offset));
used = snprintf(str + pos, left, "%*.*llu",
ff->pff_width, ff->pff_minwidth, v);
};
break;
case FL: {
int pw = 0;
double v = *((double *)(void *)(data + ff->pff_offset));
if (v < 10) {
pw = ff->pff_width - 2;
} else if (v < 100) {
pw = ff->pff_width - 3;
} else if (v < 1000) {
pw = ff->pff_width - 4;
}
if (pw < 0)
pw = 0;
used = snprintf(str + pos, left, "%*.*f",
ff->pff_width, pw, v);
};
break;
case STR: {
char *v;
int sl;
v = *((char **)(void *)(data + ff->pff_offset));
sl = strlen(v);
if (sl > ff->pff_width) {
char *cp = v + ff->pff_width - 1;
if (ff->pff_width < 4)
die(gettext(ERR_STATS_FORMAT),
ff->pff_header);
*cp-- = 0;
*cp-- = '.';
*cp-- = '.';
*cp-- = '.';
}
used = snprintf(str + pos, left, "%-*s", ff->pff_width,
v);
}
break;
}
return (used);
}
static int
bigno_f(char *str, int pos, int left, poolstat_field_format_t *ff, char *data)
{
uint64_t v;
char tag;
int pw = ff->pff_width - 4;
double pv;
int used;
v = *((uint64_t *)(void *)(data + ff->pff_offset));
pv = v;
if (v < 1000) {
pw = 0;
} else if (v < KILO * 10) {
pv = (double)v / KILO;
tag = 'K';
} else if (v < KILO * 100) {
pv = (double)v / KILO;
tag = 'K'; pw -= 1;
} else if (v < KILO * 1000) {
pv = (double)v / KILO;
tag = 'K'; pw -= 2;
} else if (v < MEGA * 10) {
pv = (double)v / MEGA;
tag = 'M';
} else if (v < MEGA * 100) {
pv = (double)v / MEGA;
tag = 'M'; pw -= 1;
} else if (v < MEGA * 1000) {
pv = (double)v / MEGA;
tag = 'M'; pw -= 2;
} else if (v < GIGA * 10) {
pv = (double)v / GIGA;
tag = 'G';
} else if (v < GIGA * 100) {
pv = (double)v / GIGA;
tag = 'G'; pw -= 1;
} else if (v < GIGA * 1000) {
pv = (double)v / GIGA;
tag = 'G'; pw -= 2;
} else if (v < TERA * 10) {
pv = (double)v / TERA;
tag = 'T';
} else if (v < TERA * 100) {
pv = (double)v / TERA;
tag = 'T'; pw -= 1;
} else if (v < TERA * 1000) {
pv = (double)v / TERA;
tag = 'T'; pw -= 2;
} else if (v < PETA * 10) {
pv = (double)v / PETA;
tag = 'P';
} else if (v < PETA * 100) {
pv = (double)v / PETA;
tag = 'P'; pw -= 1;
} else if (v < PETA * 1000) {
pv = (double)v / PETA;
tag = 'P'; pw -= 2;
} else if (v < EXA * 10) {
pv = (double)v / EXA;
tag = 'E';
} else if (v < EXA * 100) {
pv = (double)v / EXA;
tag = 'E'; pw -= 1;
} else {
pv = (double)v / EXA;
tag = 'E'; pw -= 2;
}
if (pw < 0)
pw = 0;
if (v < 1000)
used = snprintf(str + pos, left, "%*.*f",
ff->pff_width, pw, pv);
else
used = snprintf(str + pos, left, "%*.*f%c",
ff->pff_width - 1, pw, pv, tag);
return (used);
}
static int
used_stat_f(char *str, int pos, int left, poolstat_field_format_t *ff,
char *data)
{
int pw = 0;
double v = *((double *)(void *)(data + ff->pff_offset));
int used;
if (pool_sbag->sb_changed & POU_POOL) {
used = snprintf(str + pos, left, "%*c", ff->pff_width, '-');
} else {
if (v < 10) {
pw = ff->pff_width - 2;
} else if (v < 100) {
pw = ff->pff_width - 3;
} else if (v < 1000) {
pw = ff->pff_width - 4;
}
if (pw < 0)
pw = 0;
used = snprintf(str + pos, left, "%*.*f",
ff->pff_width, pw, v);
}
return (used);
}
static int
header_f(char *str, int pos, int left, poolstat_field_format_t *ff, char *data)
{
int used = 0;
if (ff->pff_type == STR)
used = snprintf(str + pos, left, "%-*s",
ff->pff_width, ff->pff_header);
else
used = snprintf(str + pos, left, "%*s",
ff->pff_width, ff->pff_header);
return (used);
}
static void
prt_stat_line(poolstat_line_format_t *lf)
{
poolstat_list_element_t *le;
char *line;
int pos = 0;
int len = MAXLINE;
int left = len;
line = ZALLOC(len);
for (le = lf->plf_prt_seq; le; le = le->ple_next) {
int used;
poolstat_field_format_t *ff =
(poolstat_field_format_t *)le->ple_obj;
if (ff->pff_prt & PABLE_FIELD) {
if (((used = ff->pff_format(line, pos, left, ff,
*ff->pff_data_ptr)) + 1) >= left) {
len += used + MAXLINE;
left += used + MAXLINE;
line = REALLOC(line, len);
if (((used = ff->pff_format(line, pos, left, ff,
*ff->pff_data_ptr)) + 1) >= left)
die(gettext(ERR_STATS_FORMAT), line);
}
left -= used;
pos += used;
if (le->ple_next != NULL) {
line[pos++] = ' ';
left--;
}
}
}
(void) printf("%s\n", line);
FREE(line);
}
static void
prt_stat_hd(const char *type)
{
poolstat_line_format_t *lf;
poolstat_list_element_t *le;
char *line;
int pos = 0;
int len = MAXLINE;
int left = len;
if (strcmp(type, POOL_TYPE_NAME) == 0) {
(void) printf("%*s\n", 19 + 15, "pset");
lf = &pool_lf;
} else if (strcmp(type, PSET_TYPE_NAME) == 0) {
lf = &pset_lf;
} else {
die(gettext(ERR_UNSUPP_RTYPE), type);
}
line = ZALLOC(len);
for (le = lf->plf_prt_seq; le; le = le->ple_next) {
int used;
poolstat_field_format_t *ff =
(poolstat_field_format_t *)le->ple_obj;
if (ff->pff_prt& PABLE_FIELD) {
if (((used = header_f(line, pos, left, ff, NULL)) + 1)
>= left) {
len += used + MAXLINE;
left += used + MAXLINE;
line = REALLOC(line, len);
if (((used = header_f(line, pos, left, ff,
NULL)) + 1) >= left)
die(gettext(ERR_STATS_FORMAT), line);
}
left -= used;
pos += used;
if (le->ple_next != NULL) {
line[pos++] = ' ';
left--;
}
}
}
pos = 0;
while (*(line + pos) != '\n') {
if (!isspace(*(line + pos))) {
(void) printf("%s\n", line);
break;
}
pos++;
}
FREE(line);
}
static pool_value_t *
create_pool_value(const char *name)
{
pool_value_t *pval;
if ((pval = pool_value_alloc()) == NULL) {
return (NULL);
}
if (pool_value_set_name(pval, name) != PO_SUCCESS) {
pool_value_free(pval);
return (NULL);
}
return (pval);
}
static pool_resource_t **
get_resources(const char *pool_name, const char *rtype, uint_t *nelem)
{
pool_resource_t **resources = NULL;
pool_value_t *pvals[] = { NULL, NULL, NULL};
pool_value_t *pv_sys_id;
pool_value_t *pv_name;
char *name_prop;
if (strcmp(rtype, PSET_TYPE_NAME) == 0) {
if ((pv_sys_id = create_pool_value(PSET_SYSID)) == NULL)
goto on_error;
name_prop = PSET_NAME;
} else {
die(gettext(ERR_UNSUPP_RTYPE), rtype);
}
if ((pvals[0] = create_pool_value("type")) == NULL)
goto on_error;
if ((pool_value_set_string(pvals[0], rtype)) == -1)
goto on_error;
if ((pv_name = create_pool_value(name_prop)) == NULL)
goto on_error;
if (pool_name != NULL) {
pool_t *pool;
if ((pool = pool_get_pool(conf, pool_name)) == NULL)
die(gettext(ERR_STATS_POOL_N), pool_name);
if ((resources = pool_query_pool_resources(
conf, pool, nelem, pvals)) == NULL)
goto on_error;
} else {
if ((resources =
pool_query_resources(conf, nelem, pvals)) == NULL)
goto on_error;
}
if (pv_name != NULL)
pool_value_free(pv_name);
if (pv_sys_id != NULL)
pool_value_free(pv_sys_id);
if (pvals[0] != NULL)
pool_value_free(pvals[0]);
return (resources);
on_error:
die(gettext(ERR_STATS_RES), get_errstr());
}
static void
prt_resource_stats_by_type(pool_resource_t **resources, const char *rtype)
{
int i;
pool_elem_t *elem;
pool_value_t *pv_name;
char *name_prop;
poolstat_line_format_t *lf;
statistic_bag_t *sbag;
if (strcmp(rtype, PSET_TYPE_NAME) == 0) {
name_prop = PSET_NAME;
lf = &pset_lf;
sbag = pset_sbag;
} else {
die(gettext(ERR_UNSUPP_RTYPE), rtype);
}
if ((pv_name = create_pool_value(name_prop)) == NULL)
goto on_error;
for (i = 0; resources[i] != NULL; i++) {
if ((elem = pool_resource_to_elem(conf, resources[i])) == NULL)
goto on_error;
if (pool_get_property(conf, elem, name_prop, pv_name) == -1)
goto on_error;
if (pool_value_get_string(pv_name, &sbag->sb_name) == -1)
goto on_error;
sa_update(sbag, 0);
prt_stat_line(lf);
}
if (pv_name != NULL)
pool_value_free(pv_name);
return;
on_error:
die(gettext(ERR_STATS_RES), get_errstr());
}
static void
update_resource_stats(pool_resource_t *resource, const char *rtype)
{
pool_elem_t *elem;
pool_value_t *pv_name;
char *name_prop;
statistic_bag_t *sbag;
if (strcmp(rtype, PSET_TYPE_NAME) == 0) {
name_prop = PSET_NAME;
sbag = pset_sbag;
} else {
die(gettext(ERR_UNSUPP_RTYPE), rtype);
}
if ((pv_name = create_pool_value(name_prop)) == NULL)
goto on_error;
if ((elem = pool_resource_to_elem(conf, resource)) == NULL)
goto on_error;
if (pool_get_property(conf, elem, name_prop, pv_name) == -1)
goto on_error;
if (pool_value_get_string(pv_name, &sbag->sb_name) == -1)
goto on_error;
sa_update(sbag, 0);
if (pv_name != NULL)
pool_value_free(pv_name);
return;
on_error:
die(gettext(ERR_STATS_RES), get_errstr());
}
static void
prt_pool_stats(poolstat_list_element_t *pn)
{
uint_t nelem;
pool_elem_t *elem;
int i;
int error;
pool_t **pools = NULL;
pool_value_t *pvals[] = { NULL, NULL };
pool_value_t *pv_name = NULL;
pool_value_t *pv_sys_id = NULL;
statistic_bag_t *sbag = pool_sbag;
poolstat_list_element_t *rtype;
pool_resource_t **resources;
if ((pv_sys_id = create_pool_value(POOL_SYSID)) == NULL)
goto on_error;
if ((pv_name = create_pool_value(POOL_NAME)) == NULL)
goto on_error;
if (pn == NULL) {
if ((pools = pool_query_pools(conf, &nelem, NULL)) == NULL)
goto on_error;
} else {
poolstat_list_element_t *poolid;
for (poolid = pn, i = 1; poolid; poolid = poolid->ple_next)
i++;
pools = ZALLOC(sizeof (pool_t *) * (i + 1));
for (poolid = pn, i = 0; poolid;
poolid = poolid->ple_next, i++) {
pool_t **pool;
int64_t sysid = Atoi(poolid->ple_obj, &error);
if (error == 0) {
pool_value_set_int64(pv_sys_id, sysid);
pvals[0] = pv_sys_id;
pool = pool_query_pools(conf, &nelem, pvals);
} else {
if (pool_value_set_string(pv_name,
poolid->ple_obj) == -1)
die(gettext(ERR_NOMEM));
pvals[0] = pv_name;
pool = pool_query_pools(conf, &nelem, pvals);
}
if (pool == NULL)
die(gettext(ERR_STATS_POOL_N), poolid->ple_obj);
pools[i] = pool[0];
FREE(pool);
}
}
if (!rflag) {
prt_stat_hd(POOL_TYPE_NAME);
for (i = 0; pools[i] != NULL; i++) {
elem = pool_to_elem(conf, pools[i]);
if (pool_get_property(conf, elem, POOL_NAME, pv_name)
== -1)
goto on_error;
if (pool_value_get_string(pv_name, &sbag->sb_name) != 0)
goto on_error;
if (pool_get_property(
conf, elem, "pool.sys_id", pv_sys_id) == -1)
goto on_error;
if (pool_value_get_int64(
pv_sys_id, &sbag->sb_sysid) != 0)
goto on_error;
for (rtype = rtypes; rtype; rtype = rtype->ple_next) {
resources = get_resources(
sbag->sb_name, rtype->ple_obj, &nelem);
update_resource_stats(*resources,
rtype->ple_obj);
FREE(resources);
}
prt_stat_line(&pool_lf);
}
} else {
for (rtype = rtypes; rtype; rtype = rtype->ple_next) {
prt_stat_hd(rtype->ple_obj);
for (i = 0; pools[i] != NULL; i++) {
elem = pool_to_elem(conf, pools[i]);
if (pool_get_property(
conf, elem, POOL_NAME, pv_name) == -1)
goto on_error;
if (pool_value_get_string(
pv_name, &sbag->sb_name) != 0)
goto on_error;
if (pool_get_property(
conf, elem, POOL_SYSID, pv_sys_id) == -1)
goto on_error;
if (pool_value_get_int64(
pv_sys_id, &sbag->sb_sysid) != 0)
goto on_error;
resources = get_resources(
sbag->sb_name, rtype->ple_obj, &nelem);
if (resources == NULL)
continue;
update_resource_stats(
*resources, rtype->ple_obj);
prt_resource_stats_by_type(resources,
rtype->ple_obj);
FREE(resources);
}
}
}
FREE(pools);
if (pv_name != NULL)
pool_value_free(pv_name);
if (pv_sys_id != NULL)
pool_value_free(pv_sys_id);
return;
on_error:
die(gettext(ERR_STATS_POOL), get_errstr());
}