491 lines
16 KiB
C
491 lines
16 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (C) 1996-1999 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
statfuns.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Statistical calculation functions
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include <windows.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <math.h>
|
|||
|
#include <pdh.h>
|
|||
|
#include "pdhicalc.h"
|
|||
|
#include "pdhitype.h"
|
|||
|
#include "pdhmsg.h"
|
|||
|
|
|||
|
|
|||
|
#define PDHI_FMT_FILTER (PDH_FMT_LONG | PDH_FMT_DOUBLE | PDH_FMT_LARGE)
|
|||
|
|
|||
|
PDH_STATUS
|
|||
|
APIENTRY
|
|||
|
PdhiComputeFirstLastStats (
|
|||
|
IN PPDHI_COUNTER pCounter,
|
|||
|
IN DWORD dwFormat,
|
|||
|
IN DWORD dwFirstEntry,
|
|||
|
IN DWORD dwNumEntries,
|
|||
|
IN PPDH_RAW_COUNTER lpRawValueArray,
|
|||
|
IN PPDH_STATISTICS data
|
|||
|
)
|
|||
|
{
|
|||
|
DOUBLE dThisValue = (double)0.0;
|
|||
|
DOUBLE dMin = (double)+10E8; // these are just "big" seed numbers
|
|||
|
DOUBLE dMax = (double)-10E8;
|
|||
|
DOUBLE dMean = (double)0.0;
|
|||
|
BOOLEAN bFirstItem = TRUE;
|
|||
|
|
|||
|
DWORD dwItem;
|
|||
|
DWORD dwValidItemCount = 0;
|
|||
|
DWORD dwFirstValidItem = 0;
|
|||
|
DWORD dwLastValidItem = 0;
|
|||
|
DWORD dwComputeFormat;
|
|||
|
|
|||
|
PPDH_RAW_COUNTER pNewCounter;
|
|||
|
PPDH_RAW_COUNTER pOldCounter;
|
|||
|
|
|||
|
PDH_FMT_COUNTERVALUE fmtValue;
|
|||
|
|
|||
|
DWORD cStatusReturn;
|
|||
|
|
|||
|
__try {
|
|||
|
// initialize th user's data buffer
|
|||
|
data->dwFormat = 0;
|
|||
|
data->count = 0;
|
|||
|
data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
data->min.largeValue = 0;
|
|||
|
data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
data->max.largeValue = 0;
|
|||
|
data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
data->mean.largeValue = 0;
|
|||
|
|
|||
|
// find first valid counter in array
|
|||
|
dwItem = dwFirstEntry;
|
|||
|
pNewCounter = NULL;
|
|||
|
pOldCounter = &lpRawValueArray[dwItem];
|
|||
|
do {
|
|||
|
// get value of this instance if next counter is valid
|
|||
|
if ((pOldCounter->CStatus == PDH_CSTATUS_VALID_DATA) ||
|
|||
|
(pOldCounter->CStatus == PDH_CSTATUS_NEW_DATA)) {
|
|||
|
pNewCounter = pOldCounter;
|
|||
|
dwFirstValidItem = dwItem;
|
|||
|
break;
|
|||
|
} else {
|
|||
|
dwItem = ++dwItem % dwNumEntries;
|
|||
|
pOldCounter = &lpRawValueArray[dwItem];
|
|||
|
}
|
|||
|
} while (dwItem != dwFirstEntry);
|
|||
|
|
|||
|
// do calculations in Floating point format
|
|||
|
dwComputeFormat = dwFormat;
|
|||
|
dwComputeFormat &= ~PDHI_FMT_FILTER;
|
|||
|
dwComputeFormat |= PDH_FMT_DOUBLE | PDH_FMT_NOCAP100;
|
|||
|
|
|||
|
// go to next entry to begin processing
|
|||
|
dwItem = ++dwItem % dwNumEntries;
|
|||
|
pNewCounter = &lpRawValueArray[dwItem];
|
|||
|
|
|||
|
// these counters need 2 or more entrys to compute values from
|
|||
|
if ((dwItem != dwFirstEntry) && (dwNumEntries > 1)) {
|
|||
|
// start record found so initialize and continue
|
|||
|
dwLastValidItem = dwItem;
|
|||
|
|
|||
|
// step through the remaining entries
|
|||
|
|
|||
|
while (dwItem != dwFirstEntry) {
|
|||
|
// get value of this instance if next counter is valid
|
|||
|
if ((pNewCounter->CStatus == PDH_CSTATUS_VALID_DATA) ||
|
|||
|
(pNewCounter->CStatus == PDH_CSTATUS_NEW_DATA)) {
|
|||
|
|
|||
|
// record this as a valid counter
|
|||
|
dwLastValidItem = dwItem;
|
|||
|
|
|||
|
// get current value
|
|||
|
cStatusReturn = PdhiComputeFormattedValue (
|
|||
|
pCounter->CalcFunc,
|
|||
|
pCounter->plCounterInfo.dwCounterType,
|
|||
|
pCounter->lScale,
|
|||
|
dwComputeFormat,
|
|||
|
pNewCounter,
|
|||
|
pOldCounter,
|
|||
|
& pCounter->TimeBase,
|
|||
|
0L,
|
|||
|
& fmtValue);
|
|||
|
if (cStatusReturn == ERROR_SUCCESS) {
|
|||
|
dThisValue = fmtValue.doubleValue;
|
|||
|
|
|||
|
// update min & max
|
|||
|
if (bFirstItem) {
|
|||
|
dMax = dMin = dThisValue;
|
|||
|
bFirstItem = FALSE;
|
|||
|
}
|
|||
|
else {
|
|||
|
if (dThisValue > dMax) dMax = dThisValue;
|
|||
|
if (dThisValue < dMin) dMin = dThisValue;
|
|||
|
}
|
|||
|
dwValidItemCount++;
|
|||
|
}
|
|||
|
}
|
|||
|
pOldCounter = pNewCounter;
|
|||
|
dwItem = ++dwItem % dwNumEntries;
|
|||
|
pNewCounter = &lpRawValueArray[dwItem];
|
|||
|
}
|
|||
|
// compute average
|
|||
|
if (dwValidItemCount > 0) {
|
|||
|
pOldCounter = &lpRawValueArray[dwFirstValidItem];
|
|||
|
pNewCounter = &lpRawValueArray[dwLastValidItem];
|
|||
|
|
|||
|
cStatusReturn = PdhiComputeFormattedValue (
|
|||
|
pCounter->CalcFunc,
|
|||
|
pCounter->plCounterInfo.dwCounterType,
|
|||
|
pCounter->lScale,
|
|||
|
dwComputeFormat,
|
|||
|
pNewCounter,
|
|||
|
pOldCounter,
|
|||
|
&pCounter->TimeBase,
|
|||
|
0L,
|
|||
|
&fmtValue);
|
|||
|
if (cStatusReturn == ERROR_SUCCESS) {
|
|||
|
dMean = fmtValue.doubleValue;
|
|||
|
cStatusReturn = PDH_CSTATUS_VALID_DATA;
|
|||
|
}
|
|||
|
else {
|
|||
|
dMean = 0.0;
|
|||
|
}
|
|||
|
} else {
|
|||
|
dMean = 0.0;
|
|||
|
dMax = 0.0;
|
|||
|
dMin = 0.0;
|
|||
|
cStatusReturn = PDH_CSTATUS_INVALID_DATA;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
// array does not contain a valid counter so exit
|
|||
|
dMean = 0.0;
|
|||
|
dMax = 0.0;
|
|||
|
dMin = 0.0;
|
|||
|
cStatusReturn = PDH_CSTATUS_INVALID_DATA;
|
|||
|
}
|
|||
|
|
|||
|
// update user's buffer with new data
|
|||
|
data->dwFormat = dwFormat;
|
|||
|
data->count = dwValidItemCount;
|
|||
|
data->min.CStatus = cStatusReturn;
|
|||
|
data->max.CStatus = cStatusReturn;
|
|||
|
data->mean.CStatus = cStatusReturn;
|
|||
|
switch ((dwFormat & PDHI_FMT_FILTER)) {
|
|||
|
case PDH_FMT_LONG:
|
|||
|
if (dMin > (DOUBLE) MAXLONG) {
|
|||
|
data->min.longValue = MAXLONG;
|
|||
|
data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
}
|
|||
|
else {
|
|||
|
data->min.longValue = (long) dMin;
|
|||
|
}
|
|||
|
if (dMax > (DOUBLE) MAXLONG) {
|
|||
|
data->max.longValue = MAXLONG;
|
|||
|
data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
}
|
|||
|
else {
|
|||
|
data->max.longValue = (long) dMax;
|
|||
|
}
|
|||
|
if (dMean > (DOUBLE) MAXLONG) {
|
|||
|
data->mean.longValue = MAXLONG;
|
|||
|
data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
}
|
|||
|
else {
|
|||
|
data->mean.longValue = (long) dMean;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case PDH_FMT_DOUBLE:
|
|||
|
data->min.doubleValue = dMin;
|
|||
|
data->max.doubleValue = dMax;
|
|||
|
data->mean.doubleValue = dMean;
|
|||
|
break;
|
|||
|
|
|||
|
case PDH_FMT_LARGE:
|
|||
|
default:
|
|||
|
if (dMin > (DOUBLE) MAXLONGLONG) {
|
|||
|
data->min.largeValue = MAXLONGLONG;
|
|||
|
data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
}
|
|||
|
else {
|
|||
|
data->min.largeValue = (LONGLONG) dMin;
|
|||
|
}
|
|||
|
if (dMax > (DOUBLE) MAXLONGLONG) {
|
|||
|
data->max.largeValue = MAXLONGLONG;
|
|||
|
data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
}
|
|||
|
else {
|
|||
|
data->max.largeValue = (LONGLONG) dMax;
|
|||
|
}
|
|||
|
if (dMean > (DOUBLE) MAXLONGLONG) {
|
|||
|
data->mean.largeValue = MAXLONGLONG;
|
|||
|
data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
}
|
|||
|
else {
|
|||
|
data->mean.largeValue = (LONGLONG) dMean;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
return PDH_INVALID_ARGUMENT;
|
|||
|
}
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
PDH_STATUS
|
|||
|
APIENTRY
|
|||
|
PdhiComputeRawCountStats (
|
|||
|
IN PPDHI_COUNTER pCounter,
|
|||
|
IN DWORD dwFormat,
|
|||
|
IN DWORD dwFirstEntry,
|
|||
|
IN DWORD dwNumEntries,
|
|||
|
IN PPDH_RAW_COUNTER lpRawValueArray,
|
|||
|
IN PPDH_STATISTICS data
|
|||
|
)
|
|||
|
{
|
|||
|
DOUBLE dThisValue = (double)0.0;
|
|||
|
DOUBLE dMin = (double)+10E8; // these are just "big" seed numbers
|
|||
|
DOUBLE dMax = (double)-10E8;
|
|||
|
DOUBLE dMean = (double)0.0;
|
|||
|
BOOLEAN bFirstItem = TRUE;
|
|||
|
DOUBLE dScale;
|
|||
|
|
|||
|
DWORD dwItem;
|
|||
|
DWORD dwValidItemCount = 0;
|
|||
|
DWORD dwFirstValidItem = 0;
|
|||
|
DWORD dwLastValidItem = 0;
|
|||
|
DWORD dwComputeFormat;
|
|||
|
|
|||
|
PPDH_RAW_COUNTER pNewCounter;
|
|||
|
PPDH_RAW_COUNTER pOldCounter = NULL;
|
|||
|
|
|||
|
PDH_FMT_COUNTERVALUE fmtValue;
|
|||
|
|
|||
|
DWORD cStatusReturn;
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER (dwFirstEntry);
|
|||
|
__try {
|
|||
|
// initialize the user's data buffer
|
|||
|
data->dwFormat = 0;
|
|||
|
data->count = 0;
|
|||
|
data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
data->min.largeValue = 0;
|
|||
|
data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
data->max.largeValue = 0;
|
|||
|
data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
data->mean.largeValue = 0;
|
|||
|
|
|||
|
// find first valid counter in array
|
|||
|
dwItem = 0;
|
|||
|
pNewCounter = lpRawValueArray;
|
|||
|
while (dwItem < dwNumEntries) {
|
|||
|
// get value of this instance if next counter is valid
|
|||
|
if ((pNewCounter->CStatus == PDH_CSTATUS_VALID_DATA) ||
|
|||
|
(pNewCounter->CStatus == PDH_CSTATUS_NEW_DATA)) {
|
|||
|
break;
|
|||
|
} else {
|
|||
|
pOldCounter = pNewCounter;
|
|||
|
pNewCounter++;
|
|||
|
dwItem++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// do calculations in Floating point format
|
|||
|
dwComputeFormat = dwFormat;
|
|||
|
dwComputeFormat &= ~PDHI_FMT_FILTER;
|
|||
|
dwComputeFormat |= PDH_FMT_DOUBLE | PDH_FMT_NOCAP100;
|
|||
|
|
|||
|
if ((dwItem != dwNumEntries) && (dwNumEntries > 0)) {
|
|||
|
// start record found so continue
|
|||
|
dwFirstValidItem = dwItem;
|
|||
|
|
|||
|
// step through the remaining entries
|
|||
|
|
|||
|
while (dwItem < dwNumEntries) {
|
|||
|
// get value of this instance if next counter is valid
|
|||
|
if ((pNewCounter->CStatus == PDH_CSTATUS_VALID_DATA) ||
|
|||
|
(pNewCounter->CStatus == PDH_CSTATUS_NEW_DATA)) {
|
|||
|
dwLastValidItem = dwItem;
|
|||
|
|
|||
|
cStatusReturn = PdhiComputeFormattedValue (
|
|||
|
pCounter->CalcFunc,
|
|||
|
pCounter->plCounterInfo.dwCounterType,
|
|||
|
pCounter->lScale,
|
|||
|
dwComputeFormat,
|
|||
|
pNewCounter,
|
|||
|
pOldCounter,
|
|||
|
& pCounter->TimeBase,
|
|||
|
0L,
|
|||
|
& fmtValue);
|
|||
|
if (cStatusReturn == ERROR_SUCCESS) {
|
|||
|
dThisValue = fmtValue.doubleValue;
|
|||
|
|
|||
|
if (bFirstItem) {
|
|||
|
dMin = dMax = dThisValue;
|
|||
|
bFirstItem = FALSE;
|
|||
|
}
|
|||
|
else {
|
|||
|
if (dThisValue > dMax) dMax = dThisValue;
|
|||
|
if (dThisValue < dMin) dMin = dThisValue;
|
|||
|
}
|
|||
|
dMean += dThisValue;
|
|||
|
|
|||
|
dwValidItemCount ++;
|
|||
|
}
|
|||
|
}
|
|||
|
pOldCounter = pNewCounter;
|
|||
|
pNewCounter++;
|
|||
|
dwItem++;
|
|||
|
}
|
|||
|
// compute average
|
|||
|
if (dwValidItemCount > 0) {
|
|||
|
dMean /= (double)dwValidItemCount;
|
|||
|
|
|||
|
if (!(dwFormat & PDH_FMT_NOSCALE)) {
|
|||
|
//now scale
|
|||
|
dScale = pow (10.0, (double)pCounter->lScale);
|
|||
|
dMean *= dScale;
|
|||
|
dMin *= dScale;
|
|||
|
dMax *= dScale;
|
|||
|
}
|
|||
|
cStatusReturn = PDH_CSTATUS_VALID_DATA;
|
|||
|
} else {
|
|||
|
dMean = 0.0;
|
|||
|
dMax = 0.0;
|
|||
|
dMin = 0.0;
|
|||
|
cStatusReturn = PDH_CSTATUS_INVALID_DATA;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
// array does not contain a valid counter so exit
|
|||
|
dMean = 0.0;
|
|||
|
dMax = 0.0;
|
|||
|
dMin = 0.0;
|
|||
|
cStatusReturn = PDH_CSTATUS_INVALID_DATA;
|
|||
|
}
|
|||
|
|
|||
|
// update user's buffer with new data
|
|||
|
data->dwFormat = dwFormat;
|
|||
|
data->count = dwValidItemCount;
|
|||
|
data->min.CStatus = cStatusReturn;
|
|||
|
data->max.CStatus = cStatusReturn;
|
|||
|
data->mean.CStatus = cStatusReturn;
|
|||
|
switch ((dwFormat & PDHI_FMT_FILTER)) {
|
|||
|
case PDH_FMT_LONG:
|
|||
|
if (dMin > (DOUBLE) MAXLONG) {
|
|||
|
data->min.longValue = MAXLONG;
|
|||
|
data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
}
|
|||
|
else {
|
|||
|
data->min.longValue = (long) dMin;
|
|||
|
}
|
|||
|
if (dMax > (DOUBLE) MAXLONG) {
|
|||
|
data->max.longValue = MAXLONG;
|
|||
|
data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
}
|
|||
|
else {
|
|||
|
data->max.longValue = (long) dMax;
|
|||
|
}
|
|||
|
if (dMean > (DOUBLE) MAXLONG) {
|
|||
|
data->mean.longValue = MAXLONG;
|
|||
|
data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
}
|
|||
|
else {
|
|||
|
data->mean.longValue = (long) dMean;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case PDH_FMT_DOUBLE:
|
|||
|
data->min.doubleValue = dMin;
|
|||
|
data->max.doubleValue = dMax;
|
|||
|
data->mean.doubleValue = dMean;
|
|||
|
break;
|
|||
|
|
|||
|
case PDH_FMT_LARGE:
|
|||
|
default:
|
|||
|
if (dMin > (DOUBLE) MAXLONGLONG) {
|
|||
|
data->min.largeValue = MAXLONGLONG;
|
|||
|
data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
}
|
|||
|
else {
|
|||
|
data->min.largeValue = (LONGLONG) dMin;
|
|||
|
}
|
|||
|
if (dMax > (DOUBLE) MAXLONGLONG) {
|
|||
|
data->max.largeValue = MAXLONGLONG;
|
|||
|
data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
}
|
|||
|
else {
|
|||
|
data->max.largeValue = (LONGLONG) dMax;
|
|||
|
}
|
|||
|
if (dMean > (DOUBLE) MAXLONGLONG) {
|
|||
|
data->mean.largeValue = MAXLONGLONG;
|
|||
|
data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
}
|
|||
|
else {
|
|||
|
data->mean.largeValue = (LONGLONG) dMean;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
return PDH_INVALID_ARGUMENT;
|
|||
|
}
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
PDH_STATUS
|
|||
|
APIENTRY
|
|||
|
PdhiComputeNoDataStats (
|
|||
|
IN PPDHI_COUNTER pCounter,
|
|||
|
IN DWORD dwFormat,
|
|||
|
IN DWORD dwFirstEntry,
|
|||
|
IN DWORD dwNumEntries,
|
|||
|
IN PPDH_RAW_COUNTER lpRawValueArray,
|
|||
|
IN PPDH_STATISTICS data
|
|||
|
)
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER (pCounter);
|
|||
|
UNREFERENCED_PARAMETER (dwFirstEntry);
|
|||
|
UNREFERENCED_PARAMETER (dwNumEntries);
|
|||
|
UNREFERENCED_PARAMETER (lpRawValueArray);
|
|||
|
__try {
|
|||
|
data->dwFormat = dwFormat;
|
|||
|
data->count = 0;
|
|||
|
data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
|
|||
|
switch ((dwFormat & PDHI_FMT_FILTER)) {
|
|||
|
case PDH_FMT_LONG:
|
|||
|
data->min.doubleValue = 0;
|
|||
|
data->max.longValue = 0;
|
|||
|
data->mean.longValue = 0;
|
|||
|
break;
|
|||
|
|
|||
|
case PDH_FMT_DOUBLE:
|
|||
|
data->min.doubleValue = (double)0;
|
|||
|
data->max.doubleValue = (double)0;
|
|||
|
data->mean.doubleValue = (double)0.0;
|
|||
|
break;
|
|||
|
|
|||
|
case PDH_FMT_LARGE:
|
|||
|
default:
|
|||
|
data->min.largeValue = 0;
|
|||
|
data->max.largeValue = 0;
|
|||
|
data->mean.largeValue = 0;
|
|||
|
break;
|
|||
|
}
|
|||
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
return PDH_INVALID_ARGUMENT;
|
|||
|
}
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|