OLD | NEW |
| (Empty) |
1 #ifndef _WINDOWS | |
2 | |
3 /* Licensed to the Apache Software Foundation (ASF) under one or more | |
4 * contributor license agreements. See the NOTICE file distributed with | |
5 * this work for additional information regarding copyright ownership. | |
6 * The ASF licenses this file to You under the Apache License, Version 2.0 | |
7 * (the "License"); you may not use this file except in compliance with | |
8 * the License. You may obtain a copy of the License at | |
9 * | |
10 * http://www.apache.org/licenses/LICENSE-2.0 | |
11 * | |
12 * Unless required by applicable law or agreed to in writing, software | |
13 * distributed under the License is distributed on an "AS IS" BASIS, | |
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
15 * See the License for the specific language governing permissions and | |
16 * limitations under the License. | |
17 */ | |
18 | |
19 /* | |
20 * | |
21 * @author Mladen Turk | |
22 * @version $Id: system.c 1445974 2013-02-13 23:11:53Z rjung $ | |
23 */ | |
24 | |
25 #include "apr.h" | |
26 #include "apr_pools.h" | |
27 #include "apr_network_io.h" | |
28 #include "apr_poll.h" | |
29 | |
30 #include "tcn.h" | |
31 #if defined(__linux__) | |
32 #include <sys/sysinfo.h> | |
33 #elif defined(sun) | |
34 #include <unistd.h> | |
35 #include <sys/swap.h> | |
36 #include <procfs.h> | |
37 #include <kstat.h> | |
38 #include <sys/sysinfo.h> | |
39 #endif | |
40 | |
41 #if defined(DARWIN) | |
42 #include <mach/mach_init.h> | |
43 #include <mach/mach_host.h> | |
44 #include <mach/host_info.h> | |
45 #include <sys/sysctl.h> | |
46 #include <sys/stat.h> | |
47 #endif | |
48 | |
49 #include <syslog.h> | |
50 #include <stdarg.h> | |
51 | |
52 #ifndef LOG_WARN | |
53 #define LOG_WARN LOG_WARNING | |
54 #endif | |
55 | |
56 #if defined(sun) | |
57 #define MAX_PROC_PATH_LEN 64 | |
58 #define MAX_CPUS 512 | |
59 #define PSINFO_T_SZ sizeof(psinfo_t) | |
60 #define PRUSAGE_T_SZ sizeof(prusage_t) | |
61 | |
62 static int proc_open(const char *type) | |
63 { | |
64 char proc_path[MAX_PROC_PATH_LEN+1]; | |
65 | |
66 sprintf(proc_path, "/proc/self/%s", type); | |
67 return open(proc_path, O_RDONLY); | |
68 } | |
69 | |
70 static int proc_read(void *buf, const size_t size, int filedes) | |
71 { | |
72 ssize_t bytes; | |
73 | |
74 if (filedes >= 0) { | |
75 bytes = pread(filedes, buf, size, 0); | |
76 if (bytes != size) | |
77 return -1; | |
78 else | |
79 return 0; | |
80 } | |
81 else | |
82 return -1; | |
83 } | |
84 | |
85 #endif | |
86 | |
87 TCN_IMPLEMENT_CALL(jboolean, OS, is)(TCN_STDARGS, jint type) | |
88 { | |
89 UNREFERENCED_STDARGS; | |
90 if (type == 1) | |
91 return JNI_TRUE; | |
92 #if defined(__linux__) | |
93 else if (type == 5) | |
94 return JNI_TRUE; | |
95 #endif | |
96 #if defined(sun) | |
97 else if (type == 6) | |
98 return JNI_TRUE; | |
99 #endif | |
100 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) | |
101 else if (type == 7) | |
102 return JNI_TRUE; | |
103 #endif | |
104 #if defined(__APPLE__) || defined(DARWIN) | |
105 else if (type == 8) | |
106 return JNI_TRUE; | |
107 #endif | |
108 else | |
109 return JNI_FALSE; | |
110 } | |
111 | |
112 TCN_IMPLEMENT_CALL(jint, OS, info)(TCN_STDARGS, | |
113 jlongArray inf) | |
114 { | |
115 jint rv; | |
116 int i; | |
117 jsize ilen = (*e)->GetArrayLength(e, inf); | |
118 jlong *pvals = (*e)->GetLongArrayElements(e, inf, NULL); | |
119 | |
120 UNREFERENCED(o); | |
121 if (ilen < 16) { | |
122 return APR_EINVAL; | |
123 } | |
124 for (i = 0; i < 16; i++) | |
125 pvals[i] = 0; | |
126 #if defined(__linux__) | |
127 { | |
128 struct sysinfo info; | |
129 if (sysinfo(&info)) | |
130 rv = apr_get_os_error(); | |
131 else { | |
132 static char buf[1024]; | |
133 unsigned long user = 0; | |
134 unsigned long system = 0; | |
135 long idle = 0; | |
136 long long starttime = 0; | |
137 int fd; | |
138 int len; | |
139 long sys_clk_tck = sysconf(_SC_CLK_TCK); /* number of system ticks p
er second */ | |
140 | |
141 pvals[0] = (jlong)(info.totalram * info.mem_unit); | |
142 pvals[1] = (jlong)(info.freeram * info.mem_unit); | |
143 pvals[2] = (jlong)(info.totalswap * info.mem_unit); | |
144 pvals[3] = (jlong)(info.freeswap * info.mem_unit); | |
145 pvals[4] = (jlong)(info.sharedram * info.mem_unit); | |
146 pvals[5] = (jlong)(info.bufferram * info.mem_unit); | |
147 pvals[6] = (jlong)(100 - (info.freeram * 100 / info.totalram)); | |
148 | |
149 if (sys_clk_tck >= 0) { | |
150 /* Get total CPU times from /proc/stat */ | |
151 /* Example for the first line: cpu 2095497 8176 3280198 9086678
41 1543576 28867 375399 0 0 */ | |
152 /* According to the man pages, the numbers are given in units of
USER_HZ: | |
153 * user mode, user mode with low priority (nice), system mode, a
nd the idle task. | |
154 * Additional values can be ignored. */ | |
155 fd = open("/proc/stat", O_RDONLY); | |
156 if (fd != -1) { | |
157 len = read(fd, buf, sizeof buf - 1); | |
158 if (len > 0) { | |
159 buf[len] = '\0'; | |
160 if (sscanf(buf, "cpu %lu %*d %lu %ld", &user, &system, &
idle) == 3) { | |
161 pvals[7] = (jlong)(idle * 1000 / sys_clk_tck * 1000)
; /* Idle Time in microseconds */ | |
162 pvals[8] = (jlong)(system * 1000 / sys_clk_tck * 100
0); /* Kernel Time in microseconds */ | |
163 pvals[9] = (jlong)(user * 1000 / sys_clk_tck * 1000)
; /* User Time in microseconds */ | |
164 } | |
165 } | |
166 close(fd); | |
167 } | |
168 /* Get process CPU times from /proc/self/stat */ | |
169 /* Example for the first line: | |
170 * 6309 (csh) S 6308 6309 6309 34816 7124 4202496 15119 252261 1
30 21 58 1537 1447 20 0 1 0 916031966 ... */ | |
171 /* Parsing it according to man -s 5 proci: | |
172 * pid %d, comm %s, state %c, ppid %d pgrp %d, session %d, tty_n
r %d, tpgid %d, flags %u, | |
173 * minflt %lu, cminflt %lu, majflt %lu, cmajflt %lu, | |
174 * utime %lu (!), stime %lu (!), cutime %ld (!), cstime %ld (!), | |
175 * priority %ld, nice %ld, num_threads %ld, itrealvalue %ld, | |
176 * starttime %llu (!) */ | |
177 fd = open("/proc/self/stat", O_RDONLY); | |
178 if (fd != -1) { | |
179 len = read(fd, buf, sizeof buf - 1); | |
180 if (len > 0) { | |
181 buf[len] = '\0'; | |
182 if (sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*u" | |
183 " %*u %*u %*u %*u" | |
184 " %lu %lu %*d %*d" | |
185 " %*d %*d %*d %*d" | |
186 "%llu", &user, &system, &starttime) == 3
) { | |
187 pvals[10] = (jlong)(apr_time_now() - apr_time_make(i
nfo.uptime - starttime / sys_clk_tck, 0)); /* Process creation time (apr_time_t)
*/ | |
188 pvals[11] = (jlong)(system * 1000 / sys_clk_tck * 10
00); /* Process System Time in microseconds */ | |
189 pvals[12] = (jlong)(user * 1000 / sys_clk_tck * 1000
); /* Process User Time in microseconds */ | |
190 } | |
191 } | |
192 close(fd); | |
193 } | |
194 } | |
195 | |
196 rv = APR_SUCCESS; | |
197 } | |
198 } | |
199 #elif defined(sun) | |
200 { | |
201 /* static variables with basic procfs info */ | |
202 static long creation = 0; /* unix timestamp of process crea
tion */ | |
203 static int psinf_fd = 0; /* file descriptor for the psinfo
procfs file */ | |
204 static int prusg_fd = 0; /* file descriptor for the usage
procfs file */ | |
205 static size_t rss = 0; /* maximum of resident set size f
rom previous calls */ | |
206 /* static variables with basic kstat info */ | |
207 static kstat_ctl_t *kstat_ctl = NULL; /* kstat control object, only ini
tialized once */ | |
208 static kstat_t *kstat_cpu[MAX_CPUS]; /* array of kstat objects for per
cpu statistics */ | |
209 static int cpu_count = 0; /* number of cpu structures found
in kstat */ | |
210 static kid_t kid = 0; /* kstat ID, for which the kstat_
ctl holds the correct chain */ | |
211 /* non-static variables - general use */ | |
212 int res = 0; /* general result state */ | |
213 /* non-static variables - sysinfo/swapctl use */ | |
214 long ret_sysconf; /* value returned from sysconf ca
ll */ | |
215 long tck_dividend; /* factor used by transforming ti
ck numbers to microseconds */ | |
216 long tck_divisor; /* divisor used by transforming t
ick numbers to microseconds */ | |
217 long sys_pagesize = sysconf(_SC_PAGESIZE); /* size of a system memory pa
ge in bytes */ | |
218 long sys_clk_tck = sysconf(_SC_CLK_TCK); /* number of system ticks per s
econd */ | |
219 struct anoninfo info; /* structure for information abou
t sizes in anonymous memory system */ | |
220 /* non-static variables - procfs use */ | |
221 psinfo_t psinf; /* psinfo structure from procfs *
/ | |
222 prusage_t prusg; /* usage structure from procfs */ | |
223 size_t new_rss = 0; /* resident set size read from pr
ocfs */ | |
224 time_t now; /* time needed for calculating pr
ocess creation time */ | |
225 /* non-static variables - kstat use */ | |
226 kstat_t *kstat = NULL; /* kstat working pointer */ | |
227 cpu_sysinfo_t cpu; /* cpu sysinfo working pointer */ | |
228 kid_t new_kid = 0; /* kstat ID returned from chain u
pdate */ | |
229 int new_kstat = 0; /* flag indicating, if kstat stru
cture has changed since last call */ | |
230 | |
231 rv = APR_SUCCESS; | |
232 | |
233 if (sys_pagesize <= 0) { | |
234 rv = apr_get_os_error(); | |
235 } | |
236 else { | |
237 ret_sysconf = sysconf(_SC_PHYS_PAGES); | |
238 if (ret_sysconf >= 0) { | |
239 pvals[0] = (jlong)((jlong)sys_pagesize * ret_sysconf); | |
240 } | |
241 else { | |
242 rv = apr_get_os_error(); | |
243 } | |
244 ret_sysconf = sysconf(_SC_AVPHYS_PAGES); | |
245 if (ret_sysconf >= 0) { | |
246 pvals[1] = (jlong)((jlong)sys_pagesize * ret_sysconf); | |
247 } | |
248 else { | |
249 rv = apr_get_os_error(); | |
250 } | |
251 res=swapctl(SC_AINFO, &info); | |
252 if (res >= 0) { | |
253 pvals[2] = (jlong)((jlong)sys_pagesize * info.ani_max); | |
254 pvals[3] = (jlong)((jlong)sys_pagesize * info.ani_free); | |
255 pvals[6] = (jlong)(100 - (jlong)info.ani_free * 100 / info.ani_m
ax); | |
256 } | |
257 else { | |
258 rv = apr_get_os_error(); | |
259 } | |
260 } | |
261 | |
262 if (psinf_fd == 0) { | |
263 psinf_fd = proc_open("psinfo"); | |
264 } | |
265 res = proc_read(&psinf, PSINFO_T_SZ, psinf_fd); | |
266 if (res >= 0) { | |
267 new_rss = psinf.pr_rssize*1024; | |
268 pvals[13] = (jlong)(new_rss); | |
269 if (new_rss > rss) { | |
270 rss = new_rss; | |
271 } | |
272 pvals[14] = (jlong)(rss); | |
273 } | |
274 else { | |
275 psinf_fd = 0; | |
276 rv = apr_get_os_error(); | |
277 } | |
278 if (prusg_fd == 0) { | |
279 prusg_fd = proc_open("usage"); | |
280 } | |
281 res = proc_read(&prusg, PRUSAGE_T_SZ, prusg_fd); | |
282 if (res >= 0) { | |
283 if (creation <= 0) { | |
284 time(&now); | |
285 creation = (long)(now - (prusg.pr_tstamp.tv_sec - | |
286 prusg.pr_create.tv_sec)); | |
287 } | |
288 pvals[10] = (jlong)(creation * 1000000L); | |
289 pvals[11] = (jlong)((jlong)prusg.pr_stime.tv_sec * 1000000L + | |
290 (prusg.pr_stime.tv_nsec / 1000L)); | |
291 pvals[12] = (jlong)((jlong)prusg.pr_utime.tv_sec * 1000000L + | |
292 (prusg.pr_utime.tv_nsec / 1000L)); | |
293 pvals[15] = (jlong)(prusg.pr_majf); | |
294 } | |
295 else { | |
296 prusg_fd = 0; | |
297 rv = apr_get_os_error(); | |
298 } | |
299 | |
300 if (sys_clk_tck <= 0) { | |
301 rv = apr_get_os_error(); | |
302 } | |
303 else { | |
304 tck_dividend = 1000000L; | |
305 tck_divisor = sys_clk_tck; | |
306 for (i = 0; i < 3; i++) { | |
307 if (tck_divisor % 2 == 0) { | |
308 tck_divisor = tck_divisor / 2; | |
309 tck_dividend = tck_dividend / 2; | |
310 } | |
311 if (tck_divisor % 5 == 0) { | |
312 tck_divisor = tck_divisor / 5; | |
313 tck_dividend = tck_dividend / 5; | |
314 } | |
315 } | |
316 if (kstat_ctl == NULL) { | |
317 kstat_ctl = kstat_open(); | |
318 kid = kstat_ctl->kc_chain_id; | |
319 new_kstat = 1; | |
320 } else { | |
321 new_kid = kstat_chain_update(kstat_ctl); | |
322 if (new_kid < 0) { | |
323 res=kstat_close(kstat_ctl); | |
324 kstat_ctl = kstat_open(); | |
325 kid = kstat_ctl->kc_chain_id; | |
326 new_kstat = 1; | |
327 } else if (new_kid > 0 && kid != new_kid) { | |
328 kid = new_kid; | |
329 new_kstat = 1; | |
330 } | |
331 } | |
332 if (new_kstat) { | |
333 cpu_count = 0; | |
334 for (kstat = kstat_ctl->kc_chain; kstat; kstat = kstat->ks_next)
{ | |
335 if (strncmp(kstat->ks_name, "cpu_stat", 8) == 0) { | |
336 kstat_cpu[cpu_count++]=kstat; | |
337 } | |
338 } | |
339 } | |
340 for (i = 0; i < cpu_count; i++) { | |
341 new_kid = kstat_read(kstat_ctl, kstat_cpu[i], NULL); | |
342 if (new_kid >= 0) { | |
343 cpu = ((cpu_stat_t *)kstat_cpu[i]->ks_data)->cpu_sysinfo; | |
344 if ( tck_divisor == 1 ) { | |
345 pvals[7] += (jlong)(((jlong)cpu.cpu[CPU_IDLE]) * tck_div
idend); | |
346 pvals[7] += (jlong)(((jlong)cpu.cpu[CPU_WAIT]) * tck_div
idend); | |
347 pvals[8] += (jlong)(((jlong)cpu.cpu[CPU_KERNEL]) * tck_d
ividend); | |
348 pvals[9] += (jlong)(((jlong)cpu.cpu[CPU_USER]) * tck_div
idend); | |
349 } else { | |
350 pvals[7] += (jlong)(((jlong)cpu.cpu[CPU_IDLE]) * tck_div
idend / tck_divisor); | |
351 pvals[7] += (jlong)(((jlong)cpu.cpu[CPU_WAIT]) * tck_div
idend / tck_divisor); | |
352 pvals[8] += (jlong)(((jlong)cpu.cpu[CPU_KERNEL]) * tck_d
ividend / tck_divisor); | |
353 pvals[9] += (jlong)(((jlong)cpu.cpu[CPU_USER]) * tck_div
idend / tck_divisor); | |
354 } | |
355 } | |
356 } | |
357 } | |
358 | |
359 /* | |
360 * The next two are not implemented yet for Solaris | |
361 * inf[4] - Amount of shared memory | |
362 * inf[5] - Memory used by buffers | |
363 * | |
364 */ | |
365 } | |
366 | |
367 #elif defined(DARWIN) | |
368 | |
369 uint64_t mem_total; | |
370 size_t len = sizeof(mem_total); | |
371 | |
372 vm_statistics_data_t vm_info; | |
373 mach_msg_type_number_t info_count = HOST_VM_INFO_COUNT; | |
374 | |
375 sysctlbyname("hw.memsize", &mem_total, &len, NULL, 0); | |
376 pvals[0] = (jlong)mem_total; | |
377 | |
378 host_statistics(mach_host_self (), HOST_VM_INFO, (host_info_t)&vm_info, &inf
o_count); | |
379 pvals[1] = (jlong)(((double)vm_info.free_count)*vm_page_size); | |
380 pvals[6] = (jlong)(100 - (pvals[1] * 100 / mem_total)); | |
381 rv = APR_SUCCESS; | |
382 | |
383 /* DARWIN */ | |
384 #else | |
385 rv = APR_ENOTIMPL; | |
386 #endif | |
387 (*e)->ReleaseLongArrayElements(e, inf, pvals, 0); | |
388 return rv; | |
389 } | |
390 | |
391 #define LOG_MSG_DOMAIN "Native" | |
392 | |
393 | |
394 TCN_IMPLEMENT_CALL(jstring, OS, expand)(TCN_STDARGS, jstring val) | |
395 { | |
396 jstring str; | |
397 TCN_ALLOC_CSTRING(val); | |
398 | |
399 UNREFERENCED(o); | |
400 | |
401 /* TODO: Make ${ENVAR} expansion */ | |
402 str = (*e)->NewStringUTF(e, J2S(val)); | |
403 | |
404 TCN_FREE_CSTRING(val); | |
405 return str; | |
406 } | |
407 | |
408 TCN_IMPLEMENT_CALL(void, OS, sysloginit)(TCN_STDARGS, jstring domain) | |
409 { | |
410 const char *d; | |
411 TCN_ALLOC_CSTRING(domain); | |
412 | |
413 UNREFERENCED(o); | |
414 if ((d = J2S(domain)) == NULL) | |
415 d = LOG_MSG_DOMAIN; | |
416 | |
417 openlog(d, LOG_CONS | LOG_PID, LOG_LOCAL0); | |
418 TCN_FREE_CSTRING(domain); | |
419 } | |
420 | |
421 TCN_IMPLEMENT_CALL(void, OS, syslog)(TCN_STDARGS, jint level, | |
422 jstring msg) | |
423 { | |
424 TCN_ALLOC_CSTRING(msg); | |
425 int id = LOG_DEBUG; | |
426 UNREFERENCED(o); | |
427 | |
428 switch (level) { | |
429 case TCN_LOG_EMERG: | |
430 id = LOG_EMERG; | |
431 break; | |
432 case TCN_LOG_ERROR: | |
433 id = LOG_ERR; | |
434 break; | |
435 case TCN_LOG_NOTICE: | |
436 id = LOG_NOTICE; | |
437 break; | |
438 case TCN_LOG_WARN: | |
439 id = LOG_WARN; | |
440 break; | |
441 case TCN_LOG_INFO: | |
442 id = LOG_INFO; | |
443 break; | |
444 } | |
445 syslog (id, "%s", J2S(msg)); | |
446 | |
447 TCN_FREE_CSTRING(msg); | |
448 } | |
449 | |
450 #endif | |
451 | |
OLD | NEW |