#include <stddef.h>
#include <kstat.h>
#include "jkstat.h"
#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 ";"
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);
if (!(bytes = (*env)->GetByteArrayElements(env, byteArray, NULL)))
return (NULL);
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);
return (valueObj);
}
static jobject
makeLong(JNIEnv *env, jlong value)
{
jobject valueObj;
if (!(valueObj = (*env)->NewObject(env, longclass, longcons_mid,
value)))
return (NULL);
return (valueObj);
}
static jobject
makeDouble(JNIEnv *env, jdouble value)
{
jobject valueObj;
if (!(valueObj = (*env)->NewObject(env, doubleclass, doublecons_mid,
value)))
return (NULL);
return (valueObj);
}
JNIEXPORT jlong JNICALL
Java_com_sun_solaris_service_kstat_KstatCtl_open(JNIEnv *env, jobject obj)
{
return ((jlong)(uintptr_t)kstat_open());
}
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);
}
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;
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;
(*env)->Throw(env, (*env)->NewObject(env, e,
(*env)->GetStaticMethodID(env, e, "<init>",
"()" CLASS_FIELD_DESC(THROWABLE_CLASS_DESC))));
}
}
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;
if (!(name = (*env)->GetStringUTFChars(env, nameObj, NULL)))
goto done;
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);
}
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);
if (!(exceptionClass = (*env)->FindClass(env,
KSTAT_TNS_EX_CLASS_DESC))) {
(*env)->ReleaseStringUTFChars(env, nameObj, name);
return (NULL);
}
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, "<init>",
"()" CLASS_FIELD_DESC(THROWABLE_CLASS_DESC))));
return (valueObj);
}
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);
return ((*env)->NewObject(env, hrtimeclass, hrtimecons_mid,
makeUnsignedInt64(env, *((hrtime_t *)ksp + ksfieldoff *
sizeof (hrtime_t)))));
}
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)));
}
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)));
}
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);
}
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;
if (!(doubleclass = (*env)->NewGlobalRef(env, doubleclass_lref)))
return;
if (!(doublecons_mid = (*env)->GetMethodID(env, doubleclass, "<init>",
"(D)V")))
return;
if (!(hrtimeclass_lref = (*env)->FindClass(env, HRTIME_CLASS_DESC)))
return;
if (!(hrtimeclass = (*env)->NewGlobalRef(env, hrtimeclass_lref)))
return;
if (!(hrtimecons_mid = (*env)->GetMethodID(env, hrtimeclass, "<init>",
"(" CLASS_FIELD_DESC(UI64_CLASS_DESC) ")V")))
return;
if (!(kstatclass_lref = (*env)->FindClass(env, KSTAT_CLASS_DESC)))
return;
if (!(kstatclass = (*env)->NewGlobalRef(env, kstatclass_lref)))
return;
if (!(kstatcons_mid = (*env)->GetMethodID(env, kstatclass, "<init>",
"(JJ)V")))
return;
if (!(kstat_kctl_fieldid = (*env)->GetFieldID(env, kstatclass, "kctl",
"J")))
return;
if (!(kstat_ksp_fieldid = (*env)->GetFieldID(env, kstatclass, "ksp",
"J")))
return;
if (!(kstatctlclass_lref = (*env)->FindClass(env, KSTATCTL_CLASS_DESC)))
return;
if (!(kstatctlclass = (*env)->NewGlobalRef(env, kstatctlclass_lref)))
return;
if (!(kstatctl_kctl_fieldid = (*env)->GetFieldID(env, kstatctlclass,
"kctl", "J")))
return;
if (!(longclass_lref = (*env)->FindClass(env, LONG_CLASS_DESC)))
return;
if (!(longclass = (*env)->NewGlobalRef(env, longclass_lref)))
return;
if (!(longcons_mid = (*env)->GetMethodID(env, longclass, "<init>",
"(J)V")))
return;
if (!(ui64class_lref = (*env)->FindClass(env, UI64_CLASS_DESC)))
return;
if (!(ui64class = (*env)->NewGlobalRef(env, ui64class_lref)))
return;
ui64cons_mid = (*env)->GetMethodID(env, ui64class, "<init>", "([B)V");
}