/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include #include "jkstat.h" /* * Class descriptors */ #define DOUBLE_CLASS_DESC "java/lang/Double" #define LONG_CLASS_DESC "java/lang/Long" #define UI64_CLASS_DESC "com/sun/solaris/service/pools/UnsignedInt64" #define HRTIME_CLASS_DESC "com/sun/solaris/service/pools/HRTime" #define KSTAT_CLASS_DESC "com/sun/solaris/service/kstat/Kstat" #define KSTATCTL_CLASS_DESC "com/sun/solaris/service/kstat/KstatCtl" #define KSTAT_READ_EX_CLASS_DESC \ "com/sun/solaris/service/kstat/KstatReadException" #define KSTAT_TNS_EX_CLASS_DESC \ "com/sun/solaris/service/kstat/KstatTypeNotSupportedException" #define THROWABLE_CLASS_DESC "java/lang/Throwable" #define CLASS_FIELD_DESC(class_desc) "L" class_desc ";" /* * Cached class, method, and field IDs. */ static jclass doubleclass; static jclass hrtimeclass; static jclass kstatclass; static jclass kstatctlclass; static jclass longclass; static jclass ui64class; static jfieldID kstat_kctl_fieldid; static jfieldID kstat_ksp_fieldid; static jfieldID kstatctl_kctl_fieldid; static jmethodID doublecons_mid; static jmethodID hrtimecons_mid; static jmethodID kstatcons_mid; static jmethodID longcons_mid; static jmethodID ui64cons_mid; static jobject makeUnsignedInt64(JNIEnv *env, uint64_t value) { jobject valueObj; jobject byteArray; jbyte *bytes; int i; if (!(byteArray = (*env)->NewByteArray(env, 9))) return (NULL); /* OutOfMemoryError thrown */ if (!(bytes = (*env)->GetByteArrayElements(env, byteArray, NULL))) return (NULL); /* OutOfMemoryError thrown */ /* * Interpret the uint64_t as a 9-byte big-endian signed quantity * suitable for constructing an UnsignedInt64 or BigInteger. */ for (i = 8; i >= 1; i--) { bytes[i] = value & 0xff; value >>= 8; } bytes[0] = 0; (*env)->ReleaseByteArrayElements(env, byteArray, bytes, 0); if (!(valueObj = (*env)->NewObject(env, ui64class, ui64cons_mid, byteArray))) return (NULL); /* exception thrown */ return (valueObj); } /* * Return a Long object with the given value. */ static jobject makeLong(JNIEnv *env, jlong value) { jobject valueObj; if (!(valueObj = (*env)->NewObject(env, longclass, longcons_mid, value))) return (NULL); /* exception thrown */ return (valueObj); } /* * Return a Double object with the given value. */ static jobject makeDouble(JNIEnv *env, jdouble value) { jobject valueObj; if (!(valueObj = (*env)->NewObject(env, doubleclass, doublecons_mid, value))) return (NULL); /* exception thrown */ return (valueObj); } /* * Returns the kctl_t * from kstat_open(3kstat). */ /*ARGSUSED*/ JNIEXPORT jlong JNICALL Java_com_sun_solaris_service_kstat_KstatCtl_open(JNIEnv *env, jobject obj) { return ((jlong)(uintptr_t)kstat_open()); } /* * Invokes kstat_close(3kstat). */ /*ARGSUSED*/ JNIEXPORT jint JNICALL Java_com_sun_solaris_service_kstat_KstatCtl_close(JNIEnv *env, jobject obj, jlong kctl) { if (kctl) return (kstat_close((kstat_ctl_t *)(uintptr_t)kctl)); else return (0); } /* * Invoke kstat_read(3kstat) for the given Kstat object. */ JNIEXPORT void JNICALL Java_com_sun_solaris_service_kstat_Kstat_read( JNIEnv *env, jobject obj) { kstat_ctl_t *kctl = ((kstat_ctl_t *)(uintptr_t)(*env)->GetLongField(env, obj, kstat_kctl_fieldid)); kstat_t *ksp = ((kstat_t *)(uintptr_t)(*env)->GetLongField(env, obj, kstat_ksp_fieldid)); kid_t kid; if (!ksp || !kctl) return; /* exception thronw */ kid = kstat_read((kstat_ctl_t *)kctl, (kstat_t *)ksp, NULL); if (kid == -1) { jclass e; if (!(e = (*env)->FindClass(env, KSTAT_READ_EX_CLASS_DESC))) return; /* exception thrown */ (*env)->Throw(env, (*env)->NewObject(env, e, (*env)->GetStaticMethodID(env, e, "", "()" CLASS_FIELD_DESC(THROWABLE_CLASS_DESC)))); } } /* * Return a Kstat object corresponding to the result of * kstat_lookup(3kstat). */ JNIEXPORT jobject JNICALL Java_com_sun_solaris_service_kstat_KstatCtl_lookup(JNIEnv *env, jobject obj, jstring moduleObj, jint instance, jstring nameObj) { const char *module = NULL; const char *name = NULL; kstat_ctl_t *kctl; kstat_t *ksp; jobject kstatObject = NULL; if (moduleObj == NULL || nameObj == NULL) return (NULL); if (!(module = (*env)->GetStringUTFChars(env, moduleObj, NULL))) goto done; /* exception thrown */ if (!(name = (*env)->GetStringUTFChars(env, nameObj, NULL))) goto done; /* exception thrown */ kctl = (kstat_ctl_t *)(uintptr_t)(*env)->GetLongField(env, obj, kstatctl_kctl_fieldid); ksp = kstat_lookup(kctl, (char *)module, instance, (char *)name); if (ksp) kstatObject = (*env)->NewObject(env, kstatclass, kstatcons_mid, (jlong)(uintptr_t)kctl, (jlong)(uintptr_t)ksp); done: if (name) (*env)->ReleaseStringUTFChars(env, nameObj, name); if (module) (*env)->ReleaseStringUTFChars(env, moduleObj, module); return (kstatObject); } /* * Returns the named value -- the value of the named kstat, or field in * a raw kstat, as applicable, and available. Returns null if no * such named kstat or field is available. * * Throws KstatTypeNotSupportedException if the raw kstat is not * understood. (Presently, none are.) */ JNIEXPORT jobject JNICALL Java_com_sun_solaris_service_kstat_Kstat_getValue(JNIEnv *env, jobject obj, jstring nameObj) { kstat_t *ksp = ((kstat_t *)(uintptr_t)(*env)->GetLongField(env, obj, kstat_ksp_fieldid)); jobject valueObj = NULL; kstat_named_t *ksnp; const char *name; jclass exceptionClass; if (!nameObj) return (NULL); if (!(name = (*env)->GetStringUTFChars(env, nameObj, NULL))) return (NULL); /* exception thrown */ if (!(exceptionClass = (*env)->FindClass(env, KSTAT_TNS_EX_CLASS_DESC))) { (*env)->ReleaseStringUTFChars(env, nameObj, name); return (NULL); /* exception thrown */ } switch (ksp->ks_type) { case KSTAT_TYPE_NAMED: ksnp = kstat_data_lookup(ksp, (char *)name); if (ksnp == NULL) break; switch (ksnp->data_type) { case KSTAT_DATA_CHAR: valueObj = makeLong(env, ksnp->value.c[0]); break; case KSTAT_DATA_INT32: valueObj = makeLong(env, ksnp->value.i32); break; case KSTAT_DATA_UINT32: valueObj = makeLong(env, ksnp->value.ui32); break; case KSTAT_DATA_INT64: valueObj = makeLong(env, ksnp->value.i64); break; case KSTAT_DATA_UINT64: valueObj = makeUnsignedInt64(env, ksnp->value.ui64); break; case KSTAT_DATA_STRING: valueObj = (*env)->NewStringUTF(env, KSTAT_NAMED_STR_PTR(ksnp)); break; case KSTAT_DATA_FLOAT: valueObj = makeDouble(env, ksnp->value.f); break; case KSTAT_DATA_DOUBLE: valueObj = makeDouble(env, ksnp->value.d); break; default: goto fail; } break; default: goto fail; } (*env)->ReleaseStringUTFChars(env, nameObj, name); return (valueObj); fail: (*env)->ReleaseStringUTFChars(env, nameObj, name); (*env)->Throw(env, (*env)->NewObject(env, exceptionClass, (*env)->GetStaticMethodID(env, exceptionClass, "", "()" CLASS_FIELD_DESC(THROWABLE_CLASS_DESC)))); return (valueObj); } /* * Given a Kstat object, return, as an HRTime object, its kstat_t's * field at the given offset. */ static jobject ksobj_get_hrtime(JNIEnv *env, jobject obj, offset_t ksfieldoff) { kstat_t *ksp = ((kstat_t *)(uintptr_t)(*env)->GetLongField(env, obj, kstat_ksp_fieldid)); if (!ksp) return (NULL); /* exception thrown */ return ((*env)->NewObject(env, hrtimeclass, hrtimecons_mid, makeUnsignedInt64(env, *((hrtime_t *)ksp + ksfieldoff * sizeof (hrtime_t))))); } /* * Given a Kstat object, return as an HRTime object its ks_snaptime * field. */ JNIEXPORT jobject JNICALL Java_com_sun_solaris_service_kstat_Kstat_getSnapTime(JNIEnv *env, jobject obj) { return (ksobj_get_hrtime(env, obj, offsetof(kstat_t, ks_snaptime))); } /* * Given a Kstat object, return as an HRTime object its ks_crtime * field. */ JNIEXPORT jobject JNICALL Java_com_sun_solaris_service_kstat_Kstat_getCreationTime(JNIEnv *env, jobject obj) { return (ksobj_get_hrtime(env, obj, offsetof(kstat_t, ks_crtime))); } /* * Invoke kstat_chain_update(3kstat) for the kstat chain corresponding * to the given KstatCtl object. */ JNIEXPORT void JNICALL Java_com_sun_solaris_service_kstat_KstatCtl_chainUpdate(JNIEnv *env, jobject obj) { kstat_ctl_t *kctl; kctl = (kstat_ctl_t *)(uintptr_t)(*env)->GetLongField(env, obj, kstatctl_kctl_fieldid); (void) kstat_chain_update(kctl); } /* * Cache class, method, and field IDs. */ /*ARGSUSED*/ JNIEXPORT void JNICALL Java_com_sun_solaris_service_kstat_KstatCtl_init(JNIEnv *env, jclass clazz) { jclass doubleclass_lref; jclass hrtimeclass_lref; jclass kstatclass_lref; jclass kstatctlclass_lref; jclass longclass_lref; jclass ui64class_lref; if (!(doubleclass_lref = (*env)->FindClass(env, DOUBLE_CLASS_DESC))) return; /* exception thrown */ if (!(doubleclass = (*env)->NewGlobalRef(env, doubleclass_lref))) return; /* exception thrown */ if (!(doublecons_mid = (*env)->GetMethodID(env, doubleclass, "", "(D)V"))) return; /* exception thrown */ if (!(hrtimeclass_lref = (*env)->FindClass(env, HRTIME_CLASS_DESC))) return; /* exception thrown */ if (!(hrtimeclass = (*env)->NewGlobalRef(env, hrtimeclass_lref))) return; /* exception thrown */ if (!(hrtimecons_mid = (*env)->GetMethodID(env, hrtimeclass, "", "(" CLASS_FIELD_DESC(UI64_CLASS_DESC) ")V"))) return; /* exception thrown */ if (!(kstatclass_lref = (*env)->FindClass(env, KSTAT_CLASS_DESC))) return; /* exception thrown */ if (!(kstatclass = (*env)->NewGlobalRef(env, kstatclass_lref))) return; /* exception thrown */ if (!(kstatcons_mid = (*env)->GetMethodID(env, kstatclass, "", "(JJ)V"))) return; /* exception thrown */ if (!(kstat_kctl_fieldid = (*env)->GetFieldID(env, kstatclass, "kctl", "J"))) return; /* exception thrown */ if (!(kstat_ksp_fieldid = (*env)->GetFieldID(env, kstatclass, "ksp", "J"))) return; /* exception thrown */ if (!(kstatctlclass_lref = (*env)->FindClass(env, KSTATCTL_CLASS_DESC))) return; /* exception thrown */ if (!(kstatctlclass = (*env)->NewGlobalRef(env, kstatctlclass_lref))) return; /* exception thrown */ if (!(kstatctl_kctl_fieldid = (*env)->GetFieldID(env, kstatctlclass, "kctl", "J"))) return; /* exception thrown */ if (!(longclass_lref = (*env)->FindClass(env, LONG_CLASS_DESC))) return; /* exception thrown */ if (!(longclass = (*env)->NewGlobalRef(env, longclass_lref))) return; /* exception thrown */ if (!(longcons_mid = (*env)->GetMethodID(env, longclass, "", "(J)V"))) return; /* exception thrown */ if (!(ui64class_lref = (*env)->FindClass(env, UI64_CLASS_DESC))) return; /* exception thrown */ if (!(ui64class = (*env)->NewGlobalRef(env, ui64class_lref))) return; /* exception thrown */ ui64cons_mid = (*env)->GetMethodID(env, ui64class, "", "([B)V"); }