sigar/bindings/java/src/jni/win32/pdh.c
2007-03-03 22:20:24 +00:00

425 lines
13 KiB
C

/*
* Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
* This file is part of SIGAR.
*
* SIGAR is free software; you can redistribute it and/or modify
* it under the terms version 2 of the GNU General Public License as
* published by the Free Software Foundation. This program is distributed
* in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
#ifdef WIN32
#include <pdh.h>
#include <pdhmsg.h>
#include "win32bindings.h"
#include "javasigar.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef PDH_ACCESS_DENIED
#define PDH_ACCESS_DENIED ((DWORD)0xC0000BDBL)
#endif
/**
* Hack around not being able to format error codes using
* FORMAT_MESSAGE_FROM_HMODULE. We only define the error
* codes that could be possibly returned.
*/
static char *get_error_message(PDH_STATUS status) {
switch (status) {
case PDH_CSTATUS_NO_MACHINE:
return "The computer is unavailable";
case PDH_CSTATUS_NO_OBJECT:
return "The specified object could not be found on the computer";
case PDH_INVALID_ARGUMENT:
return "A required argument is invalid";
case PDH_MEMORY_ALLOCATION_FAILURE:
return "A required temporary buffer could not be allocated";
case PDH_INVALID_HANDLE:
return "The query handle is not valid";
case PDH_NO_DATA:
return "The query does not currently have any counters";
case PDH_CSTATUS_BAD_COUNTERNAME:
return "The counter name path string could not be parsed or "
"interpreted";
case PDH_CSTATUS_NO_COUNTER:
return "The specified counter was not found";
case PDH_CSTATUS_NO_COUNTERNAME:
return "An empty counter name path string was passed in";
case PDH_FUNCTION_NOT_FOUND:
return "The calculation function for this counter could not "
"be determined";
case PDH_ACCESS_DENIED:
return "Access denied";
default:
return "Unknown error";
}
}
JNIEXPORT void SIGAR_JNI(win32_Pdh_pdhConnectMachine)
(JNIEnv *env, jobject cur, jstring jhost)
{
PDH_STATUS status;
LPCTSTR host = JENV->GetStringUTFChars(env, jhost, NULL);
status = PdhConnectMachine(host);
JENV->ReleaseStringUTFChars(env, jhost, host);
if (status != ERROR_SUCCESS) {
win32_throw_exception(env, get_error_message(status));
}
}
JNIEXPORT jlong JNICALL SIGAR_JNI(win32_Pdh_pdhOpenQuery)
(JNIEnv *env, jobject cur)
{
HQUERY h_query;
PDH_STATUS status;
status = PdhOpenQuery(NULL, 0, &h_query);
if (status != ERROR_SUCCESS) {
win32_throw_exception(env, get_error_message(status));
return 0;
}
return (jlong)h_query;
}
JNIEXPORT void SIGAR_JNI(win32_Pdh_pdhCloseQuery)
(JNIEnv *env, jclass cur, jlong query)
{
HQUERY h_query = (HQUERY)query;
PDH_STATUS status;
// Close the query and the log file.
status = PdhCloseQuery(h_query);
if (status != ERROR_SUCCESS) {
win32_throw_exception(env, get_error_message(status));
return;
}
}
JNIEXPORT jlong SIGAR_JNI(win32_Pdh_pdhAddCounter)
(JNIEnv *env, jclass cur, jlong query, jstring cp)
{
HCOUNTER h_counter;
HQUERY h_query = (HQUERY)query;
PDH_STATUS status;
LPCTSTR counter_path = JENV->GetStringUTFChars(env, cp, NULL);
/* Add the counter that created the data in the log file. */
status = PdhAddCounter(h_query, counter_path, 0, &h_counter);
if (status == PDH_CSTATUS_NO_COUNTER) {
/* if given counter does not exist,
* try the same name w/ "/sec" appended
*/
char counter_sec[MAX_PATH];
strcpy(counter_sec, counter_path);
strcat(counter_sec, "/sec");
status = PdhAddCounter(h_query, counter_sec, 0, &h_counter);
}
JENV->ReleaseStringUTFChars(env, cp, counter_path);
if (status != ERROR_SUCCESS) {
win32_throw_exception(env, get_error_message(status));
return 0;
}
return (jlong)h_counter;
}
JNIEXPORT void SIGAR_JNI(win32_Pdh_pdhRemoveCounter)
(JNIEnv *env, jclass cur, jlong counter)
{
HCOUNTER h_counter = (HCOUNTER)counter;
PDH_STATUS status;
status = PdhRemoveCounter(h_counter);
if (status != ERROR_SUCCESS) {
win32_throw_exception(env, get_error_message(status));
return;
}
}
JNIEXPORT jdouble SIGAR_JNI(win32_Pdh_pdhGetValue)
(JNIEnv *env, jclass cur, jlong query, jlong counter, jboolean fmt)
{
HCOUNTER h_counter = (HCOUNTER)counter;
HQUERY h_query = (HQUERY)query;
PDH_STATUS status;
PDH_RAW_COUNTER raw_value;
PDH_FMT_COUNTERVALUE fmt_value;
DWORD type;
status = PdhCollectQueryData(h_query);
if (status != ERROR_SUCCESS) {
win32_throw_exception(env, get_error_message(status));
return 0;
}
if (fmt) {
/* may require 2 counters, see msdn docs */
int i=0;
for (i=0; i<2; i++) {
status = PdhGetFormattedCounterValue(h_counter,
PDH_FMT_DOUBLE,
(LPDWORD)NULL,
&fmt_value);
if (status == ERROR_SUCCESS) {
break;
}
PdhCollectQueryData(h_query);
}
}
else {
status = PdhGetRawCounterValue(h_counter, &type, &raw_value);
}
if (status != ERROR_SUCCESS) {
win32_throw_exception(env, get_error_message(status));
return 0;
}
if (fmt) {
return fmt_value.doubleValue;
}
else {
return (jdouble)raw_value.FirstValue;
}
}
JNIEXPORT jobjectArray SIGAR_JNI(win32_Pdh_pdhGetInstances)
(JNIEnv *env, jclass cur, jstring cp)
{
PDH_STATUS status = ERROR_SUCCESS;
DWORD counter_list_size = 0;
DWORD instance_list_size = 8096;
LPTSTR instance_list_buf =
(LPTSTR)malloc ((instance_list_size * sizeof (TCHAR)));
LPTSTR cur_object = NULL;
LPCTSTR counter_path =
(LPCTSTR)JENV->GetStringUTFChars(env, cp, 0);
jobjectArray array = NULL;
status = PdhEnumObjectItems(NULL, NULL, counter_path, NULL,
&counter_list_size, instance_list_buf,
&instance_list_size, PERF_DETAIL_WIZARD,
FALSE);
if (status == PDH_MORE_DATA && instance_list_size > 0) {
// Allocate the buffers and try the call again.
if (instance_list_buf != NULL)
free(instance_list_buf);
instance_list_buf = (LPTSTR)malloc((instance_list_size *
sizeof (TCHAR)));
counter_list_size = 0;
status = PdhEnumObjectItems (NULL, NULL, counter_path,
NULL, &counter_list_size,
instance_list_buf,
&instance_list_size,
PERF_DETAIL_WIZARD, FALSE);
}
JENV->ReleaseStringUTFChars(env, cp, counter_path);
// Still may get PDH_ERROR_MORE data after the first reallocation,
// but that is OK for just browsing the instances
if (status == ERROR_SUCCESS || status == PDH_MORE_DATA) {
int i, count;
for (cur_object = instance_list_buf, count = 0;
*cur_object != 0;
cur_object += lstrlen(cur_object) + 1, count++);
array = JENV->NewObjectArray(env, count,
JENV->FindClass(env,
"java/lang/String"),
JENV->NewStringUTF(env, ""));
/* Walk the return instance list, creating an array */
for (cur_object = instance_list_buf, i = 0;
*cur_object != 0;
cur_object += lstrlen(cur_object) + 1, i++)
{
jstring s = JENV->NewStringUTF(env, cur_object);
JENV->SetObjectArrayElement(env, array, i, s);
}
} else {
if (instance_list_buf != NULL)
free(instance_list_buf);
// An error occured
win32_throw_exception(env, get_error_message(status));
return NULL;
}
if (instance_list_buf != NULL)
free(instance_list_buf);
return array;
}
JNIEXPORT jobjectArray SIGAR_JNI(win32_Pdh_pdhGetKeys)
(JNIEnv *env, jclass cur, jstring cp)
{
PDH_STATUS status = ERROR_SUCCESS;
DWORD counter_list_size = 8096;
DWORD instance_list_size = 0;
LPTSTR instance_list_buf =
(LPTSTR)malloc (counter_list_size * sizeof(TCHAR));
LPTSTR cur_object = NULL;
LPCTSTR counter_path = JENV->GetStringUTFChars(env, cp, 0);
jobjectArray array = NULL;
status = PdhEnumObjectItems(NULL, NULL, counter_path,
instance_list_buf, &counter_list_size,
NULL, &instance_list_size,
PERF_DETAIL_WIZARD, FALSE);
if (status == PDH_MORE_DATA) {
/* Allocate the buffers and try the call again. */
if (instance_list_buf != NULL)
free(instance_list_buf);
instance_list_buf = (LPTSTR)malloc(counter_list_size *
sizeof(TCHAR));
instance_list_size = 0;
status = PdhEnumObjectItems (NULL, NULL, counter_path,
instance_list_buf,
&counter_list_size, NULL,
&instance_list_size,
PERF_DETAIL_WIZARD, 0);
}
JENV->ReleaseStringUTFChars(env, cp, counter_path);
if (status == ERROR_SUCCESS || status == PDH_MORE_DATA) {
int i, count;
for (cur_object = instance_list_buf, count = 0;
*cur_object != 0;
cur_object += lstrlen(cur_object) + 1, count++);
array = JENV->NewObjectArray(env, count,
JENV->FindClass(env,
"java/lang/String"),
JENV->NewStringUTF(env, ""));
/* Walk the return instance list, creating an array */
for (cur_object = instance_list_buf, i = 0;
*cur_object != 0;
cur_object += lstrlen(cur_object) + 1, i++)
{
jstring s = JENV->NewStringUTF(env, cur_object);
JENV->SetObjectArrayElement(env, array, i, s);
}
} else {
// An error occured
if (instance_list_buf != NULL)
free(instance_list_buf);
// An error occured
win32_throw_exception(env, get_error_message(status));
return NULL;
}
if (instance_list_buf != NULL)
free(instance_list_buf);
return array;
}
JNIEXPORT jobjectArray SIGAR_JNI(win32_Pdh_pdhGetObjects)
(JNIEnv *env, jclass cur)
{
PDH_STATUS status;
DWORD list_size = 8096;
LPTSTR list_buf = (LPTSTR)malloc(list_size * sizeof(TCHAR));
LPTSTR cur_object;
DWORD i, num_objects = 0;
jobjectArray array = NULL;
status = PdhEnumObjects(NULL, NULL, list_buf, &list_size,
PERF_DETAIL_WIZARD, FALSE);
if (status == PDH_MORE_DATA) {
// Re-try call with a larger buffer
if (list_buf != NULL)
free(list_buf);
list_buf = (LPTSTR)malloc(list_size * sizeof(TCHAR));
status = PdhEnumObjects(NULL, NULL, list_buf, &list_size,
PERF_DETAIL_WIZARD, FALSE);
}
if (status != ERROR_SUCCESS) {
if (list_buf != NULL)
free(list_buf);
win32_throw_exception(env, get_error_message(status));
return NULL;
}
// Walk the return buffer counting the number of objects
for (cur_object = list_buf, num_objects = 0;
*cur_object != 0;
cur_object += lstrlen(cur_object) + 1, num_objects++);
array = JENV->NewObjectArray(env, num_objects,
JENV->FindClass(env,
"java/lang/String"),
JENV->NewStringUTF(env, ""));
for (cur_object = list_buf, i = 0;
*cur_object != 0;
cur_object += lstrlen(cur_object) + 1, i++)
{
jstring s = JENV->NewStringUTF(env, cur_object);
JENV->SetObjectArrayElement(env, array, i, s);
}
if (list_buf != NULL)
free(list_buf);
return array;
}
JNIEXPORT jstring SIGAR_JNI(win32_Pdh_pdhLookupPerfName)
(JNIEnv *env, jclass cur, jint index)
{
TCHAR path[8192];
DWORD len = sizeof(path);
PDH_STATUS status =
PdhLookupPerfNameByIndex(NULL, index, path, &len);
if (status == ERROR_SUCCESS) {
return JENV->NewStringUTF(env, path);
}
else {
win32_throw_exception(env, get_error_message(status));
return NULL;
}
}
#ifdef __cplusplus
}
#endif
#endif /* WIN32 */