| 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 |