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 2004 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 *)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 = ((kstat_ctl_t *)(*env)->GetLongField(env, obj, 161 kstat_kctl_fieldid)); 162 kstat_t *ksp = ((kstat_t *)(*env)->GetLongField(env, obj, 163 kstat_ksp_fieldid)); 164 kid_t kid; 165 166 if (!ksp || !kctl) 167 return; /* exception thronw */ 168 169 kid = kstat_read((kstat_ctl_t *)kctl, (kstat_t *)ksp, NULL); 170 if (kid == -1) { 171 jclass e; 172 if (!(e = (*env)->FindClass(env, KSTAT_READ_EX_CLASS_DESC))) 173 return; /* exception thrown */ 174 175 (*env)->Throw(env, (*env)->NewObject(env, e, 176 (*env)->GetStaticMethodID(env, e, "<init>", 177 "()" CLASS_FIELD_DESC(THROWABLE_CLASS_DESC)))); 178 } 179 } 180 181 /* 182 * Return a Kstat object corresponding to the result of 183 * kstat_lookup(3kstat). 184 */ 185 JNIEXPORT jobject JNICALL 186 Java_com_sun_solaris_service_kstat_KstatCtl_lookup(JNIEnv *env, jobject obj, 187 jstring moduleObj, jint instance, jstring nameObj) 188 { 189 const char *module = NULL; 190 const char *name = NULL; 191 kstat_ctl_t *kctl; 192 kstat_t *ksp; 193 jobject kstatObject = NULL; 194 195 if (moduleObj == NULL || nameObj == NULL) 196 return (NULL); 197 198 if (!(module = (*env)->GetStringUTFChars(env, moduleObj, NULL))) 199 goto done; /* exception thrown */ 200 if (!(name = (*env)->GetStringUTFChars(env, nameObj, NULL))) 201 goto done; /* exception thrown */ 202 203 kctl = (kstat_ctl_t *)(*env)->GetLongField(env, obj, 204 kstatctl_kctl_fieldid); 205 ksp = kstat_lookup(kctl, (char *)module, instance, (char *)name); 206 if (ksp) 207 kstatObject = (*env)->NewObject(env, kstatclass, kstatcons_mid, 208 (jlong)(uintptr_t)kctl, (jlong)(uintptr_t)ksp); 209 210 done: 211 if (name) 212 (*env)->ReleaseStringUTFChars(env, nameObj, name); 213 if (module) 214 (*env)->ReleaseStringUTFChars(env, moduleObj, module); 215 216 return (kstatObject); 217 } 218 219 /* 220 * Returns the named value -- the value of the named kstat, or field in 221 * a raw kstat, as applicable, and available. Returns <i>null</i> if no 222 * such named kstat or field is available. 223 * 224 * Throws KstatTypeNotSupportedException if the raw kstat is not 225 * understood. (Presently, none are.) 226 */ 227 JNIEXPORT jobject JNICALL 228 Java_com_sun_solaris_service_kstat_Kstat_getValue(JNIEnv *env, jobject obj, 229 jstring nameObj) 230 { 231 kstat_t *ksp = ((kstat_t *)(*env)->GetLongField(env, obj, 232 kstat_ksp_fieldid)); 233 jobject valueObj = NULL; 234 kstat_named_t *ksnp; 235 const char *name; 236 jclass exceptionClass; 237 238 if (!nameObj) 239 return (NULL); 240 241 if (!(name = (*env)->GetStringUTFChars(env, nameObj, NULL))) 242 return (NULL); /* exception thrown */ 243 244 if (!(exceptionClass = (*env)->FindClass(env, 245 KSTAT_TNS_EX_CLASS_DESC))) { 246 (*env)->ReleaseStringUTFChars(env, nameObj, name); 247 return (NULL); /* exception thrown */ 248 } 249 250 switch (ksp->ks_type) { 251 case KSTAT_TYPE_NAMED: 252 ksnp = kstat_data_lookup(ksp, (char *)name); 253 if (ksnp == NULL) 254 break; 255 switch (ksnp->data_type) { 256 case KSTAT_DATA_CHAR: 257 valueObj = makeLong(env, ksnp->value.c[0]); 258 break; 259 case KSTAT_DATA_INT32: 260 valueObj = makeLong(env, ksnp->value.i32); 261 break; 262 case KSTAT_DATA_UINT32: 263 valueObj = makeLong(env, ksnp->value.ui32); 264 break; 265 case KSTAT_DATA_INT64: 266 valueObj = makeLong(env, ksnp->value.i64); 267 break; 268 case KSTAT_DATA_UINT64: 269 valueObj = makeUnsignedInt64(env, ksnp->value.ui64); 270 break; 271 case KSTAT_DATA_STRING: 272 valueObj = (*env)->NewStringUTF(env, 273 KSTAT_NAMED_STR_PTR(ksnp)); 274 break; 275 case KSTAT_DATA_FLOAT: 276 valueObj = makeDouble(env, ksnp->value.f); 277 break; 278 case KSTAT_DATA_DOUBLE: 279 valueObj = makeDouble(env, ksnp->value.d); 280 break; 281 default: 282 goto fail; 283 } 284 break; 285 default: 286 goto fail; 287 } 288 289 (*env)->ReleaseStringUTFChars(env, nameObj, name); 290 return (valueObj); 291 292 fail: 293 (*env)->ReleaseStringUTFChars(env, nameObj, name); 294 (*env)->Throw(env, (*env)->NewObject(env, exceptionClass, 295 (*env)->GetStaticMethodID(env, exceptionClass, "<init>", 296 "()" CLASS_FIELD_DESC(THROWABLE_CLASS_DESC)))); 297 298 return (valueObj); 299 } 300 301 /* 302 * Given a Kstat object, return, as an HRTime object, its kstat_t's 303 * field at the given offset. 304 */ 305 static jobject 306 ksobj_get_hrtime(JNIEnv *env, jobject obj, offset_t ksfieldoff) 307 { 308 kstat_t *ksp = ((kstat_t *)(*env)->GetLongField(env, obj, 309 kstat_ksp_fieldid)); 310 311 if (!ksp) 312 return (NULL); /* exception thrown */ 313 314 return ((*env)->NewObject(env, hrtimeclass, hrtimecons_mid, 315 makeUnsignedInt64(env, *((hrtime_t *)ksp + ksfieldoff * 316 sizeof (hrtime_t))))); 317 } 318 319 /* 320 * Given a Kstat object, return as an HRTime object its ks_snaptime 321 * field. 322 */ 323 JNIEXPORT jobject JNICALL 324 Java_com_sun_solaris_service_kstat_Kstat_getSnapTime(JNIEnv *env, jobject obj) 325 { 326 return (ksobj_get_hrtime(env, obj, offsetof(kstat_t, ks_snaptime))); 327 } 328 329 /* 330 * Given a Kstat object, return as an HRTime object its ks_crtime 331 * field. 332 */ 333 JNIEXPORT jobject JNICALL 334 Java_com_sun_solaris_service_kstat_Kstat_getCreationTime(JNIEnv *env, 335 jobject obj) 336 { 337 return (ksobj_get_hrtime(env, obj, offsetof(kstat_t, ks_crtime))); 338 } 339 340 /* 341 * Invoke kstat_chain_update(3kstat) for the kstat chain corresponding 342 * to the given KstatCtl object. 343 */ 344 JNIEXPORT void JNICALL 345 Java_com_sun_solaris_service_kstat_KstatCtl_chainUpdate(JNIEnv *env, 346 jobject obj) 347 { 348 kstat_ctl_t *kctl; 349 350 kctl = (kstat_ctl_t *)(*env)->GetLongField(env, obj, 351 kstatctl_kctl_fieldid); 352 353 (void) kstat_chain_update(kctl); 354 } 355 356 /* 357 * Cache class, method, and field IDs. 358 */ 359 /*ARGSUSED*/ 360 JNIEXPORT void JNICALL 361 Java_com_sun_solaris_service_kstat_KstatCtl_init(JNIEnv *env, jclass clazz) 362 { 363 jclass doubleclass_lref; 364 jclass hrtimeclass_lref; 365 jclass kstatclass_lref; 366 jclass kstatctlclass_lref; 367 jclass longclass_lref; 368 jclass ui64class_lref; 369 370 if (!(doubleclass_lref = (*env)->FindClass(env, DOUBLE_CLASS_DESC))) 371 return; /* exception thrown */ 372 if (!(doubleclass = (*env)->NewGlobalRef(env, doubleclass_lref))) 373 return; /* exception thrown */ 374 if (!(doublecons_mid = (*env)->GetMethodID(env, doubleclass, "<init>", 375 "(D)V"))) 376 return; /* exception thrown */ 377 378 if (!(hrtimeclass_lref = (*env)->FindClass(env, HRTIME_CLASS_DESC))) 379 return; /* exception thrown */ 380 if (!(hrtimeclass = (*env)->NewGlobalRef(env, hrtimeclass_lref))) 381 return; /* exception thrown */ 382 if (!(hrtimecons_mid = (*env)->GetMethodID(env, hrtimeclass, "<init>", 383 "(" CLASS_FIELD_DESC(UI64_CLASS_DESC) ")V"))) 384 return; /* exception thrown */ 385 386 if (!(kstatclass_lref = (*env)->FindClass(env, KSTAT_CLASS_DESC))) 387 return; /* exception thrown */ 388 if (!(kstatclass = (*env)->NewGlobalRef(env, kstatclass_lref))) 389 return; /* exception thrown */ 390 if (!(kstatcons_mid = (*env)->GetMethodID(env, kstatclass, "<init>", 391 "(JJ)V"))) 392 return; /* exception thrown */ 393 if (!(kstat_kctl_fieldid = (*env)->GetFieldID(env, kstatclass, "kctl", 394 "J"))) 395 return; /* exception thrown */ 396 if (!(kstat_ksp_fieldid = (*env)->GetFieldID(env, kstatclass, "ksp", 397 "J"))) 398 return; /* exception thrown */ 399 400 if (!(kstatctlclass_lref = (*env)->FindClass(env, KSTATCTL_CLASS_DESC))) 401 return; /* exception thrown */ 402 if (!(kstatctlclass = (*env)->NewGlobalRef(env, kstatctlclass_lref))) 403 return; /* exception thrown */ 404 if (!(kstatctl_kctl_fieldid = (*env)->GetFieldID(env, kstatctlclass, 405 "kctl", "J"))) 406 return; /* exception thrown */ 407 408 if (!(longclass_lref = (*env)->FindClass(env, LONG_CLASS_DESC))) 409 return; /* exception thrown */ 410 if (!(longclass = (*env)->NewGlobalRef(env, longclass_lref))) 411 return; /* exception thrown */ 412 if (!(longcons_mid = (*env)->GetMethodID(env, longclass, "<init>", 413 "(J)V"))) 414 return; /* exception thrown */ 415 416 if (!(ui64class_lref = (*env)->FindClass(env, UI64_CLASS_DESC))) 417 return; /* exception thrown */ 418 if (!(ui64class = (*env)->NewGlobalRef(env, ui64class_lref))) 419 return; /* exception thrown */ 420 ui64cons_mid = (*env)->GetMethodID(env, ui64class, "<init>", "([B)V"); 421 } 422