/*++ Copyright (C) 1996-1999 Microsoft Corporation Module Name: statfuns.c Abstract: Statistical calculation functions --*/ #include #include #include "strsafe.h" #include #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; }