1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stddef.h> 30 #include <kstat.h> 31 32 #include "jkstat.h" 33 34 /* 35 * Class descriptors 36 */ 37 #define DOUBLE_CLASS_DESC "java/lang/Double" 38 #define LONG_CLASS_DESC "java/lang/Long" 39 #define UI64_CLASS_DESC "com/sun/solaris/service/pools/UnsignedInt64" 40 #define HRTIME_CLASS_DESC "com/sun/solaris/service/pools/HRTime" 41 #define KSTAT_CLASS_DESC "com/sun/solaris/service/kstat/Kstat" 42 #define KSTATCTL_CLASS_DESC "com/sun/solaris/service/kstat/KstatCtl" 43 #define KSTAT_READ_EX_CLASS_DESC \ 44 "com/sun/solaris/service/kstat/KstatReadException" 45 #define KSTAT_TNS_EX_CLASS_DESC \ 46 "com/sun/solaris/service/kstat/KstatTypeNotSupportedException" 47 #define THROWABLE_CLASS_DESC "java/lang/Throwable" 48 49 #define CLASS_FIELD_DESC(class_desc) "L" class_desc ";" 50 51 /* 52 * Cached class, method, and field IDs. 53 */ 54 static jclass doubleclass; 55 static jclass hrtimeclass; 56 static jclass kstatclass; 57 static jclass kstatctlclass; 58 static jclass longclass; 59 static jclass ui64class; 60 static jfieldID kstat_kctl_fieldid; 61 static jfieldID kstat_ksp_fieldid; 62 static jfieldID kstatctl_kctl_fieldid; 63 static jmethodID doublecons_mid; 64 static jmethodID hrtimecons_mid; 65 static jmethodID kstatcons_mid; 66 static jmethodID longcons_mid; 67 static jmethodID ui64cons_mid; 68 69 static jobject 70 makeUnsignedInt64(JNIEnv *env, uint64_t value) 71 { 72 jobject valueObj; 73 jobject byteArray; 74 jbyte *bytes; 75 int i; 76 77 if (!(byteArray = (*env)->NewByteArray(env, 9))) 78 return (NULL); /* OutOfMemoryError thrown */ 79 if (!(bytes = (*env)->GetByteArrayElements(env, byteArray, NULL))) 80 return (NULL); /* OutOfMemoryError thrown */ 81 82 /* 83 * Interpret the uint64_t as a 9-byte big-endian signed quantity 84 * suitable for constructing an UnsignedInt64 or BigInteger. 85 */ 86 for (i = 8; i >= 1; i--) { 87 bytes[i] = value & 0xff; 88 value >>= 8; 89 } 90 bytes[0] = 0; 91 (*env)->ReleaseByteArrayElements(env, byteArray, bytes, 0); 92 93 if (!(valueObj = (*env)->NewObject(env, ui64class, ui64cons_mid, 94 byteArray))) 95 return (NULL); /* exception thrown */ 96 97 return (valueObj); 98 } 99 100 /* 101 * Return a Long object with the given value. 102 */ 103 static jobject 104 makeLong(JNIEnv *env, jlong value) 105 { 106 jobject valueObj; 107 108 if (!(valueObj = (*env)->NewObject(env, longclass, longcons_mid, 109 value))) 110 return (NULL); /* exception thrown */ 111 112 return (valueObj); 113 } 114 115 /* 116 * Return a Double object with the given value. 117 */ 118 static jobject 119 makeDouble(JNIEnv *env, jdouble value) 120 { 121 jobject valueObj; 122 123 if (!(valueObj = (*env)->NewObject(env, doubleclass, doublecons_mid, 124 value))) 125 return (NULL); /* exception thrown */ 126 127 return (valueObj); 128 } 129 130 /* 131 * Returns the kctl_t * from kstat_open(3kstat). 132 */ 133 /*ARGSUSED*/ 134 JNIEXPORT jlong JNICALL 135 Java_com_sun_solaris_service_kstat_KstatCtl_open(JNIEnv *env, jobject obj) 136 { 137 return ((jlong)(uintptr_t)kstat_open()); 138 } 139 140 /* 141 * Invokes kstat_close(3kstat). 142 */ 143 /*ARGSUSED*/ 144 JNIEXPORT jint JNICALL 145 Java_com_sun_solaris_service_kstat_KstatCtl_close(JNIEnv *env, jobject obj, 146 jlong kctl) 147 { 148 if (kctl) 149 return (kstat_close((kstat_ctl_t *)(uintptr_t)kctl)); 150 else 151 return (0); 152 } 153 154 /* 155 * Invoke kstat_read(3kstat) for the given Kstat object. 156 */ 157 JNIEXPORT void JNICALL Java_com_sun_solaris_service_kstat_Kstat_read( 158 JNIEnv *env, jobject obj) 159 { 160 kstat_ctl_t *kctl = 161 ((kstat_ctl_t *)(uintptr_t)(*env)->GetLongField(env, obj, 162 kstat_kctl_fieldid)); 163 kstat_t *ksp = ((kstat_t *)(uintptr_t)(*env)->GetLongField(env, obj, 164 kstat_ksp_fieldid)); 165 kid_t kid; 166 167 if (!ksp || !kctl) 168 return; /* exception thronw */ 169 170 kid = kstat_read((kstat_ctl_t *)kctl, (kstat_t *)ksp, NULL); 171 if (kid == -1) { 172 jclass e; 173 if (!(e = (*env)->FindClass(env, KSTAT_READ_EX_CLASS_DESC))) 174 return; /* exception thrown */ 175 176 (*env)->Throw(env, (*env)->NewObject(env, e, 177 (*env)->GetStaticMethodID(env, e, "<init>", 178 "()" CLASS_FIELD_DESC(THROWABLE_CLASS_DESC)))); 179 } 180 } 181 182 /* 183 * Return a Kstat object corresponding to the result of 184 * kstat_lookup(3kstat). 185 */ 186 JNIEXPORT jobject JNICALL 187 Java_com_sun_solaris_service_kstat_KstatCtl_lookup(JNIEnv *env, jobject obj, 188 jstring moduleObj, jint instance, jstring nameObj) 189 { 190 const char *module = NULL; 191 const char *name = NULL; 192 kstat_ctl_t *kctl; 193 kstat_t *ksp; 194 jobject kstatObject = NULL; 195 196 if (moduleObj == NULL || nameObj == NULL) 197 return (NULL); 198 199 if (!(module = (*env)->GetStringUTFChars(env, moduleObj, NULL))) 200 goto done; /* exception thrown */ 201 if (!(name = (*env)->GetStringUTFChars(env, nameObj, NULL))) 202 goto done; /* exception thrown */ 203 204 kctl = (kstat_ctl_t *)(uintptr_t)(*env)->GetLongField(env, obj, 205 kstatctl_kctl_fieldid); 206 ksp = kstat_lookup(kctl, (char *)module, instance, (char *)name); 207 if (ksp) 208 kstatObject = (*env)->NewObject(env, kstatclass, kstatcons_mid, 209 (jlong)(uintptr_t)kctl, (jlong)(uintptr_t)ksp); 210 211 done: 212 if (name) 213 (*env)->ReleaseStringUTFChars(env, nameObj, name); 214 if (module) 215 (*env)->ReleaseStringUTFChars(env, moduleObj, module); 216 217 return (kstatObject); 218 } 219 220 /* 221 * Returns the named value -- the value of the named kstat, or field in 222 * a raw kstat, as applicable, and available. Returns <i>null</i> if no 223 * such named kstat or field is available. 224 * 225 * Throws KstatTypeNotSupportedException if the raw kstat is not 226 * understood. (Presently, none are.) 227 */ 228 JNIEXPORT jobject JNICALL 229 Java_com_sun_solaris_service_kstat_Kstat_getValue(JNIEnv *env, jobject obj, 230 jstring nameObj) 231 { 232 kstat_t *ksp = ((kstat_t *)(uintptr_t)(*env)->GetLongField(env, obj, 233 kstat_ksp_fieldid)); 234 jobject valueObj = NULL; 235 kstat_named_t *ksnp; 236 const char *name; 237 jclass exceptionClass; 238 239 if (!nameObj) 240 return (NULL); 241 242 if (!(name = (*env)->GetStringUTFChars(env, nameObj, NULL))) 243 return (NULL); /* exception thrown */ 244 245 if (!(exceptionClass = (*env)->FindClass(env, 246 KSTAT_TNS_EX_CLASS_DESC))) { 247 (*env)->ReleaseStringUTFChars(env, nameObj, name); 248 return (NULL); /* exception thrown */ 249 } 250 251 switch (ksp->ks_type) { 252 case KSTAT_TYPE_NAMED: 253 ksnp = kstat_data_lookup(ksp, (char *)name); 254 if (ksnp == NULL) 255 break; 256 switch (ksnp->data_type) { 257 case KSTAT_DATA_CHAR: 258 valueObj = makeLong(env, ksnp->value.c[0]); 259 break; 260 case KSTAT_DATA_INT32: 261 valueObj = makeLong(env, ksnp->value.i32); 262 break; 263 case KSTAT_DATA_UINT32: 264 valueObj = makeLong(env, ksnp->value.ui32); 265 break; 266 case KSTAT_DATA_INT64: 267 valueObj = makeLong(env, ksnp->value.i64); 268 break; 269 case KSTAT_DATA_UINT64: 270 valueObj = makeUnsignedInt64(env, ksnp->value.ui64); 271 break; 272 case KSTAT_DATA_STRING: 273 valueObj = (*env)->NewStringUTF(env, 274 KSTAT_NAMED_STR_PTR(ksnp)); 275 break; 276 case KSTAT_DATA_FLOAT: 277 valueObj = makeDouble(env, ksnp->value.f); 278 break; 279 case KSTAT_DATA_DOUBLE: 280 valueObj = makeDouble(env, ksnp->value.d); 281 break; 282 default: 283 goto fail; 284 } 285 break; 286 default: 287 goto fail; 288 } 289 290 (*env)->ReleaseStringUTFChars(env, nameObj, name); 291 return (valueObj); 292 293 fail: 294 (*env)->ReleaseStringUTFChars(env, nameObj, name); 295 (*env)->Throw(env, (*env)->NewObject(env, exceptionClass, 296 (*env)->GetStaticMethodID(env, exceptionClass, "<init>", 297 "()" CLASS_FIELD_DESC(THROWABLE_CLASS_DESC)))); 298 299 return (valueObj); 300 } 301 302 /* 303 * Given a Kstat object, return, as an HRTime object, its kstat_t's 304 * field at the given offset. 305 */ 306 static jobject 307 ksobj_get_hrtime(JNIEnv *env, jobject obj, offset_t ksfieldoff) 308 { 309 kstat_t *ksp = ((kstat_t *)(uintptr_t)(*env)->GetLongField(env, obj, 310 kstat_ksp_fieldid)); 311 312 if (!ksp) 313 return (NULL); /* exception thrown */ 314 315 return ((*env)->NewObject(env, hrtimeclass, hrtimecons_mid, 316 makeUnsignedInt64(env, *((hrtime_t *)ksp + ksfieldoff * 317 sizeof (hrtime_t))))); 318 } 319 320 /* 321 * Given a Kstat object, return as an HRTime object its ks_snaptime 322 * field. 323 */ 324 JNIEXPORT jobject JNICALL 325 Java_com_sun_solaris_service_kstat_Kstat_getSnapTime(JNIEnv *env, jobject obj) 326 { 327 return (ksobj_get_hrtime(env, obj, offsetof(kstat_t, ks_snaptime))); 328 } 329 330 /* 331 * Given a Kstat object, return as an HRTime object its ks_crtime 332 * field. 333 */ 334 JNIEXPORT jobject JNICALL 335 Java_com_sun_solaris_service_kstat_Kstat_getCreationTime(JNIEnv *env, 336 jobject obj) 337 { 338 return (ksobj_get_hrtime(env, obj, offsetof(kstat_t, ks_crtime))); 339 } 340 341 /* 342 * Invoke kstat_chain_update(3kstat) for the kstat chain corresponding 343 * to the given KstatCtl object. 344 */ 345 JNIEXPORT void JNICALL 346 Java_com_sun_solaris_service_kstat_KstatCtl_chainUpdate(JNIEnv *env, 347 jobject obj) 348 { 349 kstat_ctl_t *kctl; 350 351 kctl = (kstat_ctl_t *)(uintptr_t)(*env)->GetLongField(env, obj, 352 kstatctl_kctl_fieldid); 353 354 (void) kstat_chain_update(kctl); 355 } 356 357 /* 358 * Cache class, method, and field IDs. 359 */ 360 /*ARGSUSED*/ 361 JNIEXPORT void JNICALL 362 Java_com_sun_solaris_service_kstat_KstatCtl_init(JNIEnv *env, jclass clazz) 363 { 364 jclass doubleclass_lref; 365 jclass hrtimeclass_lref; 366 jclass kstatclass_lref; 367 jclass kstatctlclass_lref; 368 jclass longclass_lref; 369 jclass ui64class_lref; 370 371 if (!(doubleclass_lref = (*env)->FindClass(env, DOUBLE_CLASS_DESC))) 372 return; /* exception thrown */ 373 if (!(doubleclass = (*env)->NewGlobalRef(env, doubleclass_lref))) 374 return; /* exception thrown */ 375 if (!(doublecons_mid = (*env)->GetMethodID(env, doubleclass, "<init>", 376 "(D)V"))) 377 return; /* exception thrown */ 378 379 if (!(hrtimeclass_lref = (*env)->FindClass(env, HRTIME_CLASS_DESC))) 380 return; /* exception thrown */ 381 if (!(hrtimeclass = (*env)->NewGlobalRef(env, hrtimeclass_lref))) 382 return; /* exception thrown */ 383 if (!(hrtimecons_mid = (*env)->GetMethodID(env, hrtimeclass, "<init>", 384 "(" CLASS_FIELD_DESC(UI64_CLASS_DESC) ")V"))) 385 return; /* exception thrown */ 386 387 if (!(kstatclass_lref = (*env)->FindClass(env, KSTAT_CLASS_DESC))) 388 return; /* exception thrown */ 389 if (!(kstatclass = (*env)->NewGlobalRef(env, kstatclass_lref))) 390 return; /* exception thrown */ 391 if (!(kstatcons_mid = (*env)->GetMethodID(env, kstatclass, "<init>", 392 "(JJ)V"))) 393 return; /* exception thrown */ 394 if (!(kstat_kctl_fieldid = (*env)->GetFieldID(env, kstatclass, "kctl", 395 "J"))) 396 return; /* exception thrown */ 397 if (!(kstat_ksp_fieldid = (*env)->GetFieldID(env, kstatclass, "ksp", 398 "J"))) 399 return; /* exception thrown */ 400 401 if (!(kstatctlclass_lref = (*env)->FindClass(env, KSTATCTL_CLASS_DESC))) 402 return; /* exception thrown */ 403 if (!(kstatctlclass = (*env)->NewGlobalRef(env, kstatctlclass_lref))) 404 return; /* exception thrown */ 405 if (!(kstatctl_kctl_fieldid = (*env)->GetFieldID(env, kstatctlclass, 406 "kctl", "J"))) 407 return; /* exception thrown */ 408 409 if (!(longclass_lref = (*env)->FindClass(env, LONG_CLASS_DESC))) 410 return; /* exception thrown */ 411 if (!(longclass = (*env)->NewGlobalRef(env, longclass_lref))) 412 return; /* exception thrown */ 413 if (!(longcons_mid = (*env)->GetMethodID(env, longclass, "<init>", 414 "(J)V"))) 415 return; /* exception thrown */ 416 417 if (!(ui64class_lref = (*env)->FindClass(env, UI64_CLASS_DESC))) 418 return; /* exception thrown */ 419 if (!(ui64class = (*env)->NewGlobalRef(env, ui64class_lref))) 420 return; /* exception thrown */ 421 ui64cons_mid = (*env)->GetMethodID(env, ui64class, "<init>", "([B)V"); 422 } 423