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;
|
||
}
|