4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * poolstat - report active pool statistics
43 #include "poolstat_utils.h"
44 #include "statcommon.h"
47 #define TEXT_DOMAIN "SYS_TEST"
50 #define addrof(s) ((char **)&(s))
52 /* verify if a field is printable in respect of the current option flags */
53 #define PRINTABLE(i) ((lf->plf_ffs[(i)].pff_prt & D_FIELD) || \
54 (lf->plf_ffs[(i)].pff_prt & X_FIELD))
56 typedef int (* formatter
) (char *, int, int, poolstat_field_format_t
*, char *);
58 static uint_t timestamp_fmt
= NODATE
;
60 /* available field formatters */
61 static int default_f(char *, int, int, poolstat_field_format_t
*, char *);
62 static int bigno_f(char *, int, int, poolstat_field_format_t
*, char *);
63 static int used_stat_f(char *, int, int, poolstat_field_format_t
*, char *);
64 static int header_f(char *, int, int, poolstat_field_format_t
*, char *);
66 /* statistics bags used to collect data from various provider */
67 static statistic_bag_t pool_sbag_s
;
68 static statistic_bag_t pset_sbag_s
;
69 static statistic_bag_t
*pool_sbag
= &pool_sbag_s
;
70 static statistic_bag_t
*pset_sbag
= &pset_sbag_s
;
72 /* formatter objects for pset, defined in a default printing sequence */
73 static poolstat_field_format_t pset_ffs
[] = {
74 /* prt flags,name,header,type,width,minwidth,offset,formatter */
75 { DX_FIELD
, "id", "id", LL
, 3, 1, addrof(pool_sbag
),
76 offsetof(statistic_bag_t
, sb_sysid
),
77 (formatter
)default_f
},
78 { DX_FIELD
, "pool", "pool", STR
, 20, 14, addrof(pool_sbag
),
79 offsetof(statistic_bag_t
, sb_name
),
80 (formatter
)default_f
},
81 { DX_FIELD
, "type", "type", STR
, 4, 5, addrof(pset_sbag
),
82 offsetof(statistic_bag_t
, sb_type
),
83 (formatter
)default_f
},
84 { D_FIELD
, "rid", "rid", LL
, 3, 1, addrof(pset_sbag_s
.bag
),
85 offsetof(pset_statistic_bag_t
, pset_sb_sysid
),
86 (formatter
)default_f
},
87 { DX_FIELD
, "rset", "rset", STR
, 20, 14, addrof(pset_sbag
),
88 offsetof(statistic_bag_t
, sb_name
),
89 (formatter
)default_f
},
90 { DX_FIELD
, "min", "min", ULL
, 4, 1, addrof(pset_sbag_s
.bag
),
91 offsetof(pset_statistic_bag_t
, pset_sb_min
),
93 { DX_FIELD
, "max", "max", ULL
, 4, 1, addrof(pset_sbag_s
.bag
),
94 offsetof(pset_statistic_bag_t
, pset_sb_max
),
96 { DX_FIELD
, "size", "size", ULL
, 4, 1, addrof(pset_sbag_s
.bag
),
97 offsetof(pset_statistic_bag_t
, pset_sb_size
),
98 (formatter
)default_f
},
99 { DX_FIELD
, "used", "used", FL
, 4, -1, addrof(pset_sbag_s
.bag
),
100 offsetof(pset_statistic_bag_t
, pset_sb_used
),
101 (formatter
)used_stat_f
},
102 { DX_FIELD
, "load", "load", FL
, 4, -1, addrof(pset_sbag_s
.bag
),
103 offsetof(pset_statistic_bag_t
, pset_sb_load
),
104 (formatter
)default_f
}
107 /* formatter objects for pool, defined in a default printing sequence */
108 static poolstat_field_format_t pool_ffs
[] = {
109 /* prt flags,name,header,type,width,minwidth,offset,formatter */
110 { D_FIELD
, "id", "id", LL
, 3, 1, addrof(pool_sbag
),
111 offsetof(statistic_bag_t
, sb_sysid
),
112 (formatter
)default_f
},
113 { D_FIELD
, "pool", "pool", STR
, 20, 13, addrof(pool_sbag
),
114 offsetof(statistic_bag_t
, sb_name
),
115 (formatter
)default_f
},
116 { D_FIELD
, "p_size", "size", ULL
, 4, 1, addrof(pset_sbag_s
.bag
),
117 offsetof(pset_statistic_bag_t
, pset_sb_size
),
118 (formatter
)default_f
},
119 { D_FIELD
, "p_used", "used", FL
, 4, -1, addrof(pset_sbag_s
.bag
),
120 offsetof(pset_statistic_bag_t
, pset_sb_used
),
121 (formatter
)default_f
},
122 { D_FIELD
, "p_load", "load", FL
, 4, -1, addrof(pset_sbag_s
.bag
),
123 offsetof(pset_statistic_bag_t
, pset_sb_load
),
124 (formatter
)default_f
},
127 /* lists with formatter objects, one for each statistics field */
128 static poolstat_line_format_t pool_lf
; /* formatting list in default mode */
129 static poolstat_line_format_t pset_lf
; /* formatting list for psets */
131 /* name of pools to be shown */
132 static poolstat_list_element_t
*pnames
;
134 * type of resources to be shown, currently we only have one type 'pset'
135 * but, poolstat can be extended to handle new upcoming resource types.
137 static poolstat_list_element_t
*rtypes
;
139 /* a handle to the pool configuration */
140 static pool_conf_t
*conf
;
148 static int interval
= 0; /* update interval */
149 static long count
= 1; /* one run */
151 /* data structure handlers */
152 static poolstat_list_element_t
*
153 create_prt_sequence_list(char *, poolstat_line_format_t
*);
154 static poolstat_list_element_t
*
155 create_args_list(char *, poolstat_list_element_t
*, const char *);
157 /* statistics update function */
158 static void sa_update(statistic_bag_t
*, int);
160 /* statistics printing function */
161 static void prt_pool_stats(poolstat_list_element_t
*);
163 static void usage(void) __NORETURN
;
168 (void) fprintf(stderr
, gettext(
170 "poolstat [-p pool-list] [-r rset-list] [-T d|u] [interval [count]]\n"
171 "poolstat [-p pool-list] [-o format -r rset-list] [-T d|u] [interval [count]]\n"
172 " \'pool-list\' is a space-separated list of pool IDs or names\n"
173 " \'rset-list\' is \'all\' or \'pset\'\n"
174 " \'format\' for all resource types is one or more of:\n"
175 "\tid pool type rid rset min max size used load\n"));
176 (void) exit(E_USAGE
);
180 Atoi(char *p
, int *errp
)
185 i
= strtol(p
, &q
, 10);
186 if (errno
!= 0 || q
== p
|| *q
!= '\0')
194 main(int argc
, char *argv
[])
199 (void) getpname(argv
[0]);
200 (void) setlocale(LC_ALL
, "");
201 (void) textdomain(TEXT_DOMAIN
);
203 /* pset_sbag_s is used to collect pset statistics */
204 pset_sbag_s
.sb_type
= PSET_TYPE_NAME
;
205 pset_sbag_s
.bag
= ZALLOC(sizeof (pset_statistic_bag_t
));
206 pool_sbag_s
.sb_type
= POOL_TYPE_NAME
;
208 pset_lf
.plf_ffs
= pset_ffs
;
209 pset_lf
.plf_ff_len
= sizeof (pset_ffs
) /
210 sizeof (poolstat_field_format_t
);
211 pool_lf
.plf_ffs
= pool_ffs
;
212 pool_lf
.plf_ff_len
= sizeof (pool_ffs
) /
213 sizeof (poolstat_field_format_t
);
215 /* Don't let buffering interfere with piped output. */
216 (void) setvbuf(stdout
, NULL
, _IOLBF
, 0);
218 while ((c
= getopt(argc
, argv
, ":p:r:o:T:")) != EOF
) {
220 case 'p': /* pool name specification */
222 pnames
= create_args_list(optarg
, pnames
,
225 case 'r': { /* resource type */
227 rtypes
= create_args_list(optarg
, rtypes
,
231 case 'o': { /* format specification */
233 if (create_prt_sequence_list(optarg
, &pset_lf
) == NULL
)
240 timestamp_fmt
= UDATE
;
241 else if (*optarg
== 'd')
242 timestamp_fmt
= DDATE
;
250 (void) fprintf(stderr
,
251 gettext(ERR_OPTION_ARGS
), optopt
);
256 (void) fprintf(stderr
, gettext(ERR_OPTION
), optopt
);
264 if ((interval
= Atoi(argv
[optind
++], &error
)) < 1 || error
!= 0)
269 if ((count
= Atoi(argv
[optind
++], &error
)) < 1 || error
!= 0)
272 /* check for extra options/operands */
280 /* global initializations */
282 /* create the default print sequences */
283 (void) create_prt_sequence_list(NULL
, &pool_lf
);
284 (void) create_prt_sequence_list(NULL
, &pset_lf
);
287 if (rtypes
== NULL
|| strcmp(rtypes
->ple_obj
, "all") == 0) {
288 /* crate a default resource list */
290 rtypes
= create_args_list("pset", NULL
, " \t,");
293 if ((conf
= pool_conf_alloc()) == NULL
)
294 die(gettext(ERR_NOMEM
));
295 if (pool_conf_open(conf
, pool_dynamic_location(), PO_RDONLY
)
297 die(gettext(ERR_OPEN_DYNAMIC
), get_errstr());
299 /* initialize statistic adapters */
300 sa_libpool_init(conf
);
303 /* collect and print out statistics */
304 while (count
-- != 0) {
305 sa_update(pool_sbag
, SA_REFRESH
);
306 if (timestamp_fmt
!= NODATE
)
307 print_timestamp(timestamp_fmt
);
308 if (pool_sbag
->sb_changed
& POU_POOL
)
310 "<<State change>>\n");
311 prt_pool_stats(pnames
);
313 (void) sleep(interval
);
319 return (E_PO_SUCCESS
);
323 * Take the arguments and create/append a string list to the 'le' list.
325 static poolstat_list_element_t
*
326 create_args_list(char *arg
, poolstat_list_element_t
*le
, const char *delim
)
328 poolstat_list_element_t
*head
= le
;
330 while (arg
!= NULL
&& *arg
!= '\0') {
332 arg
= strpbrk(arg
, delim
);
337 /* create first element */
341 /* find last and append */
342 while (le
->ple_next
!= NULL
)
347 le
->ple_obj
= (void *)name
;
354 * Take the arguments to the -o option, and create a format field list in order
355 * specified by 'arg'.
356 * If 'arg' is NULL a list in a default printing order is created.
358 static poolstat_list_element_t
*
359 create_prt_sequence_list(char *arg
, poolstat_line_format_t
*lf
)
362 * Create a default print sequence. It is the sequence defined
363 * statically in the format list. At the same time mark the fields
364 * printable according to the current option settings.
368 NEW0(lf
->plf_prt_seq
);
369 lf
->plf_ffs
[0].pff_prt
|= PRINTABLE(0) ? PABLE_FIELD
: 0;
370 lf
->plf_last
= lf
->plf_prt_seq
;
371 lf
->plf_last
->ple_obj
= &(lf
->plf_ffs
[0]);
372 for (i
= 1; i
< lf
->plf_ff_len
; i
++) {
373 lf
->plf_ffs
[i
].pff_prt
|=
374 PRINTABLE(i
) ? PABLE_FIELD
: 0;
375 NEW0(lf
->plf_last
->ple_next
);
376 lf
->plf_last
= lf
->plf_last
->ple_next
;
377 lf
->plf_last
->ple_obj
= &(lf
->plf_ffs
[i
]);
379 return (lf
->plf_prt_seq
);
382 while (arg
!= NULL
&& *arg
!= '\0') {
383 poolstat_field_format_t
*ff
; /* current format field */
384 int ffIdx
; /* format field index */
385 char *name
; /* name of field */
386 int n
; /* no. of chars to strip */
388 n
= strspn(arg
, " ,\t\r\v\f\n");
389 arg
+= n
; /* strip multiples separator */
392 if (strlen(name
) < 1)
395 if ((arg
= strpbrk(arg
, " ,\t\r\v\f\n")) != NULL
)
398 /* search for a named format field */
399 for (ffIdx
= 0; ffIdx
< lf
->plf_ff_len
; ffIdx
++) {
400 ff
= lf
->plf_ffs
+ ffIdx
;
401 if (strcmp(ff
->pff_name
, name
) == 0) {
402 ff
->pff_prt
|= PABLE_FIELD
;
406 /* if the name wasn't found */
407 if (ffIdx
== lf
->plf_ff_len
) {
408 (void) fprintf(stderr
, gettext(ERR_UNSUPP_STAT_FIELD
),
412 if (lf
->plf_last
== NULL
) {
413 /* create first print handle */
414 NEW0(lf
->plf_prt_seq
);
415 lf
->plf_last
= lf
->plf_prt_seq
;
417 NEW0(lf
->plf_last
->ple_next
);
418 lf
->plf_last
= lf
->plf_last
->ple_next
;
420 lf
->plf_last
->ple_obj
= ff
; /* refer to the format field */
423 return (lf
->plf_prt_seq
);
426 /* update the statistic data by adapters */
428 sa_update(statistic_bag_t
*sbag
, int flags
)
430 sa_libpool_update(sbag
, flags
);
431 sa_kstat_update(sbag
, flags
);
435 * Format one statistic field and put it into the 'str' buffer. 'ff' contains
436 * the field formatting parameters. Return the number of used bytes.
439 default_f(char *str
, int pos
, int left
, poolstat_field_format_t
*ff
, char *data
)
443 switch (ff
->pff_type
) {
446 v
= *((int64_t *)(void *)(data
+ ff
->pff_offset
));
447 used
= snprintf(str
+ pos
, left
, "%*.*lld",
448 ff
->pff_width
, ff
->pff_minwidth
, v
);
453 v
= *((uint64_t *)(void *)(data
+ ff
->pff_offset
));
454 used
= snprintf(str
+ pos
, left
, "%*.*llu",
455 ff
->pff_width
, ff
->pff_minwidth
, v
);
460 double v
= *((double *)(void *)(data
+ ff
->pff_offset
));
462 pw
= ff
->pff_width
- 2;
463 } else if (v
< 100) {
464 pw
= ff
->pff_width
- 3;
465 } else if (v
< 1000) {
466 pw
= ff
->pff_width
- 4;
470 used
= snprintf(str
+ pos
, left
, "%*.*f",
471 ff
->pff_width
, pw
, v
);
477 v
= *((char **)(void *)(data
+ ff
->pff_offset
));
479 /* truncate if it doesn't fit */
480 if (sl
> ff
->pff_width
) {
481 char *cp
= v
+ ff
->pff_width
- 1;
482 if (ff
->pff_width
< 4)
483 die(gettext(ERR_STATS_FORMAT
),
490 used
= snprintf(str
+ pos
, left
, "%-*s", ff
->pff_width
,
499 /* format big numbers */
501 bigno_f(char *str
, int pos
, int left
, poolstat_field_format_t
*ff
, char *data
)
505 int pw
= ff
->pff_width
- 4;
509 v
= *((uint64_t *)(void *)(data
+ ff
->pff_offset
));
511 * the max value can be ULONG_MAX, which is formatted as:
513 * 18 446 744 073 709 551 615
514 * As a result ULONG_MAX is displayed as 18E
519 } else if (v
< KILO
* 10) {
520 pv
= (double)v
/ KILO
;
522 } else if (v
< KILO
* 100) {
523 pv
= (double)v
/ KILO
;
525 } else if (v
< KILO
* 1000) {
526 pv
= (double)v
/ KILO
;
528 } else if (v
< MEGA
* 10) {
529 pv
= (double)v
/ MEGA
;
531 } else if (v
< MEGA
* 100) {
532 pv
= (double)v
/ MEGA
;
534 } else if (v
< MEGA
* 1000) {
535 pv
= (double)v
/ MEGA
;
537 } else if (v
< GIGA
* 10) {
538 pv
= (double)v
/ GIGA
;
540 } else if (v
< GIGA
* 100) {
541 pv
= (double)v
/ GIGA
;
543 } else if (v
< GIGA
* 1000) {
544 pv
= (double)v
/ GIGA
;
546 } else if (v
< TERA
* 10) {
547 pv
= (double)v
/ TERA
;
549 } else if (v
< TERA
* 100) {
550 pv
= (double)v
/ TERA
;
552 } else if (v
< TERA
* 1000) {
553 pv
= (double)v
/ TERA
;
555 } else if (v
< PETA
* 10) {
556 pv
= (double)v
/ PETA
;
558 } else if (v
< PETA
* 100) {
559 pv
= (double)v
/ PETA
;
561 } else if (v
< PETA
* 1000) {
562 pv
= (double)v
/ PETA
;
564 } else if (v
< EXA
* 10) {
565 pv
= (double)v
/ EXA
;
567 } else if (v
< EXA
* 100) {
568 pv
= (double)v
/ EXA
;
571 pv
= (double)v
/ EXA
;
577 used
= snprintf(str
+ pos
, left
, "%*.*f",
578 ff
->pff_width
, pw
, pv
);
580 used
= snprintf(str
+ pos
, left
, "%*.*f%c",
581 ff
->pff_width
- 1, pw
, pv
, tag
);
586 /* format usage statistic, if configuration has changed print '-'. */
588 used_stat_f(char *str
, int pos
, int left
, poolstat_field_format_t
*ff
,
592 double v
= *((double *)(void *)(data
+ ff
->pff_offset
));
595 if (pool_sbag
->sb_changed
& POU_POOL
) {
596 used
= snprintf(str
+ pos
, left
, "%*c", ff
->pff_width
, '-');
599 pw
= ff
->pff_width
- 2;
600 } else if (v
< 100) {
601 pw
= ff
->pff_width
- 3;
602 } else if (v
< 1000) {
603 pw
= ff
->pff_width
- 4;
607 used
= snprintf(str
+ pos
, left
, "%*.*f",
608 ff
->pff_width
, pw
, v
);
614 * Format one header field and put it into the 'str' buffer.
618 header_f(char *str
, int pos
, int left
, poolstat_field_format_t
*ff
, char *data
)
622 if (ff
->pff_type
== STR
)
623 /* strings are left justified */
624 used
= snprintf(str
+ pos
, left
, "%-*s",
625 ff
->pff_width
, ff
->pff_header
);
627 used
= snprintf(str
+ pos
, left
, "%*s",
628 ff
->pff_width
, ff
->pff_header
);
633 * Print one statistic line according to the definitions in 'lf'.
636 prt_stat_line(poolstat_line_format_t
*lf
)
638 poolstat_list_element_t
*le
; /* list element in the print sequence */
640 int pos
= 0; /* position in the printed line */
641 int len
= MAXLINE
; /* the length of the line */
642 int left
= len
; /* chars left to use in the line */
645 for (le
= lf
->plf_prt_seq
; le
; le
= le
->ple_next
) {
647 poolstat_field_format_t
*ff
=
648 (poolstat_field_format_t
*)le
->ple_obj
;
649 /* if the filed is marked to be printed */
650 if (ff
->pff_prt
& PABLE_FIELD
) {
651 if (((used
= ff
->pff_format(line
, pos
, left
, ff
,
652 *ff
->pff_data_ptr
)) + 1) >= left
) {
653 /* if field doesn't fit allocate new space */
654 len
+= used
+ MAXLINE
;
655 left
+= used
+ MAXLINE
;
656 line
= REALLOC(line
, len
);
657 if (((used
= ff
->pff_format(line
, pos
, left
, ff
,
658 *ff
->pff_data_ptr
)) + 1) >= left
)
659 die(gettext(ERR_STATS_FORMAT
), line
);
663 if (le
->ple_next
!= NULL
) {
664 /* separate columns with a space */
671 (void) printf("%s\n", line
);
676 * Print a statistics header line for a given resource type.
679 prt_stat_hd(const char *type
)
681 poolstat_line_format_t
*lf
; /* line format */
682 poolstat_list_element_t
*le
; /* list element in the print sequence */
684 int pos
= 0; /* position in the printed line */
685 int len
= MAXLINE
; /* the length of the line */
686 int left
= len
; /* chars left to use in the line */
688 if (strcmp(type
, POOL_TYPE_NAME
) == 0) {
689 /* pool format needs an extra header */
690 (void) printf("%*s\n", 19 + 15, "pset");
692 } else if (strcmp(type
, PSET_TYPE_NAME
) == 0) {
695 die(gettext(ERR_UNSUPP_RTYPE
), type
);
698 for (le
= lf
->plf_prt_seq
; le
; le
= le
->ple_next
) {
699 int used
; /* used chars in line */
700 poolstat_field_format_t
*ff
=
701 (poolstat_field_format_t
*)le
->ple_obj
;
702 /* if the filed is marked to be printed */
703 if (ff
->pff_prt
& PABLE_FIELD
) {
704 if (((used
= header_f(line
, pos
, left
, ff
, NULL
)) + 1)
706 /* if field doesn't fit allocate new space */
707 len
+= used
+ MAXLINE
;
708 left
+= used
+ MAXLINE
;
709 line
= REALLOC(line
, len
);
710 if (((used
= header_f(line
, pos
, left
, ff
,
712 die(gettext(ERR_STATS_FORMAT
), line
);
716 if (le
->ple_next
!= NULL
) {
717 /* separate columns with a space */
724 /* only header line with non space characters should be printed */
726 while (*(line
+ pos
) != '\n') {
727 if (!isspace(*(line
+ pos
))) {
728 (void) printf("%s\n", line
);
738 * Create a pool value instance and set its name to 'name'.
740 static pool_value_t
*
741 create_pool_value(const char *name
)
745 if ((pval
= pool_value_alloc()) == NULL
) {
748 if (pool_value_set_name(pval
, name
) != PO_SUCCESS
) {
749 pool_value_free(pval
);
757 * Find all resources of type 'rtype'.
758 * If 'pool_name' is defined find all resources bound to this pool.
760 static pool_resource_t
**
761 get_resources(const char *pool_name
, const char *rtype
, uint_t
*nelem
)
763 pool_resource_t
**resources
= NULL
;
764 pool_value_t
*pvals
[] = { NULL
, NULL
, NULL
};
765 pool_value_t
*pv_sys_id
;
766 pool_value_t
*pv_name
;
767 char *name_prop
; /* set name property */
769 if (strcmp(rtype
, PSET_TYPE_NAME
) == 0) {
770 if ((pv_sys_id
= create_pool_value(PSET_SYSID
)) == NULL
)
772 name_prop
= PSET_NAME
;
774 die(gettext(ERR_UNSUPP_RTYPE
), rtype
);
777 if ((pvals
[0] = create_pool_value("type")) == NULL
)
779 if ((pool_value_set_string(pvals
[0], rtype
)) == -1)
782 if ((pv_name
= create_pool_value(name_prop
)) == NULL
)
785 if (pool_name
!= NULL
) {
786 /* collect resources associated to 'pool_name' */
788 if ((pool
= pool_get_pool(conf
, pool_name
)) == NULL
)
789 die(gettext(ERR_STATS_POOL_N
), pool_name
);
790 if ((resources
= pool_query_pool_resources(
791 conf
, pool
, nelem
, pvals
)) == NULL
)
794 /* collect all resources */
796 pool_query_resources(conf
, nelem
, pvals
)) == NULL
)
801 pool_value_free(pv_name
);
802 if (pv_sys_id
!= NULL
)
803 pool_value_free(pv_sys_id
);
804 if (pvals
[0] != NULL
)
805 pool_value_free(pvals
[0]);
809 die(gettext(ERR_STATS_RES
), get_errstr());
814 * Print statistics for all resources of type 'rtype' passed in 'resources'.
817 prt_resource_stats_by_type(pool_resource_t
**resources
, const char *rtype
)
821 pool_value_t
*pv_name
;
824 poolstat_line_format_t
*lf
;
825 statistic_bag_t
*sbag
;
827 if (strcmp(rtype
, PSET_TYPE_NAME
) == 0) {
828 name_prop
= PSET_NAME
;
832 die(gettext(ERR_UNSUPP_RTYPE
), rtype
);
835 if ((pv_name
= create_pool_value(name_prop
)) == NULL
)
838 /* collect and print statistics for the given resources */
839 for (i
= 0; resources
[i
] != NULL
; i
++) {
840 if ((elem
= pool_resource_to_elem(conf
, resources
[i
])) == NULL
)
842 if (pool_get_property(conf
, elem
, name_prop
, pv_name
) == -1)
844 if (pool_value_get_string(pv_name
, &sbag
->sb_name
) == -1)
852 pool_value_free(pv_name
);
855 die(gettext(ERR_STATS_RES
), get_errstr());
859 * Update statistics for all resources of type 'rtype' pased in 'resources'.
862 update_resource_stats(pool_resource_t
*resource
, const char *rtype
)
865 pool_value_t
*pv_name
;
866 char *name_prop
; /* set name property */
868 statistic_bag_t
*sbag
;
870 if (strcmp(rtype
, PSET_TYPE_NAME
) == 0) {
871 name_prop
= PSET_NAME
;
874 die(gettext(ERR_UNSUPP_RTYPE
), rtype
);
877 if ((pv_name
= create_pool_value(name_prop
)) == NULL
)
880 if ((elem
= pool_resource_to_elem(conf
, resource
)) == NULL
)
882 if (pool_get_property(conf
, elem
, name_prop
, pv_name
) == -1)
884 if (pool_value_get_string(pv_name
, &sbag
->sb_name
) == -1)
889 pool_value_free(pv_name
);
893 die(gettext(ERR_STATS_RES
), get_errstr());
897 * For each pool in the configuration print statistics of associated resources.
898 * If the pool name list 'pn' is defined, only print resources of pools
899 * specified in the list. The list can specify the pool name or its system id.
902 prt_pool_stats(poolstat_list_element_t
*pn
)
908 pool_t
**pools
= NULL
;
909 pool_value_t
*pvals
[] = { NULL
, NULL
};
910 pool_value_t
*pv_name
= NULL
;
911 pool_value_t
*pv_sys_id
= NULL
;
912 statistic_bag_t
*sbag
= pool_sbag
;
913 poolstat_list_element_t
*rtype
;
914 pool_resource_t
**resources
;
916 if ((pv_sys_id
= create_pool_value(POOL_SYSID
)) == NULL
)
918 if ((pv_name
= create_pool_value(POOL_NAME
)) == NULL
)
922 /* collect all pools */
923 if ((pools
= pool_query_pools(conf
, &nelem
, NULL
)) == NULL
)
927 * collect pools specified in the 'pn' list.
928 * 'poolid' the pool identifier can be a pool name or sys_id.
930 poolstat_list_element_t
*poolid
;
931 for (poolid
= pn
, i
= 1; poolid
; poolid
= poolid
->ple_next
)
933 pools
= ZALLOC(sizeof (pool_t
*) * (i
+ 1));
934 for (poolid
= pn
, i
= 0; poolid
;
935 poolid
= poolid
->ple_next
, i
++) {
937 int64_t sysid
= Atoi(poolid
->ple_obj
, &error
);
939 /* the pool is identified by sys_id */
940 pool_value_set_int64(pv_sys_id
, sysid
);
941 pvals
[0] = pv_sys_id
;
942 pool
= pool_query_pools(conf
, &nelem
, pvals
);
944 if (pool_value_set_string(pv_name
,
945 poolid
->ple_obj
) == -1)
946 die(gettext(ERR_NOMEM
));
948 pool
= pool_query_pools(conf
, &nelem
, pvals
);
951 die(gettext(ERR_STATS_POOL_N
), poolid
->ple_obj
);
957 /* print statistic for all pools found */
959 /* print the common resource header */
960 prt_stat_hd(POOL_TYPE_NAME
);
962 /* print statistics for the resources bound to the pools */
963 for (i
= 0; pools
[i
] != NULL
; i
++) {
964 elem
= pool_to_elem(conf
, pools
[i
]);
965 if (pool_get_property(conf
, elem
, POOL_NAME
, pv_name
)
968 if (pool_value_get_string(pv_name
, &sbag
->sb_name
) != 0)
970 if (pool_get_property(
971 conf
, elem
, "pool.sys_id", pv_sys_id
) == -1)
973 if (pool_value_get_int64(
974 pv_sys_id
, &sbag
->sb_sysid
) != 0)
977 for (rtype
= rtypes
; rtype
; rtype
= rtype
->ple_next
) {
978 resources
= get_resources(
979 sbag
->sb_name
, rtype
->ple_obj
, &nelem
);
980 update_resource_stats(*resources
,
984 prt_stat_line(&pool_lf
);
987 /* print statistic for all resource types defined in rtypes */
988 for (rtype
= rtypes
; rtype
; rtype
= rtype
->ple_next
) {
989 prt_stat_hd(rtype
->ple_obj
);
990 for (i
= 0; pools
[i
] != NULL
; i
++) {
991 elem
= pool_to_elem(conf
, pools
[i
]);
992 if (pool_get_property(
993 conf
, elem
, POOL_NAME
, pv_name
) == -1)
995 if (pool_value_get_string(
996 pv_name
, &sbag
->sb_name
) != 0)
998 if (pool_get_property(
999 conf
, elem
, POOL_SYSID
, pv_sys_id
) == -1)
1001 if (pool_value_get_int64(
1002 pv_sys_id
, &sbag
->sb_sysid
) != 0)
1004 resources
= get_resources(
1005 sbag
->sb_name
, rtype
->ple_obj
, &nelem
);
1006 if (resources
== NULL
)
1008 update_resource_stats(
1009 *resources
, rtype
->ple_obj
);
1010 prt_resource_stats_by_type(resources
,
1018 if (pv_name
!= NULL
)
1019 pool_value_free(pv_name
);
1020 if (pv_sys_id
!= NULL
)
1021 pool_value_free(pv_sys_id
);
1025 die(gettext(ERR_STATS_POOL
), get_errstr());