xref: /openbsd/usr.bin/systat/pool.c (revision 404b540a)
1 /*	$OpenBSD: pool.c,v 1.5 2008/12/31 05:37:24 canacar Exp $	*/
2 /*
3  * Copyright (c) 2008 Can Erkin Acar <canacar@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/types.h>
19 #include <sys/param.h>
20 #include <sys/sysctl.h>
21 #include <sys/pool.h>
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include "systat.h"
27 
28 void print_pool(void);
29 int  read_pool(void);
30 void  sort_pool(void);
31 int  select_pool(void);
32 void showpool(int k);
33 
34 /* qsort callbacks */
35 int sort_name_callback(const void *s1, const void *s2);
36 int sort_req_callback(const void *s1, const void *s2);
37 int sort_psize_callback(const void *s1, const void *s2);
38 int sort_npage_callback(const void *s1, const void *s2);
39 
40 struct pool_info {
41 	char name[32];
42 	struct pool pool;
43 };
44 
45 
46 int num_pools = 0;
47 struct pool_info *pools = NULL;
48 
49 
50 field_def fields_pool[] = {
51 	{"NAME", 11, 32, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
52 	{"SIZE", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
53 	{"REQUESTS", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
54 	{"FAIL", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
55 	{"INUSE", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
56 	{"PGREQ", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
57 	{"PGREL", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
58 	{"NPAGE", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
59 	{"HIWAT", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
60 	{"MINPG", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
61 	{"MAXPG", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
62 	{"IDLE", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}
63 };
64 
65 
66 #define FIELD_ADDR(x) (&fields_pool[x])
67 
68 #define FLD_POOL_NAME	FIELD_ADDR(0)
69 #define FLD_POOL_SIZE	FIELD_ADDR(1)
70 #define FLD_POOL_REQS	FIELD_ADDR(2)
71 #define FLD_POOL_FAIL	FIELD_ADDR(3)
72 #define FLD_POOL_INUSE	FIELD_ADDR(4)
73 #define FLD_POOL_PGREQ	FIELD_ADDR(5)
74 #define FLD_POOL_PGREL	FIELD_ADDR(6)
75 #define FLD_POOL_NPAGE	FIELD_ADDR(7)
76 #define FLD_POOL_HIWAT	FIELD_ADDR(8)
77 #define FLD_POOL_MINPG	FIELD_ADDR(9)
78 #define FLD_POOL_MAXPG	FIELD_ADDR(10)
79 #define FLD_POOL_IDLE	FIELD_ADDR(11)
80 
81 /* Define views */
82 field_def *view_pool_0[] = {
83 	FLD_POOL_NAME, FLD_POOL_SIZE, FLD_POOL_REQS, FLD_POOL_FAIL,
84 	FLD_POOL_INUSE, FLD_POOL_PGREQ, FLD_POOL_PGREL, FLD_POOL_NPAGE,
85 	FLD_POOL_HIWAT, FLD_POOL_MINPG, FLD_POOL_MAXPG, FLD_POOL_IDLE, NULL
86 };
87 
88 order_type pool_order_list[] = {
89 	{"name", "name", 'N', sort_name_callback},
90 	{"requests", "requests", 'Q', sort_req_callback},
91 	{"size", "size", 'Z', sort_psize_callback},
92 	{"npages", "npages", 'P', sort_npage_callback},
93 	{NULL, NULL, 0, NULL}
94 };
95 
96 /* Define view managers */
97 struct view_manager pool_mgr = {
98 	"Pool", select_pool, read_pool, sort_pool, print_header,
99 	print_pool, keyboard_callback, pool_order_list, pool_order_list
100 };
101 
102 field_view views_pool[] = {
103 	{view_pool_0, "pool", '5', &pool_mgr},
104 	{NULL, NULL, 0, NULL}
105 };
106 
107 
108 int
109 sort_name_callback(const void *s1, const void *s2)
110 {
111 	struct pool_info *p1, *p2;
112 	p1 = (struct pool_info *)s1;
113 	p2 = (struct pool_info *)s2;
114 
115 	return strcmp(p1->name, p2->name) * sortdir;
116 }
117 
118 int
119 sort_req_callback(const void *s1, const void *s2)
120 {
121 	struct pool_info *p1, *p2;
122 	p1 = (struct pool_info *)s1;
123 	p2 = (struct pool_info *)s2;
124 
125 	if (p1->pool.pr_nget <  p2->pool.pr_nget)
126 		return sortdir;
127 	if (p1->pool.pr_nget >  p2->pool.pr_nget)
128 		return -sortdir;
129 
130 	return sort_name_callback(s1, s2);
131 }
132 
133 int
134 sort_npage_callback(const void *s1, const void *s2)
135 {
136 	struct pool_info *p1, *p2;
137 	p1 = (struct pool_info *)s1;
138 	p2 = (struct pool_info *)s2;
139 
140 	if (p1->pool.pr_npages <  p2->pool.pr_npages)
141 		return sortdir;
142 	if (p1->pool.pr_npages >  p2->pool.pr_npages)
143 		return -sortdir;
144 
145 	return sort_name_callback(s1, s2);
146 }
147 
148 int
149 sort_psize_callback(const void *s1, const void *s2)
150 {
151 	struct pool_info *p1, *p2;
152 	size_t ps1, ps2;
153 
154 	p1 = (struct pool_info *)s1;
155 	p2 = (struct pool_info *)s2;
156 
157 	ps1  = (size_t)(p1->pool.pr_nget - p1->pool.pr_nput) *
158 	    (size_t)p1->pool.pr_size;
159 	ps2  = (size_t)(p2->pool.pr_nget - p2->pool.pr_nput) *
160 	    (size_t)p2->pool.pr_size;
161 
162 	if (ps1 <  ps2)
163 		return sortdir;
164 	if (ps1 >  ps2)
165 		return -sortdir;
166 
167 	return sort_npage_callback(s1, s2);
168 }
169 
170 void
171 sort_pool(void)
172 {
173 	order_type *ordering;
174 
175 	if (curr_mgr == NULL)
176 		return;
177 
178 	ordering = curr_mgr->order_curr;
179 
180 	if (ordering == NULL)
181 		return;
182 	if (ordering->func == NULL)
183 		return;
184 	if (pools == NULL)
185 		return;
186 	if (num_pools <= 0)
187 		return;
188 
189 	mergesort(pools, num_pools, sizeof(struct pool_info), ordering->func);
190 }
191 
192 int
193 select_pool(void)
194 {
195 	num_disp = num_pools;
196 	return (0);
197 }
198 
199 int
200 read_pool(void)
201 {
202 	int mib[4], np, i;
203 	size_t size;
204 
205 	mib[0] = CTL_KERN;
206 	mib[1] = KERN_POOL;
207 	mib[2] = KERN_POOL_NPOOLS;
208 	size = sizeof(np);
209 
210 	if (sysctl(mib, 3, &np, &size, NULL, 0) < 0) {
211 		error("sysctl(npools): %s", strerror(errno));
212 		return (-1);
213 	}
214 
215 	if (np <= 0) {
216 		num_pools = 0;
217 		return (0);
218 	}
219 
220 	if (np > num_pools || pools == NULL) {
221 		struct pool_info *p = realloc(pools, sizeof(*pools) * np);
222 		if (p == NULL) {
223 			error("realloc: %s", strerror(errno));
224 			return (-1);
225 		}
226 		pools = p;
227 		num_pools = np;
228 	}
229 
230 	num_disp = num_pools;
231 
232 	for (i = 0; i < num_pools; i++) {
233 		mib[0] = CTL_KERN;
234 		mib[1] = KERN_POOL;
235 		mib[2] = KERN_POOL_POOL;
236 		mib[3] = i + 1;
237 		size = sizeof(struct pool);
238 		if (sysctl(mib, 4, &pools[i].pool, &size, NULL, 0) < 0) {
239 			memset(&pools[i], 0, sizeof(pools[i]));
240 			num_disp--;
241 			continue;
242 		}
243 		mib[2] = KERN_POOL_NAME;
244 		size = sizeof(pools[i].name);
245 		if (sysctl(mib, 4, &pools[i].name, &size, NULL, 0) < 0) {
246 			snprintf(pools[i].name, size, "#%d#", mib[3]);
247 		}
248 	}
249 
250 	if (i != num_pools) {
251 		memset(pools, 0, sizeof(*pools) * num_pools);
252 		return (-1);
253 	}
254 
255 	return 0;
256 }
257 
258 
259 void
260 print_pool(void)
261 {
262 	int i, n, count = 0;
263 
264 	if (pools == NULL)
265 		return;
266 
267 	for (n = i = 0; i < num_pools; i++) {
268 		if (pools[i].name[0] == 0)
269 			continue;
270 		if (n++ < dispstart)
271 			continue;
272 		showpool(i);
273 		count++;
274 		if (maxprint > 0 && count >= maxprint)
275 			break;
276 	}
277 }
278 
279 int
280 initpool(void)
281 {
282 	field_view *v;
283 
284 	for (v = views_pool; v->name != NULL; v++)
285 		add_view(v);
286 
287 	read_pool();
288 
289 	return(0);
290 }
291 
292 void
293 showpool(int k)
294 {
295 	struct pool_info *p = pools + k;
296 
297 	if (k < 0 || k >= num_pools)
298 		return;
299 
300 	print_fld_str(FLD_POOL_NAME, p->name);
301 	print_fld_uint(FLD_POOL_SIZE, p->pool.pr_size);
302 
303 	print_fld_size(FLD_POOL_REQS, p->pool.pr_nget);
304 	print_fld_size(FLD_POOL_FAIL, p->pool.pr_nfail);
305 	print_fld_ssize(FLD_POOL_INUSE, p->pool.pr_nget - p->pool.pr_nput);
306 	print_fld_size(FLD_POOL_PGREQ, p->pool.pr_npagealloc);
307 	print_fld_size(FLD_POOL_PGREL, p->pool.pr_npagefree);
308 
309 	print_fld_size(FLD_POOL_NPAGE, p->pool.pr_npages);
310 	print_fld_size(FLD_POOL_HIWAT, p->pool.pr_hiwat);
311 	print_fld_size(FLD_POOL_MINPG, p->pool.pr_minpages);
312 
313 	if (p->pool.pr_maxpages == UINT_MAX)
314 		print_fld_str(FLD_POOL_MAXPG, "inf");
315 	else
316 		print_fld_size(FLD_POOL_MAXPG, p->pool.pr_maxpages);
317 
318 	print_fld_size(FLD_POOL_IDLE, p->pool.pr_nidle);
319 
320 	end_line();
321 }
322