You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
488 lines
18 KiB
488 lines
18 KiB
/*++
|
|
|
|
Copyright (C) 1996-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
statfuns.c
|
|
|
|
Abstract:
|
|
|
|
Statistical calculation functions
|
|
|
|
--*/
|
|
|
|
#include <windows.h>
|
|
#include <math.h>
|
|
#include "strsafe.h"
|
|
#include <pdh.h>
|
|
#include "pdhitype.h"
|
|
#include "pdhidef.h"
|
|
#include "pdhicalc.h"
|
|
#include "pdhmsg.h"
|
|
|
|
#define PDHI_FMT_FILTER (PDH_FMT_LONG | PDH_FMT_DOUBLE | PDH_FMT_LARGE)
|
|
|
|
PDH_STATUS
|
|
APIENTRY
|
|
PdhiComputeFirstLastStats(
|
|
PPDHI_COUNTER pCounter,
|
|
DWORD dwFormat,
|
|
DWORD dwFirstEntry,
|
|
DWORD dwNumEntries,
|
|
PPDH_RAW_COUNTER lpRawValueArray,
|
|
PPDH_STATISTICS data
|
|
)
|
|
{
|
|
PDH_STATUS Status = ERROR_SUCCESS;
|
|
DOUBLE dThisValue = (double) 0.0;
|
|
DOUBLE dMin = (double) +10E8; // these are just "big" seed numbers
|
|
DOUBLE dMax = (double) -10E8;
|
|
DOUBLE dMean = (double) 0.0;
|
|
DOUBLE dTotal = (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;
|
|
}
|
|
dTotal += 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 = dTotal / dwValidItemCount;
|
|
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) {
|
|
Status = PDH_INVALID_ARGUMENT;
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
PDH_STATUS
|
|
APIENTRY
|
|
PdhiComputeRawCountStats(
|
|
PPDHI_COUNTER pCounter,
|
|
DWORD dwFormat,
|
|
DWORD dwFirstEntry,
|
|
DWORD dwNumEntries,
|
|
PPDH_RAW_COUNTER lpRawValueArray,
|
|
PPDH_STATISTICS data
|
|
)
|
|
{
|
|
PDH_STATUS Status = ERROR_SUCCESS;
|
|
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) {
|
|
Status = PDH_INVALID_ARGUMENT;
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
PDH_STATUS
|
|
APIENTRY
|
|
PdhiComputeNoDataStats(
|
|
PPDHI_COUNTER pCounter,
|
|
DWORD dwFormat,
|
|
DWORD dwFirstEntry,
|
|
DWORD dwNumEntries,
|
|
PPDH_RAW_COUNTER lpRawValueArray,
|
|
PPDH_STATISTICS data
|
|
)
|
|
{
|
|
PDH_STATUS Status = ERROR_SUCCESS;
|
|
|
|
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) {
|
|
Status = PDH_INVALID_ARGUMENT;
|
|
}
|
|
return Status;
|
|
}
|