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