Leaked source code of windows server 2003
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.

403 lines
11 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 (NULL == ppv) return E_POINTER;
  81. if(riid == IID_IUnknown)
  82. *ppv = (LPVOID)(IUnknown*)(IWMISimpleCooker*)this;
  83. else if(riid == IID_IWMISimpleCooker)
  84. *ppv = (LPVOID)(IWMISimpleCooker*)this;
  85. else {
  86. *ppv = NULL;
  87. return E_NOINTERFACE;
  88. }
  89. ((IUnknown*)*ppv)->AddRef();
  90. return S_OK;
  91. }
  92. STDMETHODIMP_(ULONG) CRawCooker::AddRef()
  93. //////////////////////////////////////////////////////////////
  94. //
  95. // Standard COM AddRef
  96. //
  97. //////////////////////////////////////////////////////////////
  98. //ok
  99. {
  100. return InterlockedIncrement(&m_lRef);
  101. }
  102. STDMETHODIMP_(ULONG) CRawCooker::Release()
  103. //////////////////////////////////////////////////////////////
  104. //
  105. // Standard COM Release
  106. //
  107. //////////////////////////////////////////////////////////////
  108. //ok
  109. {
  110. long lRef = InterlockedDecrement(&m_lRef);
  111. if(lRef == 0) delete this;
  112. return lRef;
  113. }
  114. STDMETHODIMP CRawCooker::CookRawValues(
  115. /*[in] */ DWORD dwCookingType,
  116. /*[in] */ DWORD dwNumSamples,
  117. /*[in] */ __int64* anTimeStamp,
  118. /*[in] */ __int64* anRawValue,
  119. /*[in] */ __int64* anBase,
  120. /*[in] */ __int64 nTimeFrequency,
  121. /*[in] */ long lScale,
  122. /*[out]*/ __int64* pnResult )
  123. {
  124. HRESULT hResult = S_OK;
  125. PDH_STATUS lRet = 0;
  126. LPCOUNTERCALC pCalcFunction = NULL;
  127. LPCOUNTERSTAT pStatFunction = NULL;
  128. PDH_FMT_COUNTERVALUE fmtValue;
  129. memset( &fmtValue, 0, sizeof( PDH_FMT_COUNTERVALUE ) );
  130. if ( AssignCalcFunction( dwCookingType, &pCalcFunction, &pStatFunction ) && ( 2 == dwNumSamples ) )
  131. {
  132. PDH_RAW_COUNTER RawValue1;
  133. PDH_RAW_COUNTER RawValue2;
  134. RawValue1.CStatus = 0;
  135. RawValue1.MultiCount = 0;
  136. RawValue2.CStatus = 0;
  137. RawValue2.MultiCount = 0;
  138. if ((dwCookingType == PERF_RAW_FRACTION) ||
  139. (dwCookingType == PERF_SAMPLE_FRACTION) ||
  140. (dwCookingType == PERF_AVERAGE_TIMER) ||
  141. (dwCookingType == PERF_AVERAGE_BULK))
  142. {
  143. RawValue1.TimeStamp = *(FILETIME*)&anTimeStamp[0];
  144. RawValue1.FirstValue = anRawValue[0];
  145. RawValue1.SecondValue = anBase[0];
  146. RawValue2.TimeStamp = *(FILETIME*)&anTimeStamp[1];
  147. RawValue2.FirstValue = anRawValue[1];
  148. RawValue2.SecondValue = anBase[1];
  149. }
  150. else
  151. {
  152. RawValue1.TimeStamp = *(FILETIME *)&anBase[0];
  153. RawValue1.FirstValue = anRawValue[0];
  154. RawValue1.SecondValue = anTimeStamp[0];
  155. RawValue2.TimeStamp = *(FILETIME *)&anBase[1];
  156. RawValue2.FirstValue = anRawValue[1];
  157. RawValue2.SecondValue = anTimeStamp[1];
  158. }
  159. DWORD dwFormat = PDH_FMT_LARGE;
  160. // do not scale if lScale is 0
  161. if (!lScale)
  162. {
  163. dwFormat |= PDH_FMT_NOSCALE;
  164. }
  165. lRet = PdhiComputeFormattedValue(
  166. pCalcFunction,
  167. dwCookingType,
  168. lScale,
  169. dwFormat, //PDH_FMT_NOSCALE | PDH_FMT_LARGE,
  170. &RawValue1,
  171. &RawValue2,
  172. &nTimeFrequency,
  173. 0,
  174. &fmtValue );
  175. if ( 0 == lRet )
  176. *pnResult = fmtValue.largeValue;
  177. else if (lRet == PDH_CALC_NEGATIVE_VALUE ||
  178. lRet == PDH_CALC_NEGATIVE_DENOMINATOR)
  179. {
  180. *pnResult = 0;
  181. }
  182. else
  183. {
  184. hResult = lRet; //WBEM_E_FAILED;
  185. }
  186. }
  187. else
  188. {
  189. // The last calculation record is cached in an attempt to avoid a new
  190. // search. A cooking type of zero means "use the last calc record"
  191. // ==================================================================
  192. if ( NULL == m_pCalcRecord || ( m_pCalcRecord->GetID() != dwCookingType ) &&
  193. ( m_pCalcRecord->GetID() != 0 ) )
  194. {
  195. m_pCalcRecord = m_CalcTable.GetCalcRecord( dwCookingType );
  196. if ( NULL == m_pCalcRecord )
  197. {
  198. hResult = E_FAIL;
  199. }
  200. }
  201. if ( SUCCEEDED( hResult ) )
  202. {
  203. // Calculate the result
  204. // ====================
  205. PERFCALC* pCalc = m_pCalcRecord->GetCalc();
  206. if ( NULL != pCalc )
  207. {
  208. hResult = pCalc( dwNumSamples,
  209. anTimeStamp,
  210. anRawValue,
  211. anBase,
  212. nTimeFrequency,
  213. pnResult );
  214. }
  215. }
  216. }
  217. return hResult;
  218. }
  219. //////////////////////////////////////////////////////////////
  220. //
  221. // Perf Calculations
  222. //
  223. //////////////////////////////////////////////////////////////
  224. WMISTATUS APIENTRY CRawCooker::_Average( DWORD dwNumSamples,
  225. __int64* anTimeStamp,
  226. __int64* anRawValue,
  227. __int64* anBase,
  228. __int64 nTimeFrequency,
  229. __int64* pnResult)
  230. {
  231. WMISTATUS dwStatus = WBEM_NO_ERROR;
  232. __int64 nVal = 0;
  233. if ( 0 == dwNumSamples || NULL == pnResult) return WBEM_E_FAILED;
  234. for ( DWORD dwSample = 0; SUCCEEDED( dwStatus ) && dwSample < dwNumSamples; dwSample++ )
  235. {
  236. if ( (0x7FFFFFFFFFFFFFFF - nVal) < anRawValue[dwSample] )
  237. dwStatus = WBEM_E_INVALID_OPERATION;
  238. else
  239. nVal += anRawValue[dwSample];
  240. }
  241. *pnResult = nVal / dwNumSamples;
  242. return dwStatus;
  243. }
  244. WMISTATUS APIENTRY CRawCooker::_Min( DWORD dwNumSamples,
  245. __int64* anTimeStamp,
  246. __int64* anRawValue,
  247. __int64* anBase,
  248. __int64 nTimeFrequency,
  249. __int64* pnResult)
  250. {
  251. if ( 0 == dwNumSamples || NULL == pnResult) return WBEM_E_FAILED;
  252. __int64 nVal = anRawValue[0];
  253. for ( DWORD dwSample = 1; dwSample < dwNumSamples; dwSample++ )
  254. {
  255. if ( anRawValue[dwSample] < nVal )
  256. nVal = anRawValue[dwSample];
  257. }
  258. *pnResult = nVal;
  259. return WBEM_NO_ERROR;
  260. }
  261. WMISTATUS APIENTRY CRawCooker::_Max( DWORD dwNumSamples,
  262. __int64* anTimeStamp,
  263. __int64* anRawValue,
  264. __int64* anBase,
  265. __int64 nTimeFrequency,
  266. __int64* pnResult)
  267. {
  268. if ( 0 == dwNumSamples || NULL == pnResult) return WBEM_E_FAILED;
  269. __int64 nVal = anRawValue[0];
  270. for ( DWORD dwSample = 1; dwSample < dwNumSamples; dwSample++ )
  271. {
  272. if ( anRawValue[dwSample] > nVal )
  273. nVal = anRawValue[dwSample];
  274. }
  275. *pnResult = nVal;
  276. return WBEM_NO_ERROR;
  277. }
  278. WMISTATUS APIENTRY CRawCooker::_Range( DWORD dwNumSamples,
  279. __int64* anTimeStamp,
  280. __int64* anRawValue,
  281. __int64* anBase,
  282. __int64 nTimeFrequency,
  283. __int64* pnResult)
  284. {
  285. if ( 0 == dwNumSamples || NULL == pnResult) return WBEM_E_FAILED;
  286. __int64 nValMin = anRawValue[0];
  287. __int64 nValMax = anRawValue[0];
  288. for ( DWORD dwSample = 1; dwSample < dwNumSamples; dwSample++ )
  289. {
  290. if ( anRawValue[dwSample] > nValMax )
  291. nValMax = anRawValue[dwSample];
  292. if ( anRawValue[dwSample] < nValMin )
  293. nValMin = anRawValue[dwSample];
  294. }
  295. *pnResult = (nValMax - nValMin);
  296. return WBEM_NO_ERROR;
  297. }
  298. WMISTATUS APIENTRY CRawCooker::_Variance( DWORD dwNumSamples,
  299. __int64* anTimeStamp,
  300. __int64* anRawValue,
  301. __int64* anBase,
  302. __int64 nTimeFrequency,
  303. __int64* pnResult)
  304. {
  305. if ( 0 == dwNumSamples || NULL == pnResult)
  306. {
  307. return WBEM_E_FAILED;
  308. };
  309. double SumX_i = 0;
  310. double Average = 0;
  311. for ( DWORD dwSample = 0; dwSample < dwNumSamples; dwSample++ )
  312. {
  313. SumX_i += (anRawValue[dwSample]*anRawValue[dwSample]);
  314. Average += anRawValue[dwSample];
  315. }
  316. double Tmp = (double(SumX_i/dwNumSamples) - (double(Average/dwNumSamples)*double(Average/dwNumSamples)));
  317. *pnResult = __int64(Tmp);
  318. return WBEM_NO_ERROR;
  319. }