Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

408 lines
8.5 KiB

/*++
Copyright (C) 1996-2001 Microsoft Corporation
Module Name:
Abstract:
History:
--*/
// Cooker.cpp
#include "precomp.h"
#include <winperf.h>
#include "pdh.h"
#include "pdhmsg.h"
#include <pdhicalc.h>
#include "RawCooker.h"
CCalcTable::CCalcTable()
{
m_lSize = 5;
// Ordered list based on Perf IDs
// ==============================
m_aTable[0].Init( 0x00000001, CRawCooker::_Average );
m_aTable[1].Init( 0x00000002, CRawCooker::_Min );
m_aTable[2].Init( 0x00000003, CRawCooker::_Max );
m_aTable[3].Init( 0x00000004, CRawCooker::_Range );
m_aTable[4].Init( 0x00000005, CRawCooker::_Variance );
}
CCalcTable::~CCalcTable()
{
}
CCalcRecord* CCalcTable::GetCalcRecord( DWORD dwCookingType )
{
CCalcRecord* pCalcRecord = NULL;
long left = 0,
right = m_lSize - 1,
mid = right / 2;
DWORD dwMidVal = 0;
bool bFound = FALSE;
while ( !bFound && ( left <= right ) )
{
dwMidVal = m_aTable[mid].GetID();
if ( dwCookingType < dwMidVal )
{
right = mid - 1;
mid = ( left + right ) / 2;
}
else if ( dwCookingType > dwMidVal )
{
left = mid + 1;
mid = ( left + right ) / 2;
}
else
{
bFound = TRUE;
pCalcRecord = &m_aTable[mid];
}
}
return pCalcRecord;
}
CRawCooker::CRawCooker() : m_lRef( 1 ), m_pCalcRecord( NULL )
{
}
CRawCooker::~CRawCooker()
{
}
//////////////////////////////////////////////////////////////
//
// COM methods
//
//////////////////////////////////////////////////////////////
STDMETHODIMP CRawCooker::QueryInterface(REFIID riid, void** ppv)
//////////////////////////////////////////////////////////////
//
// Standard QueryInterface
//
// Parameters:
// riid - the ID of the requested interface
// ppv - a pointer to the interface pointer
//
//////////////////////////////////////////////////////////////
//ok
{
if(riid == IID_IUnknown)
*ppv = (LPVOID)(IUnknown*)(IWMISimpleCooker*)this;
else if(riid == IID_IWMISimpleCooker)
*ppv = (LPVOID)(IWMISimpleCooker*)this;
else return E_NOINTERFACE;
((IUnknown*)*ppv)->AddRef();
return S_OK;
}
STDMETHODIMP_(ULONG) CRawCooker::AddRef()
//////////////////////////////////////////////////////////////
//
// Standard COM AddRef
//
//////////////////////////////////////////////////////////////
//ok
{
return InterlockedIncrement(&m_lRef);
}
STDMETHODIMP_(ULONG) CRawCooker::Release()
//////////////////////////////////////////////////////////////
//
// Standard COM Release
//
//////////////////////////////////////////////////////////////
//ok
{
long lRef = InterlockedDecrement(&m_lRef);
if(lRef == 0)
delete this;
return lRef;
}
STDMETHODIMP CRawCooker::CookRawValues(
/*[in] */ DWORD dwCookingType,
/*[in] */ DWORD dwNumSamples,
/*[in] */ __int64* anTimeStamp,
/*[in] */ __int64* anRawValue,
/*[in] */ __int64* anBase,
/*[in] */ __int64 nTimeFrequency,
/*[in] */ long lScale,
/*[out]*/ __int64* pnResult )
{
HRESULT hResult = S_OK;
PDH_STATUS lRet = 0;
LPCOUNTERCALC pCalcFunction = NULL;
LPCOUNTERSTAT pStatFunction = NULL;
PDH_FMT_COUNTERVALUE fmtValue;
memset( &fmtValue, 0, sizeof( PDH_FMT_COUNTERVALUE ) );
if ( AssignCalcFunction( dwCookingType, &pCalcFunction, &pStatFunction ) && ( 2 == dwNumSamples ) )
{
PDH_RAW_COUNTER RawValue1;
PDH_RAW_COUNTER RawValue2;
RawValue1.CStatus = 0;
RawValue1.MultiCount = 0;
RawValue2.CStatus = 0;
RawValue2.MultiCount = 0;
if ((dwCookingType == PERF_RAW_FRACTION) ||
(dwCookingType == PERF_SAMPLE_FRACTION) ||
(dwCookingType == PERF_AVERAGE_TIMER) ||
(dwCookingType == PERF_AVERAGE_BULK)) {
RawValue1.TimeStamp = *(FILETIME*)&anTimeStamp[0];
RawValue1.FirstValue = anRawValue[0];
RawValue1.SecondValue = anBase[0];
RawValue2.TimeStamp = *(FILETIME*)&anTimeStamp[1];
RawValue2.FirstValue = anRawValue[1];
RawValue2.SecondValue = anBase[1];
} else {
RawValue1.TimeStamp = *(FILETIME *)&anBase[0];
RawValue1.FirstValue = anRawValue[0];
RawValue1.SecondValue = anTimeStamp[0];
RawValue2.TimeStamp = *(FILETIME *)&anBase[1];
RawValue2.FirstValue = anRawValue[1];
RawValue2.SecondValue = anTimeStamp[1];
}
DWORD dwFormat = PDH_FMT_LARGE;
// do not scale if lScale is 0
if (!lScale)
{
dwFormat |= PDH_FMT_NOSCALE;
}
lRet = PdhiComputeFormattedValue(
pCalcFunction,
dwCookingType,
lScale,
dwFormat, //PDH_FMT_NOSCALE | PDH_FMT_LARGE,
&RawValue1,
&RawValue2,
&nTimeFrequency,
0,
&fmtValue );
if ( 0 == lRet )
*pnResult = fmtValue.largeValue;
else if (lRet == PDH_CALC_NEGATIVE_VALUE ||
lRet == PDH_CALC_NEGATIVE_DENOMINATOR) {
*pnResult = 0;
} else {
hResult = lRet; //WBEM_E_FAILED;
}
}
else
{
// The last calculation record is cached in an attempt to avoid a new
// search. A cooking type of zero means "use the last clac record"
// ==================================================================
if ( NULL == m_pCalcRecord || ( m_pCalcRecord->GetID() != dwCookingType ) &&
( m_pCalcRecord->GetID() != 0 ) )
{
m_pCalcRecord = m_CalcTable.GetCalcRecord( dwCookingType );
if ( NULL == m_pCalcRecord )
{
hResult = E_FAIL;
}
}
if ( SUCCEEDED( hResult ) )
{
// Calculate the result
// ====================
PERFCALC* pCalc = m_pCalcRecord->GetCalc();
if ( NULL != pCalc )
{
hResult = pCalc( dwNumSamples,
anTimeStamp,
anRawValue,
anBase,
nTimeFrequency,
pnResult );
}
}
}
return hResult;
}
//////////////////////////////////////////////////////////////
//
// Perf Calculations
//
//////////////////////////////////////////////////////////////
WMISTATUS APIENTRY CRawCooker::_Average( DWORD dwNumSamples,
__int64* anTimeStamp,
__int64* anRawValue,
__int64* anBase,
__int64 nTimeFrequency,
__int64* pnResult)
{
WMISTATUS dwStatus = WBEM_NO_ERROR;
__int64 nVal = 0;
if ( 0 == dwNumSamples )
{
dwStatus = WBEM_E_FAILED;
}
for ( DWORD dwSample = 0; SUCCEEDED( dwStatus ) && dwSample < dwNumSamples; dwSample++ )
{
if ( (0x7FFFFFFFFFFFFFFF - nVal) < anRawValue[dwSample] )
dwStatus = WBEM_E_INVALID_OPERATION;
else
nVal += anRawValue[dwSample];
}
*pnResult = nVal / dwNumSamples;
return dwStatus;
}
WMISTATUS APIENTRY CRawCooker::_Min( DWORD dwNumSamples,
__int64* anTimeStamp,
__int64* anRawValue,
__int64* anBase,
__int64 nTimeFrequency,
__int64* pnResult)
{
if ( 0 == dwNumSamples ){
return WBEM_E_FAILED;
};
__int64 nVal = anRawValue[0];
for ( DWORD dwSample = 1; dwSample < dwNumSamples; dwSample++ ){
if ( anRawValue[dwSample] < nVal ){
nVal = anRawValue[dwSample];
}
}
*pnResult = nVal;
return WBEM_NO_ERROR;
}
WMISTATUS APIENTRY CRawCooker::_Max( DWORD dwNumSamples,
__int64* anTimeStamp,
__int64* anRawValue,
__int64* anBase,
__int64 nTimeFrequency,
__int64* pnResult)
{
if ( 0 == dwNumSamples ){
return WBEM_E_FAILED;
};
__int64 nVal = anRawValue[0];
for ( DWORD dwSample = 1; dwSample < dwNumSamples; dwSample++ ){
if ( anRawValue[dwSample] > nVal ){
nVal = anRawValue[dwSample];
}
}
*pnResult = nVal;
return WBEM_NO_ERROR;
}
WMISTATUS APIENTRY CRawCooker::_Range( DWORD dwNumSamples,
__int64* anTimeStamp,
__int64* anRawValue,
__int64* anBase,
__int64 nTimeFrequency,
__int64* pnResult)
{
if ( 0 == dwNumSamples ){
return WBEM_E_FAILED;
};
__int64 nValMin = anRawValue[0];
__int64 nValMax = anRawValue[0];
for ( DWORD dwSample = 1; dwSample < dwNumSamples; dwSample++ ){
if ( anRawValue[dwSample] > nValMax ){
nValMax = anRawValue[dwSample];
};
if ( anRawValue[dwSample] < nValMin ){
nValMin = anRawValue[dwSample];
};
}
*pnResult = (nValMax - nValMin);
return WBEM_NO_ERROR;
}
WMISTATUS APIENTRY CRawCooker::_Variance( DWORD dwNumSamples,
__int64* anTimeStamp,
__int64* anRawValue,
__int64* anBase,
__int64 nTimeFrequency,
__int64* pnResult)
{
if ( 0 == dwNumSamples ){
return WBEM_E_FAILED;
};
double SumX_i = 0;
double Average = 0;
for ( DWORD dwSample = 0; dwSample < dwNumSamples; dwSample++ ){
SumX_i += (anRawValue[dwSample]*anRawValue[dwSample]);
Average += anRawValue[dwSample];
}
double Tmp = (double(SumX_i/dwNumSamples) - (double(Average/dwNumSamples)*double(Average/dwNumSamples)));
*pnResult = __int64(Tmp);
return WBEM_NO_ERROR;
}