1 | /* |
2 | * This Source Code Form is subject to the terms of the Mozilla Public |
3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
5 | * |
6 | * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V. |
7 | */ |
8 | |
9 | /* |
10 | * author M.L. Kersten, P. Boncz, N.Nes |
11 | * System state information |
12 | * This document introduces a series of bats and operations that provide access |
13 | * to information stored within the Monet Version 5 internal data structures. |
14 | * In all cases, pseudo BAT operation returns a transient BAT that |
15 | * should be garbage collected after being used. |
16 | * |
17 | * The main performance drain would be to use a pseudo BAT directly to |
18 | * successively access it components. This can be avoided by first assigning |
19 | * the pseudo BAT to a variable. |
20 | */ |
21 | |
22 | #include "monetdb_config.h" |
23 | #include "gdk.h" |
24 | #include <time.h> |
25 | #include "mal_exception.h" |
26 | #include "status.h" |
27 | #ifdef HAVE_UNISTD_H |
28 | # include <unistd.h> |
29 | #endif |
30 | |
31 | #ifdef HAVE_SYS_TIMES_H |
32 | # include <sys/times.h> |
33 | #endif |
34 | |
35 | #ifdef HAVE_SYS_RESOURCE_H |
36 | # include <sys/resource.h> |
37 | #endif |
38 | |
39 | static int |
40 | pseudo(bat *ret, bat *ret2, BAT *bn, BAT *b) { |
41 | *ret = bn->batCacheid; |
42 | BBPkeepref(*ret); |
43 | *ret2 = b->batCacheid; |
44 | BBPkeepref(*ret2); |
45 | return 0; |
46 | } |
47 | |
48 | str |
49 | SYSgetmem_cursize(lng *num) |
50 | { |
51 | *num = GDKmem_cursize(); |
52 | return MAL_SUCCEED; |
53 | } |
54 | |
55 | str |
56 | SYSgetmem_maxsize(lng *num) |
57 | { |
58 | *num = GDK_mem_maxsize; |
59 | return MAL_SUCCEED; |
60 | } |
61 | |
62 | str |
63 | SYSsetmem_maxsize(void *ret, const lng *num) |
64 | { |
65 | size_t sze = 0; |
66 | (void) ret; |
67 | if (*num < 0) |
68 | throw(ILLARG, "status.mem_maxsize" , "new size must not be < 0" ); |
69 | #if SIZEOF_SIZE_T == SIZEOF_INT |
70 | { |
71 | lng size_t_max = 2 * (lng)INT_MAX; |
72 | if (*num > size_t_max) |
73 | throw(ILLARG, "status.mem_maxsize" , "new size must not be > " LLFMT, size_t_max); |
74 | } |
75 | #endif |
76 | GDK_mem_maxsize = sze; |
77 | return MAL_SUCCEED; |
78 | } |
79 | |
80 | str |
81 | SYSgetvm_cursize(lng *num) |
82 | { |
83 | *num = GDKvm_cursize(); |
84 | return MAL_SUCCEED; |
85 | } |
86 | |
87 | str |
88 | SYSgetvm_maxsize(lng *num) |
89 | { |
90 | *num = GDK_vm_maxsize; |
91 | return MAL_SUCCEED; |
92 | } |
93 | |
94 | str |
95 | SYSsetvm_maxsize(void *ret, const lng *num) |
96 | { |
97 | (void) ret; |
98 | GDK_vm_maxsize = (size_t) *num; |
99 | return MAL_SUCCEED; |
100 | } |
101 | |
102 | /* |
103 | * Performance |
104 | * To obtain a good impression of the Monet performance we need timing information. |
105 | * The most detailed information is best obtained with the system profiler. |
106 | * |
107 | * However, the direct approach is to enable the user to read the timers maintained |
108 | * internally. This is done with the CPU, IO, MEMORY, and BBP command which |
109 | * displays the elapsed time in seconds, user- and system-cpu time in milliseconds |
110 | * since its last invocation and the amount of space in use. The process |
111 | * identifier is used to differentiate among the possible processes. |
112 | * |
113 | * Note that in multi threaded mode the routine prints the elapsed |
114 | * time since the beginning of each process. |
115 | */ |
116 | #ifdef HAVE_TIMES |
117 | static time_t clk = 0; |
118 | static struct tms state; |
119 | #endif |
120 | |
121 | str |
122 | SYScpuStatistics(bat *ret, bat *ret2) |
123 | { |
124 | lng i; |
125 | BAT *b, *bn; |
126 | #ifdef HAVE_TIMES |
127 | struct tms newst; |
128 | # ifndef HZ |
129 | static int HZ = 0; |
130 | |
131 | if (HZ == 0) { |
132 | # if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK) |
133 | HZ = sysconf(_SC_CLK_TCK); |
134 | # else |
135 | HZ = CLK_TCK; |
136 | # endif |
137 | } |
138 | # endif |
139 | #endif |
140 | |
141 | bn = COLnew(0, TYPE_str, 32, TRANSIENT); |
142 | b = COLnew(0, TYPE_lng, 32, TRANSIENT); |
143 | if (b == 0 || bn == 0){ |
144 | if ( b) BBPunfix(b->batCacheid); |
145 | if ( bn) BBPunfix(bn->batCacheid); |
146 | throw(MAL, "status.cpuStatistics" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
147 | } |
148 | #ifdef HAVE_TIMES |
149 | if (clk == 0) { |
150 | clk = time(0); |
151 | times(&state); |
152 | } |
153 | times(&newst); |
154 | /* store counters, ignore errors */ |
155 | i = (lng) (time(0) - clk); |
156 | if (BUNappend(bn, "elapsed" , false) != GDK_SUCCEED || |
157 | BUNappend(b, &i, false) != GDK_SUCCEED) |
158 | goto bailout; |
159 | i = newst.tms_utime * 1000 / HZ; |
160 | if (BUNappend(bn, "user" , false) != GDK_SUCCEED || |
161 | BUNappend(b, &i, false) != GDK_SUCCEED) |
162 | goto bailout; |
163 | i = (newst.tms_utime - state.tms_utime) * 1000 / HZ; |
164 | if (BUNappend(bn, "elapuser" , false) != GDK_SUCCEED || |
165 | BUNappend(b, &i, false) != GDK_SUCCEED) |
166 | goto bailout; |
167 | i = newst.tms_stime * 1000 / HZ; |
168 | if (BUNappend(bn, "system" , false) != GDK_SUCCEED || |
169 | BUNappend(b, &i, false) != GDK_SUCCEED) |
170 | goto bailout; |
171 | i = (newst.tms_stime - state.tms_stime) * 1000 / HZ; |
172 | if (BUNappend(bn, "elapsystem" , false) != GDK_SUCCEED || |
173 | BUNappend(b, &i, false) != GDK_SUCCEED) |
174 | goto bailout; |
175 | |
176 | state = newst; |
177 | #else |
178 | i = lng_nil; |
179 | if (BUNappend(bn, "elapsed" , false) != GDK_SUCCEED || |
180 | BUNappend(b, &i, false) != GDK_SUCCEED || |
181 | BUNappend(bn, "user" , false) != GDK_SUCCEED || |
182 | BUNappend(b, &i, false) != GDK_SUCCEED || |
183 | BUNappend(bn, "elapuser" , false) != GDK_SUCCEED || |
184 | BUNappend(b, &i, false) != GDK_SUCCEED || |
185 | BUNappend(bn, "system" , false) != GDK_SUCCEED || |
186 | BUNappend(b, &i, false) != GDK_SUCCEED || |
187 | BUNappend(bn, "elapsystem" , false) != GDK_SUCCEED || |
188 | BUNappend(b, &i, false) != GDK_SUCCEED) |
189 | goto bailout; |
190 | #endif |
191 | if (pseudo(ret,ret2,bn,b)) |
192 | goto bailout; |
193 | return MAL_SUCCEED; |
194 | bailout: |
195 | BBPunfix(b->batCacheid); |
196 | BBPunfix(bn->batCacheid); |
197 | throw(MAL, "status.cpuStatistics" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
198 | } |
199 | |
200 | static size_t memincr; |
201 | str |
202 | SYSmemStatistics(bat *ret, bat *ret2) |
203 | { |
204 | BAT *b, *bn; |
205 | lng i; |
206 | |
207 | bn = COLnew(0,TYPE_str, 32, TRANSIENT); |
208 | b = COLnew(0, TYPE_lng, 32, TRANSIENT); |
209 | if (b == 0 || bn == 0) { |
210 | if ( b) BBPunfix(b->batCacheid); |
211 | if ( bn) BBPunfix(bn->batCacheid); |
212 | throw(MAL, "status.memStatistics" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
213 | } |
214 | |
215 | /* store counters, ignore errors */ |
216 | i = (lng) (GDKmem_cursize() - memincr); |
217 | memincr = GDKmem_cursize(); |
218 | if (BUNappend(bn, "memincr" , false) != GDK_SUCCEED || |
219 | BUNappend(b, &i, false) != GDK_SUCCEED) |
220 | goto bailout; |
221 | if (pseudo(ret,ret2,bn,b)) |
222 | goto bailout; |
223 | return MAL_SUCCEED; |
224 | bailout: |
225 | BBPunfix(b->batCacheid); |
226 | BBPunfix(bn->batCacheid); |
227 | throw(MAL, "status.memStatistics" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
228 | } |
229 | |
230 | #define heap(X1,X2,X3,X4) \ |
231 | if (X1) { \ |
232 | sz = HEAPmemsize(X2); \ |
233 | if (sz > *minsize) { \ |
234 | sprintf(buf, X4"/%s", s); \ |
235 | if (BUNappend(bn, buf, false) != GDK_SUCCEED || \ |
236 | BUNappend(b, &sz, false) != GDK_SUCCEED) \ |
237 | goto bailout; \ |
238 | } \ |
239 | X3 += sz; tot += sz; \ |
240 | } |
241 | #define heapvm(X1,X2,X3,X4) \ |
242 | if (X1) { \ |
243 | sz = HEAPvmsize(X2); \ |
244 | if (sz > *minsize) { \ |
245 | sprintf(buf, X4"/%s", s); \ |
246 | if (BUNappend(bn, buf, false) != GDK_SUCCEED || \ |
247 | BUNappend(b, &sz, false) != GDK_SUCCEED) \ |
248 | goto bailout; \ |
249 | } \ |
250 | X3 += sz; tot += sz; \ |
251 | } |
252 | |
253 | str |
254 | SYSmem_usage(bat *ret, bat *ret2, const lng *minsize) |
255 | { |
256 | lng hbuns = 0, tbuns = 0, hhsh = 0, thsh = 0, hind = 0, tind = 0, head = 0, tail = 0, tot = 0, n = 0, sz; |
257 | BAT *bn = COLnew(0, TYPE_str, 2 * getBBPsize(), TRANSIENT); |
258 | BAT *b = COLnew(0, TYPE_lng, 2 * getBBPsize(), TRANSIENT); |
259 | char buf[1024]; |
260 | bat i; |
261 | |
262 | if (b == 0 || bn == 0) { |
263 | if ( b) BBPunfix(b->batCacheid); |
264 | if ( bn) BBPunfix(bn->batCacheid); |
265 | throw(MAL, "status.memUsage" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
266 | } |
267 | BBPlock(); |
268 | for (i = 1; i < getBBPsize(); i++) { |
269 | BAT *c = BBPquickdesc(i, false); |
270 | str s; |
271 | |
272 | if( c == NULL || !BBPvalid(i)) |
273 | continue; |
274 | |
275 | s = BBPname(i); |
276 | sz = 0; |
277 | if (BBP_desc(i)) |
278 | sz += sizeof(BAT); |
279 | if (BBP_logical(i)) |
280 | n += strLen(BBP_logical(i)); |
281 | if (BBP_physical(i)) |
282 | n += strLen(BBP_physical(i)); |
283 | |
284 | if (sz > *minsize) { |
285 | sprintf(buf, "desc/%s" , s); |
286 | if (BUNappend(bn, buf, false) != GDK_SUCCEED || |
287 | BUNappend(b, &sz, false) != GDK_SUCCEED) |
288 | goto bailout; |
289 | } |
290 | tot += (lng) sz; |
291 | |
292 | if (c == NULL || isVIEW(c)) { |
293 | continue; |
294 | } |
295 | heap(1,&c->theap,tbuns,"tbuns" ); |
296 | heap(c->thash && c->thash != (Hash *) 1,&c->thash->heap,thsh,"thsh" ); |
297 | heap(c->tvheap,c->tvheap,tail,"tail" ); |
298 | } |
299 | /* totals per category */ |
300 | if (BUNappend(bn, "_tot/hbuns" , false) != GDK_SUCCEED || |
301 | BUNappend(b, &hbuns, false) != GDK_SUCCEED || |
302 | BUNappend(bn, "_tot/tbuns" , false) != GDK_SUCCEED || |
303 | BUNappend(b, &tbuns, false) != GDK_SUCCEED || |
304 | BUNappend(bn, "_tot/head" , false) != GDK_SUCCEED || |
305 | BUNappend(b, &head, false) != GDK_SUCCEED || |
306 | BUNappend(bn, "_tot/tail" , false) != GDK_SUCCEED || |
307 | BUNappend(b, &tail, false) != GDK_SUCCEED || |
308 | BUNappend(bn, "_tot/hhsh" , false) != GDK_SUCCEED || |
309 | BUNappend(b, &hhsh, false) != GDK_SUCCEED || |
310 | BUNappend(bn, "_tot/thsh" , false) != GDK_SUCCEED || |
311 | BUNappend(b, &thsh, false) != GDK_SUCCEED || |
312 | BUNappend(bn, "_tot/hind" , false) != GDK_SUCCEED || |
313 | BUNappend(b, &hind, false) != GDK_SUCCEED || |
314 | BUNappend(bn, "_tot/tind" , false) != GDK_SUCCEED || |
315 | BUNappend(b, &tind, false) != GDK_SUCCEED) |
316 | goto bailout; |
317 | |
318 | /* special area 1: BBP rec */ |
319 | sz = BBPlimit * sizeof(BBPrec) + n; |
320 | if (BUNappend(bn, "_tot/bbp" , false) != GDK_SUCCEED || |
321 | BUNappend(b, &sz, false) != GDK_SUCCEED) |
322 | goto bailout; |
323 | tot += sz; |
324 | |
325 | /* this concludes all major traceable Monet memory usages */ |
326 | tot += sz; |
327 | if (BUNappend(bn, "_tot/found" , false) != GDK_SUCCEED || |
328 | BUNappend(b, &tot, false) != GDK_SUCCEED) |
329 | goto bailout; |
330 | |
331 | /* now look at what the global statistics report (to see if it coincides) */ |
332 | |
333 | /* measure actual heap size, includes wasted fragmented space and anon mmap space used by malloc() */ |
334 | sz = GDKmem_cursize(); |
335 | if (BUNappend(bn, "_tot/heap" , false) != GDK_SUCCEED || |
336 | BUNappend(b, &sz, false) != GDK_SUCCEED) |
337 | goto bailout; |
338 | |
339 | tot = GDKmem_cursize(); |
340 | |
341 | /* allocated swap area memory that is not plain malloc() */ |
342 | sz = MAX(0, sz - tot); |
343 | if (BUNappend(bn, "_tot/valloc" , false) != GDK_SUCCEED || |
344 | BUNappend(b, &sz, false) != GDK_SUCCEED) |
345 | goto bailout; |
346 | |
347 | /* swap-area memory is in either GDKvmalloc or heap */ |
348 | if (BUNappend(bn, "_tot/swapmem" , false) != GDK_SUCCEED || |
349 | BUNappend(b, &tot, false) != GDK_SUCCEED) |
350 | goto bailout; |
351 | |
352 | BBPunlock(); |
353 | *ret = bn->batCacheid; |
354 | BBPkeepref(bn->batCacheid); |
355 | *ret2 = b->batCacheid; |
356 | BBPkeepref(b->batCacheid); |
357 | |
358 | return MAL_SUCCEED; |
359 | |
360 | bailout: |
361 | BBPunlock(); |
362 | BBPunfix(b->batCacheid); |
363 | BBPunfix(bn->batCacheid); |
364 | throw(MAL, "status.memUsage" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
365 | } |
366 | |
367 | str |
368 | SYSvm_usage(bat *ret, bat *ret2, const lng *minsize) |
369 | { |
370 | lng hbuns = 0, tbuns = 0, hhsh = 0, thsh = 0, hind = 0, tind = 0, head = 0, tail = 0, tot = 0, sz; |
371 | BAT *bn = COLnew(0, TYPE_str, 2 * getBBPsize(), TRANSIENT); |
372 | BAT *b = COLnew(0, TYPE_lng, 2 * getBBPsize(), TRANSIENT); |
373 | char buf[1024]; |
374 | bat i; |
375 | |
376 | if (b == 0 || bn == 0) { |
377 | if ( b) BBPunfix(b->batCacheid); |
378 | if ( bn) BBPunfix(bn->batCacheid); |
379 | throw(MAL, "status.vmStatistics" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
380 | } |
381 | BBPlock(); |
382 | for (i = 1; i < getBBPsize(); i++) { |
383 | BAT *c; |
384 | str s; |
385 | |
386 | if (!BBPvalid(i)) |
387 | continue; |
388 | |
389 | s = BBPname(i); |
390 | c = BBP_cache(i); |
391 | if (c == NULL || isVIEW(c)) { |
392 | continue; |
393 | } |
394 | heapvm(1,&c->theap,tbuns,"tcuns" ); |
395 | heapvm(c->thash && c->thash != (Hash *) 1,&c->thash->heap,thsh,"thsh" ); |
396 | heapvm(c->tvheap,c->tvheap,tail,"tail" ); |
397 | } |
398 | /* totals per category */ |
399 | if (BUNappend(bn, "_tot/hbuns" , false) != GDK_SUCCEED || |
400 | BUNappend(b, &hbuns, false) != GDK_SUCCEED || |
401 | BUNappend(bn, "_tot/tbuns" , false) != GDK_SUCCEED || |
402 | BUNappend(b, &tbuns, false) != GDK_SUCCEED || |
403 | BUNappend(bn, "_tot/head" , false) != GDK_SUCCEED || |
404 | BUNappend(b, &head, false) != GDK_SUCCEED || |
405 | BUNappend(bn, "_tot/tail" , false) != GDK_SUCCEED || |
406 | BUNappend(b, &tail, false) != GDK_SUCCEED || |
407 | BUNappend(bn, "_tot/hhsh" , false) != GDK_SUCCEED || |
408 | BUNappend(b, &hhsh, false) != GDK_SUCCEED || |
409 | BUNappend(bn, "_tot/thsh" , false) != GDK_SUCCEED || |
410 | BUNappend(b, &thsh, false) != GDK_SUCCEED || |
411 | BUNappend(bn, "_tot/hind" , false) != GDK_SUCCEED || |
412 | BUNappend(b, &hind, false) != GDK_SUCCEED || |
413 | BUNappend(bn, "_tot/tind" , false) != GDK_SUCCEED || |
414 | BUNappend(b, &tind, false) != GDK_SUCCEED) |
415 | goto bailout; |
416 | |
417 | /* special area 1: BBP rec */ |
418 | sz = BBPlimit * sizeof(BBPrec); |
419 | if (BUNappend(bn, "_tot/bbp" , false) != GDK_SUCCEED || |
420 | BUNappend(b, &sz, false) != GDK_SUCCEED) |
421 | goto bailout; |
422 | tot += sz; |
423 | |
424 | |
425 | /* this concludes all major traceable Monet virtual memory usages */ |
426 | tot += sz; |
427 | if (BUNappend(bn, "_tot/found" , false) != GDK_SUCCEED || |
428 | BUNappend(b, &tot, false) != GDK_SUCCEED) |
429 | goto bailout; |
430 | |
431 | /* all VM is either GDKmmap or GDKvmalloc (possibly redirected GDKmalloc), *plus* the heap */ |
432 | sz = GDKvm_cursize(); |
433 | if (BUNappend(bn, "_tot/vm" , false) != GDK_SUCCEED || |
434 | BUNappend(b, &sz, false) != GDK_SUCCEED) |
435 | goto bailout; |
436 | |
437 | BBPunlock(); |
438 | *ret = bn->batCacheid; |
439 | BBPkeepref(bn->batCacheid); |
440 | *ret2 = b->batCacheid; |
441 | BBPkeepref(b->batCacheid); |
442 | return MAL_SUCCEED; |
443 | |
444 | bailout: |
445 | BBPunlock(); |
446 | BBPunfix(b->batCacheid); |
447 | BBPunfix(bn->batCacheid); |
448 | throw(MAL, "status.vmStatistics" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
449 | } |
450 | |
451 | /* |
452 | * Additional information on the process utilization is given by |
453 | * the ioStatistics command. The following information is obtained. |
454 | * |
455 | * @T |
456 | * \begin{tabular}{| l| l|}\hline |
457 | * maxrss &the maximum resident set size utilized (in kilobytes).\\ |
458 | * minflt &the number of page faults serviced without any I/O\\ |
459 | * &activity; here I/O activity is avoided by "reclaiming" a\\ |
460 | * |
461 | * &activity; here I/O activity is avoided by "reclaiming" a\\ |
462 | * &page frame from the list of pages awaiting reallocation.\\ |
463 | * majflt &the number of page faults serviced that required I/O\\ |
464 | * &activity.\\ |
465 | * nswap &the number of times a process was "swapped" out of main\\ |
466 | * &memory\\ |
467 | * inblock &the number of times the file system had to perform input.\\ |
468 | * oublock &the number of times the file system had to perform output.\\ |
469 | * nvcsw &the number of times a context switch resulted due to a\\ |
470 | * &process voluntarily giving up the processor before its\\ |
471 | * &time slice was completed (usually to await availability of\\ |
472 | * &a resource).\\ |
473 | * nivcsw &the number of times a context switch resulted due to a\\ |
474 | * &higher priority process becoming runnable or because the\\ |
475 | * ¤t process exceeded its time slice.\\ |
476 | * \end{tabular} |
477 | * |
478 | * The resource statistics are collected in a BAT. It can then |
479 | * be queried. A default listing is produced by the command usagecmd. |
480 | * (which should be moved to Monet) |
481 | * |
482 | * The BAT grows. It should be compacted. |
483 | */ |
484 | str |
485 | SYSioStatistics(bat *ret, bat *ret2) |
486 | { |
487 | #ifdef HAVE_SYS_RESOURCE_H |
488 | struct rusage ru; |
489 | #endif |
490 | lng i; |
491 | BAT *b, *bn; |
492 | |
493 | #ifdef HAVE_SYS_RESOURCE_H |
494 | getrusage(RUSAGE_SELF, &ru); |
495 | #endif |
496 | bn = COLnew(0, TYPE_str, 32, TRANSIENT); |
497 | b = COLnew(0, TYPE_lng, 32, TRANSIENT); |
498 | if (b == 0 || bn == 0) { |
499 | if ( b) BBPunfix(b->batCacheid); |
500 | if ( bn) BBPunfix(bn->batCacheid); |
501 | throw(MAL, "status.ioStatistics" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
502 | } |
503 | |
504 | #ifdef HAVE_SYS_RESOURCE_H |
505 | /* store counters, ignore errors */ |
506 | i = ru.ru_maxrss; |
507 | if (BUNappend(bn, "maxrss" , false) != GDK_SUCCEED || |
508 | BUNappend(b, &i, false) != GDK_SUCCEED) |
509 | goto bailout; |
510 | i = ru.ru_minflt; |
511 | if (BUNappend(bn, "minflt" , false) != GDK_SUCCEED || |
512 | BUNappend(b, &i, false) != GDK_SUCCEED) |
513 | goto bailout; |
514 | i = ru.ru_majflt; |
515 | if (BUNappend(bn, "majflt" , false) != GDK_SUCCEED || |
516 | BUNappend(b, &i, false) != GDK_SUCCEED) |
517 | goto bailout; |
518 | i = ru.ru_nswap; |
519 | if (BUNappend(bn, "nswap" , false) != GDK_SUCCEED || |
520 | BUNappend(b, &i, false) != GDK_SUCCEED) |
521 | goto bailout; |
522 | i = ru.ru_inblock; |
523 | if (BUNappend(bn, "inblock" , false) != GDK_SUCCEED || |
524 | BUNappend(b, &i, false) != GDK_SUCCEED) |
525 | goto bailout; |
526 | i = ru.ru_oublock; |
527 | if (BUNappend(bn, "oublock" , false) != GDK_SUCCEED || |
528 | BUNappend(b, &i, false) != GDK_SUCCEED) |
529 | goto bailout; |
530 | i = ru.ru_nvcsw; |
531 | if (BUNappend(bn, "nvcsw" , false) != GDK_SUCCEED || |
532 | BUNappend(b, &i, false) != GDK_SUCCEED) |
533 | goto bailout; |
534 | i = ru.ru_nivcsw; |
535 | if (BUNappend(bn, "ninvcsw" , false) != GDK_SUCCEED || |
536 | BUNappend(b, &i, false) != GDK_SUCCEED) |
537 | goto bailout; |
538 | #else |
539 | i = lng_nil; |
540 | if (BUNappend(bn, "maxrss" , false) != GDK_SUCCEED || |
541 | BUNappend(b, &i, false) != GDK_SUCCEED || |
542 | BUNappend(bn, "minflt" , false) != GDK_SUCCEED || |
543 | BUNappend(b, &i, false) != GDK_SUCCEED || |
544 | BUNappend(bn, "majflt" , false) != GDK_SUCCEED || |
545 | BUNappend(b, &i, false) != GDK_SUCCEED || |
546 | BUNappend(bn, "nswap" , false) != GDK_SUCCEED || |
547 | BUNappend(b, &i, false) != GDK_SUCCEED || |
548 | BUNappend(bn, "inblock" , false) != GDK_SUCCEED || |
549 | BUNappend(b, &i, false) != GDK_SUCCEED || |
550 | BUNappend(bn, "oublock" , false) != GDK_SUCCEED || |
551 | BUNappend(b, &i, false) != GDK_SUCCEED || |
552 | BUNappend(bn, "nvcsw" , false) != GDK_SUCCEED || |
553 | BUNappend(b, &i, false) != GDK_SUCCEED || |
554 | BUNappend(bn, "ninvcsw" , false) != GDK_SUCCEED || |
555 | BUNappend(b, &i, false) != GDK_SUCCEED) |
556 | goto bailout; |
557 | #endif |
558 | |
559 | if (pseudo(ret,ret2,bn,b)) |
560 | goto bailout; |
561 | return MAL_SUCCEED; |
562 | |
563 | bailout: |
564 | BBPunfix(b->batCacheid); |
565 | BBPunfix(bn->batCacheid); |
566 | throw(MAL, "status.ioStatistics" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
567 | } |
568 | |
569 | str |
570 | SYSgdkEnv(bat *ret, bat *ret2) |
571 | { |
572 | int pbat = 0; |
573 | int pdisk = 0; |
574 | bat i; |
575 | int tmp = 0, per = 0; |
576 | BAT *b,*bn; |
577 | |
578 | bn = COLnew(0, TYPE_str, 32, TRANSIENT); |
579 | b = COLnew(0, TYPE_int, 32, TRANSIENT); |
580 | if (b == 0 || bn == 0) { |
581 | if ( b) BBPunfix(b->batCacheid); |
582 | if ( bn) BBPunfix(bn->batCacheid); |
583 | throw(MAL, "status.batStatistics" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
584 | } |
585 | |
586 | for (i = 1; i < getBBPsize(); i++) { |
587 | if (BBPvalid(i)) { |
588 | pbat++; |
589 | if (BBP_cache(i)) { |
590 | if (BBP_cache(i)->batTransient) |
591 | tmp++; |
592 | else |
593 | per++; |
594 | } else { |
595 | pdisk++; |
596 | } |
597 | } |
598 | } |
599 | if (BUNappend(bn, "bats" , false) != GDK_SUCCEED || |
600 | BUNappend(b, &pbat, false) != GDK_SUCCEED || |
601 | BUNappend(bn, "tmpbats" , false) != GDK_SUCCEED || |
602 | BUNappend(b, &tmp, false) != GDK_SUCCEED || |
603 | BUNappend(bn, "perbats" , false) != GDK_SUCCEED || |
604 | BUNappend(b, &per, false) != GDK_SUCCEED || |
605 | BUNappend(bn, "ondisk" , false) != GDK_SUCCEED || |
606 | BUNappend(b, &pdisk, false) != GDK_SUCCEED || |
607 | pseudo(ret,ret2, bn,b)) { |
608 | BBPunfix(b->batCacheid); |
609 | BBPunfix(bn->batCacheid); |
610 | throw(MAL, "status.batStatistics" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
611 | } |
612 | return MAL_SUCCEED; |
613 | } |
614 | |
615 | str |
616 | SYSgdkThread(bat *ret, bat *ret2) |
617 | { |
618 | BAT *b, *bn; |
619 | int i; |
620 | Thread thr; |
621 | |
622 | bn = COLnew(0,TYPE_int, THREADS, TRANSIENT); |
623 | b = COLnew(0, TYPE_str, THREADS, TRANSIENT); |
624 | if (b == 0 || bn == 0) { |
625 | if ( b) BBPunfix(b->batCacheid); |
626 | if ( bn) BBPunfix(bn->batCacheid); |
627 | throw(MAL, "status.getThreads" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
628 | } |
629 | |
630 | for (i = 1; i <= THREADS; i++) { |
631 | thr = THRget(i); |
632 | if (ATOMIC_GET(&thr->pid)){ |
633 | if (BUNappend(bn, &thr->tid, false) != GDK_SUCCEED || |
634 | BUNappend(b, thr->name? thr->name:"" , false) != GDK_SUCCEED) |
635 | goto bailout; |
636 | } |
637 | } |
638 | if (pseudo(ret,ret2,bn,b)) |
639 | goto bailout; |
640 | return MAL_SUCCEED; |
641 | |
642 | bailout: |
643 | BBPunfix(b->batCacheid); |
644 | BBPunfix(bn->batCacheid); |
645 | throw(MAL, "status.getThreads" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
646 | } |
647 | |