From 3788c5d8c41de9f7de91bc0efb028ed5795d57a9 Mon Sep 17 00:00:00 2001 From: Lyor Goldstein Date: Mon, 20 Jul 2015 13:46:20 +0300 Subject: [PATCH] Added basic Pdh API implementation --- CHANGES.md | 1 + .../src/com/sun/jna/platform/win32/Pdh.java | 282 +++++++++++ .../com/sun/jna/platform/win32/PdhMsg.java | 193 ++++++++ .../com/sun/jna/platform/win32/WinPerf.java | 451 ++++++++++++++++++ .../win32/AbstractWin32TestSupport.java | 16 + .../com/sun/jna/platform/win32/PdhTest.java | 158 ++++++ 6 files changed, 1101 insertions(+) create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/Pdh.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/PdhMsg.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/WinPerf.java create mode 100644 contrib/platform/test/com/sun/jna/platform/win32/PdhTest.java diff --git a/CHANGES.md b/CHANGES.md index 44e173a1ee..a0d516b6b1 100755 --- a/CHANGES.md +++ b/CHANGES.md @@ -47,6 +47,7 @@ Features * [#432](https://github.com/twall/jna/pull/432): Added SetLocalTime definition to 'com.sun.jna.platform.win32.Kernel32' - [@lgoldstein](https://github.com/lgoldstein). * [#434](https://github.com/twall/jna/pull/434): Added GetEnvironmentStrings to 'com.sun.jna.platform.win32.Kernel32' - [@lgoldstein](https://github.com/lgoldstein). * Loosen OSGI OS name matching to accommodate Windows 8 family - Niels Bertram. +* [#436] (https://github.com/twall/jna/pull/469): Added basic Pdh API implementation to 'com.sun.jna.platform.win32' - [@lgoldstein](https://github.com/lgoldstein). Bug Fixes --------- diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Pdh.java b/contrib/platform/src/com/sun/jna/platform/win32/Pdh.java new file mode 100644 index 0000000000..737ba29937 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/Pdh.java @@ -0,0 +1,282 @@ +/* Copyright (c) 2015 Goldstein Lyor, All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + */ +package com.sun.jna.platform.win32; + +import java.util.Arrays; +import java.util.List; + +import com.sun.jna.Native; +import com.sun.jna.Structure; +import com.sun.jna.platform.win32.BaseTSD.DWORD_PTR; +import com.sun.jna.platform.win32.WinBase.FILETIME; +import com.sun.jna.platform.win32.WinDef.DWORDByReference; +import com.sun.jna.platform.win32.WinDef.LONGLONGByReference; +import com.sun.jna.platform.win32.WinNT.HANDLE; +import com.sun.jna.platform.win32.WinNT.HANDLEByReference; +import com.sun.jna.win32.StdCallLibrary; +import com.sun.jna.win32.W32APIOptions; + +/** + * Windows Performance Data Helper (a.k.a. PDH). + * @author Lyor Goldstein + * @see Performance Counters + */ +public interface Pdh extends StdCallLibrary { + Pdh INSTANCE = (Pdh) Native.loadLibrary("Pdh", + Pdh.class, W32APIOptions.UNICODE_OPTIONS); + + + /** Maximum counter name length. */ + public static final int PDH_MAX_COUNTER_NAME = 1024; + /** Maximum counter instance name length. */ + public static final int PDH_MAX_INSTANCE_NAME = 1024; + /** Maximum full counter path length. */ + public static final int PDH_MAX_COUNTER_PATH = 2048; + /** Maximum full counter log name length. */ + public static final int PDH_MAX_DATASOURCE_PATH = 1024; + + /* TODO + * LPVOID CALLBACK AllocateMemory(_In_ SIZE_T AllocSize,_In_ LPVOID pContext) + * void CALLBACK FreeMemory(LPVOID pBuffer,LPVOID pContext) + */ + + /** + * Connects to the specified computer. + * @param szMachineName The name of the computer to connect to. If + * {@code null}, PDH connects to the local computer. + * @return ERROR_SUCCESS if successful + * @see PdhConnectMachine + */ + int PdhConnectMachine(String szMachineName); + + // Known values for the PdhGetDllVersion result + public static final int PDH_CVERSION_WIN40 = 0x0400; + public static final int PDH_CVERSION_WIN50 = 0x0500; + // v1.1 revision of PDH -- basic log functions + // v1.2 of the PDH -- adds variable instance counters + // v1.3 of the PDH -- adds log service control & stubs for NT5/PDH v2 fn's + // v2.0 of the PDH -- is the NT v 5.0 B2 version + public static final int PDH_VERSION = PDH_CVERSION_WIN50 + 0x0003; + + /** + * Returns the version of the currently installed Pdh.dll file. + * @param lpdwVersion A variable that receives the version of Pdh.dll. + * @return ERROR_SUCCESS if successful + * @see PdhGetDllVersion + */ + int PdhGetDllVersion(DWORDByReference lpdwVersion); + + /** + * Creates a new query that is used to manage the collection of performance data. + * @param szDataSource The name of the log file from which to retrieve performance data. + * If {@code null}, performance data is collected from a real-time data source. + * @param dwUserData User-defined value to associate with this query. + * @param phQuery (Out) Handle to the query. You use this handle in subsequent calls. + * @return ERROR_SUCCESS if successful + * @see PdhOpenQuery + */ + int PdhOpenQuery(String szDataSource, DWORD_PTR dwUserData, HANDLEByReference phQuery); + + /** + * Closes all counters contained in the specified query, closes all + * handles related to the query, and frees all memory associated with + * the query. + * @param hQuery Handle to the query to close. + * @return ERROR_SUCCESS if successful + * @see PdhCloseQuery + */ + int PdhCloseQuery(HANDLE hQuery); + + /** + * Components of a counter path + * @see PDH_COUNTER_PATH_ELEMENTS + * @see Windows Server 2003 Performance Counters Reference + */ + public class PDH_COUNTER_PATH_ELEMENTS extends Structure { + public String szMachineName; + public String szObjectName; + public String szInstanceName; + public String szParentInstance; + public int dwInstanceIndex; + public String szCounterName; + + @Override + protected List getFieldOrder() { + return Arrays.asList("szMachineName", "szObjectName", "szInstanceName", + "szParentInstance", "dwInstanceIndex", "szCounterName"); + } + } + + // flags for the PdhMakeCounterPath + public static final int PDH_PATH_WBEM_RESULT = 0x00000001; + public static final int PDH_PATH_WBEM_INPUT = 0x00000002; + + /** + * Creates a full counter path using the members specified in the + * {@link #PDH_COUNTER_PATH_ELEMENTS} structure. + * @param pCounterPathElements Structure that contains the members + * used to make up the path + * @param szFullPathBuffer Caller-allocated buffer that receives a null-terminated + * counter path. The maximum length of a counter path is PDH_MAX_COUNTER_PATH. + * Set to {@code null} if pcchBufferSize is zero. + * @param pcchBufferSize Size of the szFullPathBuffer buffer. If + * zero on input, the function returns PDH_MORE_DATA and sets this parameter + * to the required buffer size. If the buffer is larger than the required + * size, the function sets this parameter to the actual size of the buffer + * that was used. + * @param dwFlags Format of the input and output counter values. + * @return ERROR_SUCCESS (or PDH_MORE_DATA) + * @see PdhMakeCounterPath + */ + int PdhMakeCounterPath(PDH_COUNTER_PATH_ELEMENTS pCounterPathElements, char[] szFullPathBuffer, DWORDByReference pcchBufferSize, int dwFlags); + + /** + * Adds the specified counter to the query. + * @param hQuery Handle to the query to which you want to add the counter. + * @param szFullCounterPath String that contains the counter path. + * The maximum length of a counter path is {@link #PDH_MAX_COUNTER_PATH}. + * @param dwUserData User-defined value. + * @param phCounter (Out) Handle to the counter that was added to the query. + * @return ERROR_SUCCESS if successful + * @see PdhAddCounter + * @see Specifying a Counter Path + */ + int PdhAddCounter(HANDLE hQuery, String szFullCounterPath, DWORD_PTR dwUserData, HANDLEByReference phCounter); + int PdhAddEnglishCounter(HANDLE hQuery, String szFullCounterPath, DWORD_PTR dwUserData, HANDLEByReference phCounter); + + /** + * Removes a counter from a query. + * @param hCounter Handle of the counter to remove from its query. + * @return ERROR_SUCCESS if successful + * @see PdhRemoveCounter + */ + int PdhRemoveCounter(HANDLE hCounter); + + /** + * The data as it was collected from the counter provider. No translation, + * formatting, or other interpretation is performed on the data. + * @see PDH_RAW_COUNTER + */ + public class PDH_RAW_COUNTER extends Structure { + /** Counter status that indicates if the counter value is valid. */ + public int CStatus; + /** Local time for when the data was collected */ + public FILETIME TimeStamp = new FILETIME(); + /** First raw counter value. */ + public long FirstValue; + /** Second raw counter value. */ + public long SecondValue; + /** + * If the counter type contains the PERF_MULTI_COUNTER flag, + * this member contains the additional counter data used in the + * calculation + */ + public int MultiCount; + + @Override + protected List getFieldOrder() { + return Arrays.asList("CStatus", "TimeStamp", "FirstValue", "SecondValue", "MultiCount"); + } + } + + /** + * @param hCounter Handle of the counter from which to retrieve the current raw value. + * @param lpdwType Receives the counter type - this parameter is optional + * @param pValue The {@link PDH_RAW_COUNTER} structure to receive the data + * @return ERROR_SUCCESS if successful + * @see PdhGetRawCounterValue + */ + int PdhGetRawCounterValue(HANDLE hCounter, DWORDByReference lpdwType, PDH_RAW_COUNTER pValue); + + // counter value types + public static final int PDH_FMT_RAW = 0x00000010; + public static final int PDH_FMT_ANSI = 0x00000020; + public static final int PDH_FMT_UNICODE = 0x00000040; + public static final int PDH_FMT_LONG = 0x00000100; + public static final int PDH_FMT_DOUBLE = 0x00000200; + public static final int PDH_FMT_LARGE = 0x00000400; + public static final int PDH_FMT_NOSCALE = 0x00001000; + public static final int PDH_FMT_1000 = 0x00002000; + public static final int PDH_FMT_NODATA = 0x00004000; + public static final int PDH_FMT_NOCAP100 = 0x00008000; + public static final int PERF_DETAIL_COSTLY = 0x00010000; + public static final int PERF_DETAIL_STANDARD = 0x0000FFFF; + + /** + * Validates that the counter is present on the computer specified in the counter path. + * @param szFullCounterPath The counter path to validate + * @return ERROR_SUCCESS if successful + * @see PdhValidatePath + */ + int PdhValidatePath(String szFullCounterPath); + + /** + * Collects the current raw data value for all counters in the specified + * query and updates the status code of each counter. + * @param hQuery Handle to the query + * @return ERROR_SUCCESS if successful + * @see PdhCollectQueryData + */ + int PdhCollectQueryData(HANDLE hQuery); + + /** + * Uses a separate thread to collect the current raw data value for all counters + * in the specified query. The function then signals the application-defined + * event and waits the specified time interval before returning. + * @param hQuery Handle to the query + * @param dwIntervalTime Time interval to wait, in seconds. + * @param hNewDataEvent Handle to the event that you want PDH to signal after + * the time interval expires. To create an event object, call the + * {@link Kernel32#CreateEvent(com.sun.jna.platform.win32.WinBase.SECURITY_ATTRIBUTES, boolean, boolean, String)} + * function + * @return ERROR_SUCCESS if successful + * @see PdhCollectQueryDataEx + */ + int PdhCollectQueryDataEx(HANDLE hQuery, int dwIntervalTime, HANDLE hNewDataEvent); + + /** + * Collects the current raw data value for all counters in the specified + * query and updates the status code of each counter. + * @param hQuery Handle to the query + * @param pllTimeStamp Time stamp when the first counter value in the query + * was retrieved. The time is specified as {@link WinBase#FILETIME}. + * @return ERROR_SUCCESS if successful + * @see PdhCollectQueryDataWithTime + */ + int PdhCollectQueryDataWithTime(HANDLE hQuery, LONGLONGByReference pllTimeStamp); + + /** + * Information on time intervals as applied to the sampling of performance data. + * @see PDH_TIME_INFO + */ + public class PDH_TIME_INFO extends Structure { + /** Starting time of the sample interval, in local FILETIME format. */ + public long StartTime; + /** Ending time of the sample interval, in local FILETIME format. */ + public long EndTime; + /** Number of samples collected during the interval. */ + public int SampleCount; + + protected List getFieldOrder() { + return Arrays.asList("StartTime", "EndTime", "SampleCount"); + } + } + + /** + * @param hQuery Handle to the query. + * @param pInfo A {@link PDH_TIME_INFO} structure that specifies the time range. + * @return ERROR_SUCCESS if successful + * @see PdhSetQueryTimeRange + */ + int PdhSetQueryTimeRange(HANDLE hQuery, PDH_TIME_INFO pInfo); +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/PdhMsg.java b/contrib/platform/src/com/sun/jna/platform/win32/PdhMsg.java new file mode 100644 index 0000000000..b5cc508892 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/PdhMsg.java @@ -0,0 +1,193 @@ +/* Copyright (c) 2015 Goldstein Lyor, All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + */ +package com.sun.jna.platform.win32; + +/** + * PDH specific error codes + * @author Lyor Goldstein + * @see Performance Data Helper Error Codes + */ +public interface PdhMsg { + /** Returned data is valid. */ + public static final int PDH_CSTATUS_VALID_DATA = 0x00000000; + /** Return data value is valid and different from the last sample. */ + public static final int PDH_CSTATUS_NEW_DATA = 0x00000001; + /** Unable to connect to the specified computer, or the computer is offline. */ + public static final int PDH_CSTATUS_NO_MACHINE = 0x800007D0; + /** The specified instance is not present. */ + public static final int PDH_CSTATUS_NO_INSTANCE = 0x800007D1; + /** There is more data to return than would fit in the supplied buffer. Allocate a larger buffer and call the function again. */ + public static final int PDH_MORE_DATA = 0x800007D2; + /** The data item has been added to the query but has not been validated nor accessed. No other status information on this data item is available. */ + public static final int PDH_CSTATUS_ITEM_NOT_VALIDATED = 0x800007D3; + /** The selected operation should be retried. */ + public static final int PDH_RETRY = 0x800007D4; + /** No data to return. */ + public static final int PDH_NO_DATA = 0x800007D5; + /** A counter with a negative denominator value was detected. */ + public static final int PDH_CALC_NEGATIVE_DENOMINATOR = 0x800007D6; + /** A counter with a negative time base value was detected. */ + public static final int PDH_CALC_NEGATIVE_TIMEBASE = 0x800007D7; + /** A counter with a negative value was detected. */ + public static final int PDH_CALC_NEGATIVE_VALUE = 0x800007D8; + /** The user canceled the dialog box. */ + public static final int PDH_DIALOG_CANCELLED = 0x800007D9; + /** The end of the log file was reached. */ + public static final int PDH_END_OF_LOG_FILE = 0x800007DA; + /** A time-out occurred while waiting for the asynchronous counter collection thread to end. */ + public static final int PDH_ASYNC_QUERY_TIMEOUT = 0x800007DB; + /** Cannot change set default real-time data source. */ + public static final int PDH_CANNOT_SET_DEFAULT_REALTIME_DATASOURCE = 0x800007DC; + /** The specified object is not found on the system. */ + public static final int PDH_CSTATUS_NO_OBJECT = 0xC0000BB8; + /** The specified counter could not be found. */ + public static final int PDH_CSTATUS_NO_COUNTER = 0xC0000BB9; + /** The returned data is not valid. */ + public static final int PDH_CSTATUS_INVALID_DATA= 0xC0000BBA; + /** A PDH function could not allocate enough temporary memory to complete the operation. */ + public static final int PDH_MEMORY_ALLOCATION_FAILURE = 0xC0000BBB; + /** The handle is not a valid PDH object. */ + public static final int PDH_INVALID_HANDLE = 0xC0000BBC; + /** A required argument is missing or incorrect. */ + public static final int PDH_INVALID_ARGUMENT = 0xC0000BBD; + /** Unable to find the specified function. */ + public static final int PDH_FUNCTION_NOT_FOUND = 0xC0000BBE; + /** No counter was specified. */ + public static final int PDH_CSTATUS_NO_COUNTERNAME = 0xC0000BBF; + /** Unable to parse the counter path. Check the format and syntax of the specified path. */ + public static final int PDH_CSTATUS_BAD_COUNTERNAME = 0xC0000BC0; + /** The buffer passed by the caller is not valid. */ + public static final int PDH_INVALID_BUFFER = 0xC0000BC1; + /** The requested data is larger than the buffer supplied. */ + public static final int PDH_INSUFFICIENT_BUFFER = 0xC0000BC2; + /** Unable to connect to the requested computer. */ + public static final int PDH_CANNOT_CONNECT_MACHINE = 0xC0000BC3; + /** The specified counter path could not be interpreted. */ + public static final int PDH_INVALID_PATH = 0xC0000BC4; + /** The instance name could not be read from the specified counter path. */ + public static final int PDH_INVALID_INSTANCE = 0xC0000BC5; + /** The data is not valid. */ + public static final int PDH_INVALID_DATA = 0xC0000BC6; + /** The dialog box data block was missing or not valid. */ + public static final int PDH_NO_DIALOG_DATA = 0xC0000BC7; + /** Unable to read the counter and/or help text from the specified computer. */ + public static final int PDH_CANNOT_READ_NAME_STRINGS = 0xC0000BC8; + /** Unable to create the specified log file. */ + public static final int PDH_LOG_FILE_CREATE_ERROR = 0xC0000BC9; + /** Unable to open the specified log file. */ + public static final int PDH_LOG_FILE_OPEN_ERROR = 0xC0000BCA; + /** The specified log file type has not been installed on this system. */ + public static final int PDH_LOG_TYPE_NOT_FOUND = 0xC0000BCB; + /** No more data is available. */ + public static final int PDH_NO_MORE_DATA = 0xC0000BCC; + /** The specified record was not found in the log file. */ + public static final int PDH_ENTRY_NOT_IN_LOG_FILE = 0xC0000BCD; + /** The specified data source is a log file. */ + public static final int PDH_DATA_SOURCE_IS_LOG_FILE = 0xC0000BCE; + /** The specified data source is the current activity. */ + public static final int PDH_DATA_SOURCE_IS_REAL_TIME = 0xC0000BCF; + /** The log file header could not be read. */ + public static final int PDH_UNABLE_READ_LOG_HEADER = 0xC0000BD0; + /** Unable to find the specified file. */ + public static final int PDH_FILE_NOT_FOUND = 0xC0000BD1; + /** There is already a file with the specified file name. */ + public static final int PDH_FILE_ALREADY_EXISTS = 0xC0000BD2; + /** The function referenced has not been implemented. */ + public static final int PDH_NOT_IMPLEMENTED = 0xC0000BD3; + /** Unable to find the specified string in the list of performance name and help text strings. */ + public static final int PDH_STRING_NOT_FOUND = 0xC0000BD4; + /** Unable to map to the performance counter name data files. */ + public static final int PDH_UNABLE_MAP_NAME_FILES = 0x80000BD5; + /** The format of the specified log file is not recognized by the PDH DLL. */ + public static final int PDH_UNKNOWN_LOG_FORMAT = 0xC0000BD6; + /** The specified Log Service command value is not recognized. */ + public static final int PDH_UNKNOWN_LOGSVC_COMMAND = 0xC0000BD7; + /** The specified query from the Log Service could not be found or could not be opened. */ + public static final int PDH_LOGSVC_QUERY_NOT_FOUND = 0xC0000BD8; + /** The Performance Data Log Service key could not be opened. */ + public static final int PDH_LOGSVC_NOT_OPENED = 0xC0000BD9; + /** An error occurred while accessing the WBEM data store. */ + public static final int PDH_WBEM_ERROR = 0xC0000BDA; + /** Unable to access the desired computer or service. */ + public static final int PDH_ACCESS_DENIED = 0xC0000BDB; + /** The maximum log file size specified is too small to log the selected counters. */ + public static final int PDH_LOG_FILE_TOO_SMALL = 0xC0000BDC; + /** Cannot connect to ODBC DataSource Name. */ + public static final int PDH_INVALID_DATASOURCE = 0xC0000BDD; + /** SQL Data base does not contain a valid set of tables for Perfmon. */ + public static final int PDH_INVALID_SQLDB = 0xC0000BDE; + /** No counters were found for this Perfmon SQL Log Set. */ + public static final int PDH_NO_COUNTERS = 0xC0000BDF; + /** Call to SQLAllocStmt failed with %1. */ + public static final int PDH_SQL_ALLOC_FAILED = 0xC0000BE0; + /** Call to SQLAllocConnect failed with %1. */ + public static final int PDH_SQL_ALLOCCON_FAILED = 0xC0000BE1; + /** Call to SQLExecDirect failed with %1. */ + public static final int PDH_SQL_EXEC_DIRECT_FAILED = 0xC0000BE2; + /** Call to SQLFetch failed with %1. */ + public static final int PDH_SQL_FETCH_FAILED = 0xC0000BE3; + /** Call to SQLRowCount failed with %1. */ + public static final int PDH_SQL_ROWCOUNT_FAILED = 0xC0000BE4; + /** Call to SQLMoreResults failed with %1. + public static final int PDH_SQL_MORE_RESULTS_FAILED = 0xC0000BE5; + /** Call to SQLConnect failed with %1. */ + public static final int PDH_SQL_CONNECT_FAILED = 0xC0000BE6; + /** Call to SQLBindCol failed with %1. */ + public static final int PDH_SQL_BIND_FAILED = 0xC0000BE7; + /** Unable to connect to the WMI server on requested computer. */ + public static final int PDH_CANNOT_CONNECT_WMI_SERVER = 0xC0000BE8; + /** Collection "%1!s!" is already running. */ + public static final int PDH_PLA_COLLECTION_ALREADY_RUNNING = 0xC0000BE9; + /** The specified start time is after the end time. */ + public static final int PDH_PLA_ERROR_SCHEDULE_OVERLAP = 0xC0000BEA; + /** Collection "%1!s!" does not exist. */ + public static final int PDH_PLA_COLLECTION_NOT_FOUND = 0xC0000BEB; + /** The specified end time has already elapsed. */ + public static final int PDH_PLA_ERROR_SCHEDULE_ELAPSED = 0xC0000BEC; + /** Collection "%1!s!" did not start; check the application event log for any errors. */ + public static final int PDH_PLA_ERROR_NOSTART = 0xC0000BED; + /** Collection "%1!s!" already exists. */ + public static final int PDH_PLA_ERROR_ALREADY_EXISTS = 0xC0000BEE; + /** There is a mismatch in the settings type. */ + public static final int PDH_PLA_ERROR_TYPE_MISMATCH = 0xC0000BEF; + /** The information specified does not resolve to a valid path name. */ + public static final int PDH_PLA_ERROR_FILEPATH = 0xC0000BF0; + /** The "Performance Logs & Alerts" service did not respond. */ + public static final int PDH_PLA_SERVICE_ERROR = 0xC0000BF1; + /** The information passed is not valid. */ + public static final int PDH_PLA_VALIDATION_ERROR = 0xC0000BF2; + /** The information passed is not valid. */ + public static final int PDH_PLA_VALIDATION_WARNING = 0x80000BF3; + /** The name supplied is too long. */ + public static final int PDH_PLA_ERROR_NAME_TOO_LONG = 0xC0000BF4; + /** SQL log format is incorrect. Correct format is "SQL:!". */ + public static final int PDH_INVALID_SQL_LOG_FORMAT = 0xC0000BF5; + /** Performance counter in PdhAddCounter call has already been added in the performance query. */ + public static final int PDH_COUNTER_ALREADY_IN_QUERY = 0xC0000BF6; + /** Unable to read counter information and data from input binary log files. */ + public static final int PDH_BINARY_LOG_CORRUPT = 0xC0000BF7; + /** At least one of the input binary log files contain fewer than two data samples. */ + public static final int PDH_LOG_SAMPLE_TOO_SMALL = 0xC0000BF8; + /** The version of the operating system on the computer named %1 is later than that on the local computer. */ + public static final int PDH_OS_LATER_VERSION = 0xC0000BF9; + /** %1 supports %2 or later. Check the operating system version on the computer named %3. */ + public static final int PDH_OS_EARLIER_VERSION = 0xC0000BFA; + /** The output file must contain earlier data than the file to be appended. */ + public static final int PDH_INCORRECT_APPEND_TIME = 0xC0000BFB; + /** Both files must have identical counters in order to append. */ + public static final int PDH_UNMATCHED_APPEND_COUNTER = 0xC0000BFC; + /** Cannot alter CounterDetail table layout in SQL database. */ + public static final int PDH_SQL_ALTER_DETAIL_FAILED = 0xC0000BFD; + /** System is busy - a time-out occurred when collecting counter data */ + public static final int PDH_QUERY_PERF_DATA_TIMEOUT = 0xC0000BFE; +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/WinPerf.java b/contrib/platform/src/com/sun/jna/platform/win32/WinPerf.java new file mode 100644 index 0000000000..0dc4ce4f35 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/WinPerf.java @@ -0,0 +1,451 @@ +/* Copyright (c) 2015 Goldstein Lyor, All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + */ +package com.sun.jna.platform.win32; + +import java.util.Arrays; +import java.util.List; + +import com.sun.jna.Structure; +import com.sun.jna.platform.win32.WinBase.SYSTEMTIME; +import com.sun.jna.platform.win32.WinNT.LARGE_INTEGER; + +/** + * Various performance counters structures and definitions + * @author Lyor Goldstein + * @see Performance Counters Structures + */ +public interface WinPerf { + /** + * Describes the performance data block that you queried + * @see PERF_DATA_BLOCK + */ + public class PERF_DATA_BLOCK extends Structure { + public char[] Signature = new char[4]; + public int LittleEndian; + public int Version; + public int Revision; + public int TotalByteLength; + public int HeaderLength; + public int NumObjectTypes; + public int DefaultObject; + public SYSTEMTIME SystemTime = new SYSTEMTIME(); + public LARGE_INTEGER PerfTime = new LARGE_INTEGER(); + public LARGE_INTEGER PerfFreq = new LARGE_INTEGER(); + public LARGE_INTEGER PerfTime100nSec = new LARGE_INTEGER(); + public int SystemNameLength; + public int SystemNameOffset; + + @Override + protected List getFieldOrder() { + return Arrays.asList("Signature", "LittleEndian", "Version", + "Revision", "TotalByteLength", "HeaderLength", + "NumObjectTypes", "DefaultObject", "SystemTime", + "PerfTime", "PerfFreq", "PerfTime100nSec", + "SystemNameLength", "SystemNameOffset"); + } + }; + + /** + * Describes an instance of a performance object + * @see PERF_INSTANCE_DEFINITION + */ + public class PERF_INSTANCE_DEFINITION extends Structure { + public int ByteLength; + public int ParentObjectTitleIndex; + public int ParentObjectInstance; + public int UniqueID; + public int NameOffset; + public int NameLength; + + @Override + protected List getFieldOrder() { + return Arrays.asList("ByteLength", "ParentObjectTitleIndex", "ParentObjectInstance", + "UniqueID", "NameOffset", "NameLength"); + } + }; + + public static final int PERF_NO_INSTANCES = -1; // no instances (see NumInstances above) + + // + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // + // PERF_COUNTER_DEFINITION.CounterType field values + // + // + // Counter ID Field Definition: + // + // 3 2 2 2 2 1 1 1 + // 1 8 4 2 0 6 2 0 8 0 + // +--------+--------+----+----+--------+--------+----+----+----------------+ + // |Display |Calculation |Time|Counter | |Ctr |Size| | + // |Flags |Modifiers |Base|SubType |Reserved|Type|Fld | Reserved | + // +--------+--------+----+----+--------+--------+----+----+----------------+ + // + // + // The counter type is the "or" of the following values as described below + // + // select one of the following to indicate the counter's data size + // + public static final int PERF_SIZE_DWORD = 0x00000000; // 32 bit field + public static final int PERF_SIZE_LARGE = 0x00000100; // 64 bit field + public static final int PERF_SIZE_ZERO = 0x00000200; // for Zero Length fields + public static final int PERF_SIZE_VARIABLE_LEN = 0x00000300; // length is in CounterLength field + // of Counter Definition struct + // + // select one of the following values to indicate the counter field usage + // + public static final int PERF_TYPE_NUMBER = 0x00000000; // a number (not a counter) + public static final int PERF_TYPE_COUNTER = 0x00000400; // an increasing numeric value + public static final int PERF_TYPE_TEXT = 0x00000800; // a text field + public static final int PERF_TYPE_ZERO = 0x00000C00; // displays a zero + // + // If the PERF_TYPE_NUMBER field was selected, then select one of the + // following to describe the Number + // + public static final int PERF_NUMBER_HEX = 0x00000000; // display as HEX value + public static final int PERF_NUMBER_DECIMAL = 0x00010000; // display as a decimal integer + public static final int PERF_NUMBER_DEC_1000 = 0x00020000; // display as a decimal/1000 + // + // If the PERF_TYPE_COUNTER value was selected then select one of the + // following to indicate the type of counter + // + public static final int PERF_COUNTER_VALUE = 0x00000000; // display counter value + public static final int PERF_COUNTER_RATE = 0x00010000; // divide ctr / delta time + public static final int PERF_COUNTER_FRACTION = 0x00020000; // divide ctr / base + public static final int PERF_COUNTER_BASE = 0x00030000; // base value used in fractions + public static final int PERF_COUNTER_ELAPSED = 0x00040000; // subtract counter from current time + public static final int PERF_COUNTER_QUEUELEN = 0x00050000; // Use Queuelen processing func. + public static final int PERF_COUNTER_HISTOGRAM = 0x00060000; // Counter begins or ends a histogram + public static final int PERF_COUNTER_PRECISION = 0x00070000; // divide ctr / private clock + // + // If the PERF_TYPE_TEXT value was selected, then select one of the + // following to indicate the type of TEXT data. + // + public static final int PERF_TEXT_UNICODE = 0x00000000; // type of text in text field + public static final int PERF_TEXT_ASCII = 0x00010000; // ASCII using the CodePage field + // + // Timer SubTypes + // + public static final int PERF_TIMER_TICK = 0x00000000; // use system perf. freq for base + public static final int PERF_TIMER_100NS = 0x00100000; // use 100 NS timer time base units + public static final int PERF_OBJECT_TIMER = 0x00200000; // use the object timer freq + // + // Any types that have calculations performed can use one or more of + // the following calculation modification flags listed here + // + public static final int PERF_DELTA_COUNTER = 0x00400000; // compute difference first + public static final int PERF_DELTA_BASE = 0x00800000; // compute base diff as well + public static final int PERF_INVERSE_COUNTER = 0x01000000; // show as 1.00-value (assumes: + public static final int PERF_MULTI_COUNTER = 0x02000000; // sum of multiple instances + // + // Select one of the following values to indicate the display suffix (if any) + // + public static final int PERF_DISPLAY_NO_SUFFIX = 0x00000000; // no suffix + public static final int PERF_DISPLAY_PER_SEC = 0x10000000; // "/sec" + public static final int PERF_DISPLAY_PERCENT = 0x20000000; // "%" + public static final int PERF_DISPLAY_SECONDS = 0x30000000; // "secs" + public static final int PERF_DISPLAY_NOSHOW = 0x40000000; // value is not displayed + // + // Predefined counter types + // + + // 32-bit Counter. Divide delta by delta time. Display suffix: "/sec" + public static final int PERF_COUNTER_COUNTER = + (PERF_SIZE_DWORD | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | + PERF_TIMER_TICK | PERF_DELTA_COUNTER | PERF_DISPLAY_PER_SEC); + + + // 64-bit Timer. Divide delta by delta time. Display suffix: "%" + public static final int PERF_COUNTER_TIMER = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | + PERF_TIMER_TICK | PERF_DELTA_COUNTER | PERF_DISPLAY_PERCENT); + + // Queue Length Space-Time Product. Divide delta by delta time. No Display Suffix. + public static final int PERF_COUNTER_QUEUELEN_TYPE = + (PERF_SIZE_DWORD | PERF_TYPE_COUNTER | PERF_COUNTER_QUEUELEN | + PERF_TIMER_TICK | PERF_DELTA_COUNTER | PERF_DISPLAY_NO_SUFFIX); + + // Queue Length Space-Time Product. Divide delta by delta time. No Display Suffix. + public static final int PERF_COUNTER_LARGE_QUEUELEN_TYPE = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_QUEUELEN | + PERF_TIMER_TICK | PERF_DELTA_COUNTER | PERF_DISPLAY_NO_SUFFIX); + + // Queue Length Space-Time Product using 100 Ns timebase. + // Divide delta by delta time. No Display Suffix. + public static final int PERF_COUNTER_100NS_QUEUELEN_TYPE = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_QUEUELEN | + PERF_TIMER_100NS | PERF_DELTA_COUNTER | PERF_DISPLAY_NO_SUFFIX); + + // Queue Length Space-Time Product using Object specific timebase. + // Divide delta by delta time. No Display Suffix. + public static final int PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_QUEUELEN | + PERF_OBJECT_TIMER | PERF_DELTA_COUNTER | PERF_DISPLAY_NO_SUFFIX); + + // 64-bit Counter. Divide delta by delta time. Display Suffix: "/sec" + public static final int PERF_COUNTER_BULK_COUNT = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | + PERF_TIMER_TICK | PERF_DELTA_COUNTER | PERF_DISPLAY_PER_SEC); + + // Indicates the counter is not a counter but rather Unicode text Display as text. + public static final int PERF_COUNTER_TEXT = + (PERF_SIZE_VARIABLE_LEN | PERF_TYPE_TEXT | PERF_TEXT_UNICODE | + PERF_DISPLAY_NO_SUFFIX); + + // Indicates the data is a counter which should not be + // time averaged on display (such as an error counter on a serial line) + // Display as is. No Display Suffix. + public static final int PERF_COUNTER_RAWCOUNT = + (PERF_SIZE_DWORD | PERF_TYPE_NUMBER | PERF_NUMBER_DECIMAL | + PERF_DISPLAY_NO_SUFFIX); + + // Same as PERF_COUNTER_RAWCOUNT except its size is a large integer + public static final int PERF_COUNTER_LARGE_RAWCOUNT = + (PERF_SIZE_LARGE | PERF_TYPE_NUMBER | PERF_NUMBER_DECIMAL | + PERF_DISPLAY_NO_SUFFIX); + + // Special case for RAWCOUNT that want to be displayed in hex + // Indicates the data is a counter which should not be + // time averaged on display (such as an error counter on a serial line) + // Display as is. No Display Suffix. + public static final int PERF_COUNTER_RAWCOUNT_HEX = + (PERF_SIZE_DWORD | PERF_TYPE_NUMBER | PERF_NUMBER_HEX | + PERF_DISPLAY_NO_SUFFIX); + + // Same as PERF_COUNTER_RAWCOUNT_HEX except its size is a large integer + public static final int PERF_COUNTER_LARGE_RAWCOUNT_HEX = + (PERF_SIZE_LARGE | PERF_TYPE_NUMBER | PERF_NUMBER_HEX | + PERF_DISPLAY_NO_SUFFIX); + + + // A count which is either 1 or 0 on each sampling interrupt (% busy) + // Divide delta by delta base. Display Suffix: "%" + public static final int PERF_SAMPLE_FRACTION = + (PERF_SIZE_DWORD | PERF_TYPE_COUNTER | PERF_COUNTER_FRACTION | + PERF_DELTA_COUNTER | PERF_DELTA_BASE | PERF_DISPLAY_PERCENT); + + // A count which is sampled on each sampling interrupt (queue length) + // Divide delta by delta time. No Display Suffix. + public static final int PERF_SAMPLE_COUNTER = + (PERF_SIZE_DWORD | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | + PERF_TIMER_TICK | PERF_DELTA_COUNTER | PERF_DISPLAY_NO_SUFFIX); + + // A label: no data is associated with this counter (it has 0 length) + // Do not display. + public static final int PERF_COUNTER_NODATA = + (PERF_SIZE_ZERO | PERF_DISPLAY_NOSHOW); + + // 64-bit Timer inverse (e.g., idle is measured, but display busy %) + // Display 100 - delta divided by delta time. Display suffix: "%" + public static final int PERF_COUNTER_TIMER_INV = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | + PERF_TIMER_TICK | PERF_DELTA_COUNTER | PERF_INVERSE_COUNTER | + PERF_DISPLAY_PERCENT); + + // The divisor for a sample, used with the previous counter to form a + // sampled %. You must check for >0 before dividing by this! This + // counter will directly follow the numerator counter. It should not + // be displayed to the user. + public static final int PERF_SAMPLE_BASE = + (PERF_SIZE_DWORD | PERF_TYPE_COUNTER | PERF_COUNTER_BASE | + PERF_DISPLAY_NOSHOW | + 0x00000001); // for compatibility with pre-beta versions + + // A timer which, when divided by an average base, produces a time + // in seconds which is the average time of some operation. This + // timer times total operations, and the base is the number of opera- + // tions. Display Suffix: "sec" + public static final int PERF_AVERAGE_TIMER = + (PERF_SIZE_DWORD | PERF_TYPE_COUNTER | PERF_COUNTER_FRACTION | + PERF_DISPLAY_SECONDS); + + // Used as the denominator in the computation of time or count + // averages. Must directly follow the numerator counter. Not dis- + // played to the user. + public static final int PERF_AVERAGE_BASE = + (PERF_SIZE_DWORD | PERF_TYPE_COUNTER | PERF_COUNTER_BASE | + PERF_DISPLAY_NOSHOW | + 0x00000002); // for compatibility with pre-beta versions + + + // A bulk count which, when divided (typically) by the number of + // operations, gives (typically) the number of bytes per operation. + // No Display Suffix. + public static final int PERF_AVERAGE_BULK = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_FRACTION | + PERF_DISPLAY_NOSHOW); + + // 64-bit Timer in object specific units. Display delta divided by + // delta time as returned in the object type header structure. Display suffix: "%" + public static final int PERF_OBJ_TIME_TIMER = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | + PERF_OBJECT_TIMER | PERF_DELTA_COUNTER | PERF_DISPLAY_PERCENT); + + + // 64-bit Timer in 100 nsec units. Display delta divided by + // delta time. Display suffix: "%" + public static final int PERF_100NSEC_TIMER = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | + PERF_TIMER_100NS | PERF_DELTA_COUNTER | PERF_DISPLAY_PERCENT); + + // 64-bit Timer inverse (e.g., idle is measured, but display busy %) + // Display 100 - delta divided by delta time. Display suffix: "%" + public static final int PERF_100NSEC_TIMER_INV = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | + PERF_TIMER_100NS | PERF_DELTA_COUNTER | PERF_INVERSE_COUNTER | + PERF_DISPLAY_PERCENT); + + // 64-bit Timer. Divide delta by delta time. Display suffix: "%" + // Timer for multiple instances, so result can exceed 100%. + public static final int PERF_COUNTER_MULTI_TIMER = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | + PERF_DELTA_COUNTER | PERF_TIMER_TICK | PERF_MULTI_COUNTER | + PERF_DISPLAY_PERCENT); + + // 64-bit Timer inverse (e.g., idle is measured, but display busy %) + // Display 100 * _MULTI_BASE - delta divided by delta time. + // Display suffix: "%" Timer for multiple instances, so result + // can exceed 100%. Followed by a counter of type _MULTI_BASE. + public static final int PERF_COUNTER_MULTI_TIMER_INV = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | + PERF_DELTA_COUNTER | PERF_MULTI_COUNTER | PERF_TIMER_TICK | + PERF_INVERSE_COUNTER | PERF_DISPLAY_PERCENT); + + // Number of instances to which the preceding _MULTI_..._INV counter + // applies. Used as a factor to get the percentage. + public static final int PERF_COUNTER_MULTI_BASE = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_BASE | + PERF_MULTI_COUNTER | PERF_DISPLAY_NOSHOW); + + // 64-bit Timer in 100 nsec units. Display delta divided by delta time. + // Display suffix: "%" Timer for multiple instances, so result can exceed 100%. + public static final int PERF_100NSEC_MULTI_TIMER = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_DELTA_COUNTER | + PERF_COUNTER_RATE | PERF_TIMER_100NS | PERF_MULTI_COUNTER | + PERF_DISPLAY_PERCENT); + + // 64-bit Timer inverse (e.g., idle is measured, but display busy %) + // Display 100 * _MULTI_BASE - delta divided by delta time. + // Display suffix: "%" Timer for multiple instances, so result + // can exceed 100%. Followed by a counter of type _MULTI_BASE. + public static final int PERF_100NSEC_MULTI_TIMER_INV = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_DELTA_COUNTER | + PERF_COUNTER_RATE | PERF_TIMER_100NS | PERF_MULTI_COUNTER | + PERF_INVERSE_COUNTER | PERF_DISPLAY_PERCENT); + + // Indicates the data is a fraction of the following counter which + // should not be time averaged on display (such as free space over + // total space.) Display as is. Display the quotient as "%". + public static final int PERF_RAW_FRACTION = + (PERF_SIZE_DWORD | PERF_TYPE_COUNTER | PERF_COUNTER_FRACTION | + PERF_DISPLAY_PERCENT); + + public static final int PERF_LARGE_RAW_FRACTION = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_FRACTION | + PERF_DISPLAY_PERCENT); + + // Indicates the data is a base for the preceding counter which should + // not be time averaged on display (such as free space over total space.) + public static final int PERF_RAW_BASE = + (PERF_SIZE_DWORD | PERF_TYPE_COUNTER | PERF_COUNTER_BASE | + PERF_DISPLAY_NOSHOW | + 0x00000003); // for compatibility with pre-beta versions + + public static final int PERF_LARGE_RAW_BASE = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_BASE | + PERF_DISPLAY_NOSHOW ); + + // The data collected in this counter is actually the start time of the + // item being measured. For display, this data is subtracted from the + // sample time to yield the elapsed time as the difference between the two. + // In the definition below, the PerfTime field of the Object contains + // the sample time as indicated by the PERF_OBJECT_TIMER bit and the + // difference is scaled by the PerfFreq of the Object to convert the time + // units into seconds. + public static final int PERF_ELAPSED_TIME = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_ELAPSED | + PERF_OBJECT_TIMER | PERF_DISPLAY_SECONDS); + // + // The following counter type can be used with the preceding types to + // define a range of values to be displayed in a histogram. + // + + public static final int PERF_COUNTER_HISTOGRAM_TYPE = 0x80000000; // Counter begins or ends a histogram + // + // This counter is used to display the difference from one sample + // to the next. The counter value is a constantly increasing number + // and the value displayed is the difference between the current + // value and the previous value. Negative numbers are not allowed + // which shouldn't be a problem as long as the counter value is + // increasing or unchanged. + // + public static final int PERF_COUNTER_DELTA = + (PERF_SIZE_DWORD | PERF_TYPE_COUNTER | PERF_COUNTER_VALUE | + PERF_DELTA_COUNTER | PERF_DISPLAY_NO_SUFFIX); + + public static final int PERF_COUNTER_LARGE_DELTA = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_VALUE | + PERF_DELTA_COUNTER | PERF_DISPLAY_NO_SUFFIX); + // + // The precision counters are timers that consist of two counter values: + // 1) the count of elapsed time of the event being monitored + // 2) the "clock" time in the same units + // + // the precition timers are used where the standard system timers are not + // precise enough for accurate readings. It's assumed that the service + // providing the data is also providing a timestamp at the same time which + // will eliminate any error that may occur since some small and variable + // time elapses between the time the system timestamp is captured and when + // the data is collected from the performance DLL. Only in extreme cases + // has this been observed to be problematic. + // + // when using this type of timer, the definition of the + // PERF_PRECISION_TIMESTAMP counter must immediately follow the + // definition of the PERF_PRECISION_*_TIMER in the Object header + // + // The timer used has the same frequency as the System Performance Timer + public static final int PERF_PRECISION_SYSTEM_TIMER = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_PRECISION | + PERF_TIMER_TICK | PERF_DELTA_COUNTER | PERF_DISPLAY_PERCENT ); + // + // The timer used has the same frequency as the 100 NanoSecond Timer + public static final int PERF_PRECISION_100NS_TIMER = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_PRECISION | + PERF_TIMER_100NS | PERF_DELTA_COUNTER | PERF_DISPLAY_PERCENT ); + // + // The timer used is of the frequency specified in the Object header's + // PerfFreq field (PerfTime is ignored) + public static final int PERF_PRECISION_OBJECT_TIMER = + (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_PRECISION | + PERF_OBJECT_TIMER | PERF_DELTA_COUNTER | PERF_DISPLAY_PERCENT ); + // + // This is the timestamp to use in the computation of the timer specified + // in the previous description block + public static final int PERF_PRECISION_TIMESTAMP = PERF_LARGE_RAW_BASE; + // + // The following are used to determine the level of detail associated + // with the counter. The user will be setting the level of detail + // that should be displayed at any given time. + // + // + public static final int PERF_DETAIL_NOVICE = 100; // The uninformed can understand it + public static final int PERF_DETAIL_ADVANCED = 200; // For the advanced user + public static final int PERF_DETAIL_EXPERT = 300; // For the expert user + public static final int PERF_DETAIL_WIZARD = 400; // For the system designer + + public static final int PERF_NO_UNIQUE_ID = -1; + + public static final int PERF_QUERY_OBJECTS = 0x80000000; + public static final int PERF_QUERY_GLOBAL = 0x80000001; + public static final int PERF_QUERY_COSTLY = 0x80000002; +} diff --git a/contrib/platform/test/com/sun/jna/platform/win32/AbstractWin32TestSupport.java b/contrib/platform/test/com/sun/jna/platform/win32/AbstractWin32TestSupport.java index 1a6caf03a2..9f7143c23d 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/AbstractWin32TestSupport.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/AbstractWin32TestSupport.java @@ -42,4 +42,20 @@ public static final void assertCallSucceeded(String message, boolean result) { fail(message + " failed: hr=0x" + Integer.toHexString(hr)); } } + + /** + * Checks if the status code is ERROR_SUCCESS + * @param message Message to display if code is an error + * @param statusCode Status code to check + * @param showHex If status code is not error success then show it as HEX + */ + public static final void assertErrorSuccess(String message, int statusCode, boolean showHex) { + if (showHex) { + if (statusCode != WinError.ERROR_SUCCESS) { + fail(message + " - failed - hr=0x" + Integer.toHexString(statusCode)); + } + } else { + assertEquals(message, WinError.ERROR_SUCCESS, statusCode); + } + } } diff --git a/contrib/platform/test/com/sun/jna/platform/win32/PdhTest.java b/contrib/platform/test/com/sun/jna/platform/win32/PdhTest.java new file mode 100644 index 0000000000..d2c59a1df0 --- /dev/null +++ b/contrib/platform/test/com/sun/jna/platform/win32/PdhTest.java @@ -0,0 +1,158 @@ +/* Copyright (c) 2007 Timothy Wall, All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + */ +package com.sun.jna.platform.win32; + +import java.io.PrintStream; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +import org.junit.Test; + +import com.sun.jna.Native; +import com.sun.jna.platform.win32.Pdh.PDH_COUNTER_PATH_ELEMENTS; +import com.sun.jna.platform.win32.Pdh.PDH_RAW_COUNTER; +import com.sun.jna.platform.win32.WinDef.DWORD; +import com.sun.jna.platform.win32.WinDef.DWORDByReference; +import com.sun.jna.platform.win32.WinNT.HANDLE; +import com.sun.jna.platform.win32.WinNT.HANDLEByReference; + +/** + * @author lgoldstein + */ +public class PdhTest extends AbstractWin32TestSupport { + private static final Pdh pdh = Pdh.INSTANCE; + + @Test + public void testQueryOneCounter() { + PDH_COUNTER_PATH_ELEMENTS elems = new PDH_COUNTER_PATH_ELEMENTS(); + elems.szObjectName = "Processor"; + elems.szInstanceName = "_Total"; + elems.szCounterName = "% Processor Time"; + String counterName = makeCounterPath(pdh, elems); + + HANDLEByReference ref = new HANDLEByReference(); + assertErrorSuccess("PdhOpenQuery", pdh.PdhOpenQuery(null, null, ref), true); + + HANDLE hQuery = ref.getValue(); + try { + ref.setValue(null); + assertErrorSuccess("PdhAddCounter", pdh.PdhAddCounter(hQuery, counterName, null, ref), true); + + HANDLE hCounter = ref.getValue(); + try { + assertErrorSuccess("PdhCollectQueryData", pdh.PdhCollectQueryData(hQuery), true); + + DWORDByReference lpdwType = new DWORDByReference(); + PDH_RAW_COUNTER rawCounter = new PDH_RAW_COUNTER(); + assertErrorSuccess("PdhGetRawCounterValue", pdh.PdhGetRawCounterValue(hCounter, lpdwType, rawCounter), true); + assertEquals("Bad counter data status", PdhMsg.PDH_CSTATUS_VALID_DATA, rawCounter.CStatus); + + DWORD dwType = lpdwType.getValue(); + int typeValue = dwType.intValue(); + // see https://technet.microsoft.com/en-us/library/cc786359(v=ws.10).aspx + assertEquals("Mismatched counter type", WinPerf.PERF_100NSEC_TIMER_INV, typeValue); + showRawCounterData(System.out, counterName, rawCounter); + } finally { + assertErrorSuccess("PdhRemoveCounter", pdh.PdhRemoveCounter(hCounter), true); + } + } finally { + assertErrorSuccess("PdhCloseQuery", pdh.PdhCloseQuery(hQuery), true); + } + } + + @Test + public void testQueryMultipleCounters() { + Collection names = new LinkedList(); + PDH_COUNTER_PATH_ELEMENTS elems = new PDH_COUNTER_PATH_ELEMENTS(); + elems.szObjectName = "Processor"; + elems.szInstanceName = "_Total"; + for (String n : new String[] { "% Processor Time", "% Idle Time", "% User Time"}) { + elems.szCounterName = n; + String counterName = makeCounterPath(pdh, elems); + names.add(counterName); + } + + HANDLEByReference ref = new HANDLEByReference(); + assertErrorSuccess("PdhOpenQuery", pdh.PdhOpenQuery(null, null, ref), true); + + HANDLE hQuery = ref.getValue(); + try { + Map handlesMap = new HashMap(names.size()); + try { + for (String counterName : names) { + ref.setValue(null); + assertErrorSuccess("PdhAddCounter[" + counterName + "]", pdh.PdhAddCounter(hQuery, counterName, null, ref), true); + + HANDLE hCounter = ref.getValue(); + handlesMap.put(counterName, hCounter); + } + + assertErrorSuccess("PdhCollectQueryData", pdh.PdhCollectQueryData(hQuery), true); + + for (Map.Entry ch : handlesMap.entrySet()) { + String counterName = ch.getKey(); + HANDLE hCounter = ch.getValue(); + PDH_RAW_COUNTER rawCounter = new PDH_RAW_COUNTER(); + DWORDByReference lpdwType = new DWORDByReference(); + assertErrorSuccess("PdhGetRawCounterValue[" + counterName + "]", pdh.PdhGetRawCounterValue(hCounter, lpdwType, rawCounter), true); + assertEquals("Bad counter data status for " + counterName, PdhMsg.PDH_CSTATUS_VALID_DATA, rawCounter.CStatus); + showRawCounterData(System.out, counterName, rawCounter); + } + } finally { + names.clear(); + + for (Map.Entry ch : handlesMap.entrySet()) { + String name = ch.getKey(); + HANDLE hCounter = ch.getValue(); + int status = pdh.PdhRemoveCounter(hCounter); + if (status != WinError.ERROR_SUCCESS) { + names.add(name); + } + } + + if (names.size() > 0) { + fail("Failed to remove counters: " + names); + } + } + } finally { + assertErrorSuccess("PdhCloseQuery", pdh.PdhCloseQuery(hQuery), true); + } + } + + private static void showRawCounterData(PrintStream out, String counterName, PDH_RAW_COUNTER rawCounter) { + out.append('\t').append(counterName) + .append(" ").append(String.valueOf(rawCounter.TimeStamp.toDate())) + .append(" 1st=").append(String.valueOf(rawCounter.FirstValue)) + .append(" 2nd=").append(String.valueOf(rawCounter.SecondValue)) + .append(" multi=").append(String.valueOf(rawCounter.MultiCount)) + .println(); + } + + private static String makeCounterPath(Pdh pdh, PDH_COUNTER_PATH_ELEMENTS pathElements) { + DWORDByReference pcchBufferSize = new DWORDByReference(); + int status = pdh.PdhMakeCounterPath(pathElements, null, pcchBufferSize, 0); + assertEquals("Unexpected status code: 0x" + Integer.toHexString(status), PdhMsg.PDH_MORE_DATA, status); + + DWORD bufSize = pcchBufferSize.getValue(); + int numChars = bufSize.intValue(); + assertTrue("Bad required buffer size: " + numChars, numChars > 0); + + char[] szFullPathBuffer = new char[numChars + 1 /* the \0 */]; + pcchBufferSize.setValue(new DWORD(szFullPathBuffer.length)); + assertErrorSuccess("PdhMakeCounterPath", pdh.PdhMakeCounterPath(pathElements, szFullPathBuffer, pcchBufferSize, 0), true); + + return Native.toString(szFullPathBuffer); + } +}