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

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. Abstract:
  5. History:
  6. --*/
  7. // Cooker.cpp
  8. #include "precomp.h"
  9. #include <winperf.h>
  10. #include "pdh.h"
  11. #include "pdhmsg.h"
  12. #include <pdhicalc.h>
  13. #include "RawCooker.h"
  14. CCalcTable::CCalcTable()
  15. {
  16. m_lSize = 5;
  17. // Ordered list based on Perf IDs
  18. // ==============================
  19. m_aTable[0].Init( 0x00000001, CRawCooker::_Average );
  20. m_aTable[1].Init( 0x00000002, CRawCooker::_Min );
  21. m_aTable[2].Init( 0x00000003, CRawCooker::_Max );
  22. m_aTable[3].Init( 0x00000004, CRawCooker::_Range );
  23. m_aTable[4].Init( 0x00000005, CRawCooker::_Variance );
  24. }
  25. CCalcTable::~CCalcTable()
  26. {
  27. }
  28. CCalcRecord* CCalcTable::GetCalcRecord( DWORD dwCookingType )
  29. {
  30. CCalcRecord* pCalcRecord = NULL;
  31. long left = 0,
  32. right = m_lSize - 1,
  33. mid = right / 2;
  34. DWORD dwMidVal = 0;
  35. bool bFound = FALSE;
  36. while ( !bFound && ( left <= right ) )
  37. {
  38. dwMidVal = m_aTable[mid].GetID();
  39. if ( dwCookingType < dwMidVal )
  40. {
  41. right = mid - 1;
  42. mid = ( left + right ) / 2;
  43. }
  44. else if ( dwCookingType > dwMidVal )
  45. {
  46. left = mid + 1;
  47. mid = ( left + right ) / 2;
  48. }
  49. else
  50. {
  51. bFound = TRUE;
  52. pCalcRecord = &m_aTable[mid];
  53. }
  54. }
  55. return pCalcRecord;
  56. }
  57. CRawCooker::CRawCooker() : m_lRef( 1 ), m_pCalcRecord( NULL )
  58. {
  59. }
  60. CRawCooker::~CRawCooker()
  61. {
  62. }
  63. //////////////////////////////////////////////////////////////
  64. //
  65. // COM methods
  66. //
  67. //////////////////////////////////////////////////////////////
  68. STDMETHODIMP CRawCooker::QueryInterface(REFIID riid, void** ppv)
  69. //////////////////////////////////////////////////////////////
  70. //
  71. // Standard QueryInterface
  72. //
  73. // Parameters:
  74. // riid - the ID of the requested interface
  75. // ppv - a pointer to the interface pointer
  76. //
  77. //////////////////////////////////////////////////////////////
  78. //ok
  79. {
  80. if(riid == IID_IUnknown)
  81. *ppv = (LPVOID)(IUnknown*)(IWMISimpleCooker*)this;
  82. else if(riid == IID_IWMISimpleCooker)
  83. *ppv = (LPVOID)(IWMISimpleCooker*)this;
  84. else return E_NOINTERFACE;
  85. ((IUnknown*)*ppv)->AddRef();
  86. return S_OK;
  87. }
  88. STDMETHODIMP_(ULONG) CRawCooker::AddRef()
  89. //////////////////////////////////////////////////////////////
  90. //
  91. // Standard COM AddRef
  92. //
  93. //////////////////////////////////////////////////////////////
  94. //ok
  95. {
  96. return InterlockedIncrement(&m_lRef);
  97. }
  98. STDMETHODIMP_(ULONG) CRawCooker::Release()
  99. //////////////////////////////////////////////////////////////
  100. //
  101. // Standard COM Release
  102. //
  103. //////////////////////////////////////////////////////////////
  104. //ok
  105. {
  106. long lRef = InterlockedDecrement(&m_lRef);
  107. if(lRef == 0)
  108. delete this;
  109. return lRef;
  110. }
  111. STDMETHODIMP CRawCooker::CookRawValues(
  112. /*[in] */ DWORD dwCookingType,
  113. /*[in] */ DWORD dwNumSamples,
  114. /*[in] */ __int64* anTimeStamp,
  115. /*[in] */ __int64* anRawValue,
  116. /*[in] */ __int64* anBase,
  117. /*[in] */ __int64 nTimeFrequency,
  118. /*[in] */ long lScale,
  119. /*[out]*/ __int64* pnResult )
  120. {
  121. HRESULT hResult = S_OK;
  122. PDH_STATUS lRet = 0;
  123. LPCOUNTERCALC pCalcFunction = NULL;
  124. LPCOUNTERSTAT pStatFunction = NULL;
  125. PDH_FMT_COUNTERVALUE fmtValue;
  126. memset( &fmtValue, 0, sizeof( PDH_FMT_COUNTERVALUE ) );
  127. if ( AssignCalcFunction( dwCookingType, &pCalcFunction, &pStatFunction ) && ( 2 == dwNumSamples ) )
  128. {
  129. PDH_RAW_COUNTER RawValue1;
  130. PDH_RAW_COUNTER RawValue2;
  131. RawValue1.CStatus = 0;
  132. RawValue1.MultiCount = 0;
  133. RawValue2.CStatus = 0;
  134. RawValue2.MultiCount = 0;
  135. if ((dwCookingType == PERF_RAW_FRACTION) ||
  136. (dwCookingType == PERF_SAMPLE_FRACTION) ||
  137. (dwCookingType == PERF_AVERAGE_TIMER) ||
  138. (dwCookingType == PERF_AVERAGE_BULK)) {
  139. RawValue1.TimeStamp = *(FILETIME*)&anTimeStamp[0];
  140. RawValue1.FirstValue = anRawValue[0];
  141. RawValue1.SecondValue = anBase[0];
  142. RawValue2.TimeStamp = *(FILETIME*)&anTimeStamp[1];
  143. RawValue2.FirstValue = anRawValue[1];
  144. RawValue2.SecondValue = anBase[1];
  145. } else {
  146. RawValue1.TimeStamp = *(FILETIME *)&anBase[0];
  147. RawValue1.FirstValue = anRawValue[0];
  148. RawValue1.SecondValue = anTimeStamp[0];
  149. RawValue2.TimeStamp = *(FILETIME *)&anBase[1];
  150. RawValue2.FirstValue = anRawValue[1];
  151. RawValue2.SecondValue = anTimeStamp[1];
  152. }
  153. DWORD dwFormat = PDH_FMT_LARGE;
  154. // do not scale if lScale is 0
  155. if (!lScale)
  156. {
  157. dwFormat |= PDH_FMT_NOSCALE;
  158. }
  159. lRet = PdhiComputeFormattedValue(
  160. pCalcFunction,
  161. dwCookingType,
  162. lScale,
  163. dwFormat, //PDH_FMT_NOSCALE | PDH_FMT_LARGE,
  164. &RawValue1,
  165. &RawValue2,
  166. &nTimeFrequency,
  167. 0,
  168. &fmtValue );
  169. if ( 0 == lRet )
  170. *pnResult = fmtValue.largeValue;
  171. else if (lRet == PDH_CALC_NEGATIVE_VALUE ||
  172. lRet == PDH_CALC_NEGATIVE_DENOMINATOR) {
  173. *pnResult = 0;
  174. } else {
  175. hResult = lRet; //WBEM_E_FAILED;
  176. }
  177. }
  178. else
  179. {
  180. // The last calculation record is cached in an attempt to avoid a new
  181. // search. A cooking type of zero means "use the last clac record"
  182. // ==================================================================
  183. if ( NULL == m_pCalcRecord || ( m_pCalcRecord->GetID() != dwCookingType ) &&
  184. ( m_pCalcRecord->GetID() != 0 ) )
  185. {
  186. m_pCalcRecord = m_CalcTable.GetCalcRecord( dwCookingType );
  187. if ( NULL == m_pCalcRecord )
  188. {
  189. hResult = E_FAIL;
  190. }
  191. }
  192. if ( SUCCEEDED( hResult ) )
  193. {
  194. // Calculate the result
  195. // ====================
  196. PERFCALC* pCalc = m_pCalcRecord->GetCalc();
  197. if ( NULL != pCalc )
  198. {
  199. hResult = pCalc( dwNumSamples,
  200. anTimeStamp,
  201. anRawValue,
  202. anBase,
  203. nTimeFrequency,
  204. pnResult );
  205. }
  206. }
  207. }
  208. return hResult;
  209. }
  210. //////////////////////////////////////////////////////////////
  211. //
  212. // Perf Calculations
  213. //
  214. //////////////////////////////////////////////////////////////
  215. WMISTATUS APIENTRY CRawCooker::_Average( DWORD dwNumSamples,
  216. __int64* anTimeStamp,
  217. __int64* anRawValue,
  218. __int64* anBase,
  219. __int64 nTimeFrequency,
  220. __int64* pnResult)
  221. {
  222. WMISTATUS dwStatus = WBEM_NO_ERROR;
  223. __int64 nVal = 0;
  224. if ( 0 == dwNumSamples )
  225. {
  226. dwStatus = WBEM_E_FAILED;
  227. }
  228. for ( DWORD dwSample = 0; SUCCEEDED( dwStatus ) && dwSample < dwNumSamples; dwSample++ )
  229. {
  230. if ( (0x7FFFFFFFFFFFFFFF - nVal) < anRawValue[dwSample] )
  231. dwStatus = WBEM_E_INVALID_OPERATION;
  232. else
  233. nVal += anRawValue[dwSample];
  234. }
  235. *pnResult = nVal / dwNumSamples;
  236. return dwStatus;
  237. }
  238. WMISTATUS APIENTRY CRawCooker::_Min( DWORD dwNumSamples,
  239. __int64* anTimeStamp,
  240. __int64* anRawValue,
  241. __int64* anBase,
  242. __int64 nTimeFrequency,
  243. __int64* pnResult)
  244. {
  245. if ( 0 == dwNumSamples ){
  246. return WBEM_E_FAILED;
  247. };
  248. __int64 nVal = anRawValue[0];
  249. for ( DWORD dwSample = 1; dwSample < dwNumSamples; dwSample++ ){
  250. if ( anRawValue[dwSample] < nVal ){
  251. nVal = anRawValue[dwSample];
  252. }
  253. }
  254. *pnResult = nVal;
  255. return WBEM_NO_ERROR;
  256. }
  257. WMISTATUS APIENTRY CRawCooker::_Max( DWORD dwNumSamples,
  258. __int64* anTimeStamp,
  259. __int64* anRawValue,
  260. __int64* anBase,
  261. __int64 nTimeFrequency,
  262. __int64* pnResult)
  263. {
  264. if ( 0 == dwNumSamples ){
  265. return WBEM_E_FAILED;
  266. };
  267. __int64 nVal = anRawValue[0];
  268. for ( DWORD dwSample = 1; dwSample < dwNumSamples; dwSample++ ){
  269. if ( anRawValue[dwSample] > nVal ){
  270. nVal = anRawValue[dwSample];
  271. }
  272. }
  273. *pnResult = nVal;
  274. return WBEM_NO_ERROR;
  275. }
  276. WMISTATUS APIENTRY CRawCooker::_Range( DWORD dwNumSamples,
  277. __int64* anTimeStamp,
  278. __int64* anRawValue,
  279. __int64* anBase,
  280. __int64 nTimeFrequency,
  281. __int64* pnResult)
  282. {
  283. if ( 0 == dwNumSamples ){
  284. return WBEM_E_FAILED;
  285. };
  286. __int64 nValMin = anRawValue[0];
  287. __int64 nValMax = anRawValue[0];
  288. for ( DWORD dwSample = 1; dwSample < dwNumSamples; dwSample++ ){
  289. if ( anRawValue[dwSample] > nValMax ){
  290. nValMax = anRawValue[dwSample];
  291. };
  292. if ( anRawValue[dwSample] < nValMin ){
  293. nValMin = anRawValue[dwSample];
  294. };
  295. }
  296. *pnResult = (nValMax - nValMin);
  297. return WBEM_NO_ERROR;
  298. }
  299. WMISTATUS APIENTRY CRawCooker::_Variance( DWORD dwNumSamples,
  300. __int64* anTimeStamp,
  301. __int64* anRawValue,
  302. __int64* anBase,
  303. __int64 nTimeFrequency,
  304. __int64* pnResult)
  305. {
  306. if ( 0 == dwNumSamples ){
  307. return WBEM_E_FAILED;
  308. };
  309. double SumX_i = 0;
  310. double Average = 0;
  311. for ( DWORD dwSample = 0; dwSample < dwNumSamples; dwSample++ ){
  312. SumX_i += (anRawValue[dwSample]*anRawValue[dwSample]);
  313. Average += anRawValue[dwSample];
  314. }
  315. double Tmp = (double(SumX_i/dwNumSamples) - (double(Average/dwNumSamples)*double(Average/dwNumSamples)));
  316. *pnResult = __int64(Tmp);
  317. return WBEM_NO_ERROR;
  318. }