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.

490 lines
16 KiB

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. statfuns.c
  5. Abstract:
  6. Statistical calculation functions
  7. --*/
  8. #include <windows.h>
  9. #include <stdlib.h>
  10. #include <math.h>
  11. #include <pdh.h>
  12. #include "pdhicalc.h"
  13. #include "pdhitype.h"
  14. #include "pdhmsg.h"
  15. #define PDHI_FMT_FILTER (PDH_FMT_LONG | PDH_FMT_DOUBLE | PDH_FMT_LARGE)
  16. PDH_STATUS
  17. APIENTRY
  18. PdhiComputeFirstLastStats (
  19. IN PPDHI_COUNTER pCounter,
  20. IN DWORD dwFormat,
  21. IN DWORD dwFirstEntry,
  22. IN DWORD dwNumEntries,
  23. IN PPDH_RAW_COUNTER lpRawValueArray,
  24. IN PPDH_STATISTICS data
  25. )
  26. {
  27. DOUBLE dThisValue = (double)0.0;
  28. DOUBLE dMin = (double)+10E8; // these are just "big" seed numbers
  29. DOUBLE dMax = (double)-10E8;
  30. DOUBLE dMean = (double)0.0;
  31. BOOLEAN bFirstItem = TRUE;
  32. DWORD dwItem;
  33. DWORD dwValidItemCount = 0;
  34. DWORD dwFirstValidItem = 0;
  35. DWORD dwLastValidItem = 0;
  36. DWORD dwComputeFormat;
  37. PPDH_RAW_COUNTER pNewCounter;
  38. PPDH_RAW_COUNTER pOldCounter;
  39. PDH_FMT_COUNTERVALUE fmtValue;
  40. DWORD cStatusReturn;
  41. __try {
  42. // initialize th user's data buffer
  43. data->dwFormat = 0;
  44. data->count = 0;
  45. data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
  46. data->min.largeValue = 0;
  47. data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
  48. data->max.largeValue = 0;
  49. data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
  50. data->mean.largeValue = 0;
  51. // find first valid counter in array
  52. dwItem = dwFirstEntry;
  53. pNewCounter = NULL;
  54. pOldCounter = &lpRawValueArray[dwItem];
  55. do {
  56. // get value of this instance if next counter is valid
  57. if ((pOldCounter->CStatus == PDH_CSTATUS_VALID_DATA) ||
  58. (pOldCounter->CStatus == PDH_CSTATUS_NEW_DATA)) {
  59. pNewCounter = pOldCounter;
  60. dwFirstValidItem = dwItem;
  61. break;
  62. } else {
  63. dwItem = ++dwItem % dwNumEntries;
  64. pOldCounter = &lpRawValueArray[dwItem];
  65. }
  66. } while (dwItem != dwFirstEntry);
  67. // do calculations in Floating point format
  68. dwComputeFormat = dwFormat;
  69. dwComputeFormat &= ~PDHI_FMT_FILTER;
  70. dwComputeFormat |= PDH_FMT_DOUBLE | PDH_FMT_NOCAP100;
  71. // go to next entry to begin processing
  72. dwItem = ++dwItem % dwNumEntries;
  73. pNewCounter = &lpRawValueArray[dwItem];
  74. // these counters need 2 or more entrys to compute values from
  75. if ((dwItem != dwFirstEntry) && (dwNumEntries > 1)) {
  76. // start record found so initialize and continue
  77. dwLastValidItem = dwItem;
  78. // step through the remaining entries
  79. while (dwItem != dwFirstEntry) {
  80. // get value of this instance if next counter is valid
  81. if ((pNewCounter->CStatus == PDH_CSTATUS_VALID_DATA) ||
  82. (pNewCounter->CStatus == PDH_CSTATUS_NEW_DATA)) {
  83. // record this as a valid counter
  84. dwLastValidItem = dwItem;
  85. // get current value
  86. cStatusReturn = PdhiComputeFormattedValue (
  87. pCounter->CalcFunc,
  88. pCounter->plCounterInfo.dwCounterType,
  89. pCounter->lScale,
  90. dwComputeFormat,
  91. pNewCounter,
  92. pOldCounter,
  93. & pCounter->TimeBase,
  94. 0L,
  95. & fmtValue);
  96. if (cStatusReturn == ERROR_SUCCESS) {
  97. dThisValue = fmtValue.doubleValue;
  98. // update min & max
  99. if (bFirstItem) {
  100. dMax = dMin = dThisValue;
  101. bFirstItem = FALSE;
  102. }
  103. else {
  104. if (dThisValue > dMax) dMax = dThisValue;
  105. if (dThisValue < dMin) dMin = dThisValue;
  106. }
  107. dwValidItemCount++;
  108. }
  109. }
  110. pOldCounter = pNewCounter;
  111. dwItem = ++dwItem % dwNumEntries;
  112. pNewCounter = &lpRawValueArray[dwItem];
  113. }
  114. // compute average
  115. if (dwValidItemCount > 0) {
  116. pOldCounter = &lpRawValueArray[dwFirstValidItem];
  117. pNewCounter = &lpRawValueArray[dwLastValidItem];
  118. cStatusReturn = PdhiComputeFormattedValue (
  119. pCounter->CalcFunc,
  120. pCounter->plCounterInfo.dwCounterType,
  121. pCounter->lScale,
  122. dwComputeFormat,
  123. pNewCounter,
  124. pOldCounter,
  125. &pCounter->TimeBase,
  126. 0L,
  127. &fmtValue);
  128. if (cStatusReturn == ERROR_SUCCESS) {
  129. dMean = fmtValue.doubleValue;
  130. cStatusReturn = PDH_CSTATUS_VALID_DATA;
  131. }
  132. else {
  133. dMean = 0.0;
  134. }
  135. } else {
  136. dMean = 0.0;
  137. dMax = 0.0;
  138. dMin = 0.0;
  139. cStatusReturn = PDH_CSTATUS_INVALID_DATA;
  140. }
  141. } else {
  142. // array does not contain a valid counter so exit
  143. dMean = 0.0;
  144. dMax = 0.0;
  145. dMin = 0.0;
  146. cStatusReturn = PDH_CSTATUS_INVALID_DATA;
  147. }
  148. // update user's buffer with new data
  149. data->dwFormat = dwFormat;
  150. data->count = dwValidItemCount;
  151. data->min.CStatus = cStatusReturn;
  152. data->max.CStatus = cStatusReturn;
  153. data->mean.CStatus = cStatusReturn;
  154. switch ((dwFormat & PDHI_FMT_FILTER)) {
  155. case PDH_FMT_LONG:
  156. if (dMin > (DOUBLE) MAXLONG) {
  157. data->min.longValue = MAXLONG;
  158. data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
  159. }
  160. else {
  161. data->min.longValue = (long) dMin;
  162. }
  163. if (dMax > (DOUBLE) MAXLONG) {
  164. data->max.longValue = MAXLONG;
  165. data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
  166. }
  167. else {
  168. data->max.longValue = (long) dMax;
  169. }
  170. if (dMean > (DOUBLE) MAXLONG) {
  171. data->mean.longValue = MAXLONG;
  172. data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
  173. }
  174. else {
  175. data->mean.longValue = (long) dMean;
  176. }
  177. break;
  178. case PDH_FMT_DOUBLE:
  179. data->min.doubleValue = dMin;
  180. data->max.doubleValue = dMax;
  181. data->mean.doubleValue = dMean;
  182. break;
  183. case PDH_FMT_LARGE:
  184. default:
  185. if (dMin > (DOUBLE) MAXLONGLONG) {
  186. data->min.largeValue = MAXLONGLONG;
  187. data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
  188. }
  189. else {
  190. data->min.largeValue = (LONGLONG) dMin;
  191. }
  192. if (dMax > (DOUBLE) MAXLONGLONG) {
  193. data->max.largeValue = MAXLONGLONG;
  194. data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
  195. }
  196. else {
  197. data->max.largeValue = (LONGLONG) dMax;
  198. }
  199. if (dMean > (DOUBLE) MAXLONGLONG) {
  200. data->mean.largeValue = MAXLONGLONG;
  201. data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
  202. }
  203. else {
  204. data->mean.largeValue = (LONGLONG) dMean;
  205. }
  206. break;
  207. }
  208. } __except (EXCEPTION_EXECUTE_HANDLER) {
  209. return PDH_INVALID_ARGUMENT;
  210. }
  211. return ERROR_SUCCESS;
  212. }
  213. PDH_STATUS
  214. APIENTRY
  215. PdhiComputeRawCountStats (
  216. IN PPDHI_COUNTER pCounter,
  217. IN DWORD dwFormat,
  218. IN DWORD dwFirstEntry,
  219. IN DWORD dwNumEntries,
  220. IN PPDH_RAW_COUNTER lpRawValueArray,
  221. IN PPDH_STATISTICS data
  222. )
  223. {
  224. DOUBLE dThisValue = (double)0.0;
  225. DOUBLE dMin = (double)+10E8; // these are just "big" seed numbers
  226. DOUBLE dMax = (double)-10E8;
  227. DOUBLE dMean = (double)0.0;
  228. BOOLEAN bFirstItem = TRUE;
  229. DOUBLE dScale;
  230. DWORD dwItem;
  231. DWORD dwValidItemCount = 0;
  232. DWORD dwFirstValidItem = 0;
  233. DWORD dwLastValidItem = 0;
  234. DWORD dwComputeFormat;
  235. PPDH_RAW_COUNTER pNewCounter;
  236. PPDH_RAW_COUNTER pOldCounter = NULL;
  237. PDH_FMT_COUNTERVALUE fmtValue;
  238. DWORD cStatusReturn;
  239. UNREFERENCED_PARAMETER (dwFirstEntry);
  240. __try {
  241. // initialize the user's data buffer
  242. data->dwFormat = 0;
  243. data->count = 0;
  244. data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
  245. data->min.largeValue = 0;
  246. data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
  247. data->max.largeValue = 0;
  248. data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
  249. data->mean.largeValue = 0;
  250. // find first valid counter in array
  251. dwItem = 0;
  252. pNewCounter = lpRawValueArray;
  253. while (dwItem < dwNumEntries) {
  254. // get value of this instance if next counter is valid
  255. if ((pNewCounter->CStatus == PDH_CSTATUS_VALID_DATA) ||
  256. (pNewCounter->CStatus == PDH_CSTATUS_NEW_DATA)) {
  257. break;
  258. } else {
  259. pOldCounter = pNewCounter;
  260. pNewCounter++;
  261. dwItem++;
  262. }
  263. }
  264. // do calculations in Floating point format
  265. dwComputeFormat = dwFormat;
  266. dwComputeFormat &= ~PDHI_FMT_FILTER;
  267. dwComputeFormat |= PDH_FMT_DOUBLE | PDH_FMT_NOCAP100;
  268. if ((dwItem != dwNumEntries) && (dwNumEntries > 0)) {
  269. // start record found so continue
  270. dwFirstValidItem = dwItem;
  271. // step through the remaining entries
  272. while (dwItem < dwNumEntries) {
  273. // get value of this instance if next counter is valid
  274. if ((pNewCounter->CStatus == PDH_CSTATUS_VALID_DATA) ||
  275. (pNewCounter->CStatus == PDH_CSTATUS_NEW_DATA)) {
  276. dwLastValidItem = dwItem;
  277. cStatusReturn = PdhiComputeFormattedValue (
  278. pCounter->CalcFunc,
  279. pCounter->plCounterInfo.dwCounterType,
  280. pCounter->lScale,
  281. dwComputeFormat,
  282. pNewCounter,
  283. pOldCounter,
  284. & pCounter->TimeBase,
  285. 0L,
  286. & fmtValue);
  287. if (cStatusReturn == ERROR_SUCCESS) {
  288. dThisValue = fmtValue.doubleValue;
  289. if (bFirstItem) {
  290. dMin = dMax = dThisValue;
  291. bFirstItem = FALSE;
  292. }
  293. else {
  294. if (dThisValue > dMax) dMax = dThisValue;
  295. if (dThisValue < dMin) dMin = dThisValue;
  296. }
  297. dMean += dThisValue;
  298. dwValidItemCount ++;
  299. }
  300. }
  301. pOldCounter = pNewCounter;
  302. pNewCounter++;
  303. dwItem++;
  304. }
  305. // compute average
  306. if (dwValidItemCount > 0) {
  307. dMean /= (double)dwValidItemCount;
  308. if (!(dwFormat & PDH_FMT_NOSCALE)) {
  309. //now scale
  310. dScale = pow (10.0, (double)pCounter->lScale);
  311. dMean *= dScale;
  312. dMin *= dScale;
  313. dMax *= dScale;
  314. }
  315. cStatusReturn = PDH_CSTATUS_VALID_DATA;
  316. } else {
  317. dMean = 0.0;
  318. dMax = 0.0;
  319. dMin = 0.0;
  320. cStatusReturn = PDH_CSTATUS_INVALID_DATA;
  321. }
  322. } else {
  323. // array does not contain a valid counter so exit
  324. dMean = 0.0;
  325. dMax = 0.0;
  326. dMin = 0.0;
  327. cStatusReturn = PDH_CSTATUS_INVALID_DATA;
  328. }
  329. // update user's buffer with new data
  330. data->dwFormat = dwFormat;
  331. data->count = dwValidItemCount;
  332. data->min.CStatus = cStatusReturn;
  333. data->max.CStatus = cStatusReturn;
  334. data->mean.CStatus = cStatusReturn;
  335. switch ((dwFormat & PDHI_FMT_FILTER)) {
  336. case PDH_FMT_LONG:
  337. if (dMin > (DOUBLE) MAXLONG) {
  338. data->min.longValue = MAXLONG;
  339. data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
  340. }
  341. else {
  342. data->min.longValue = (long) dMin;
  343. }
  344. if (dMax > (DOUBLE) MAXLONG) {
  345. data->max.longValue = MAXLONG;
  346. data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
  347. }
  348. else {
  349. data->max.longValue = (long) dMax;
  350. }
  351. if (dMean > (DOUBLE) MAXLONG) {
  352. data->mean.longValue = MAXLONG;
  353. data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
  354. }
  355. else {
  356. data->mean.longValue = (long) dMean;
  357. }
  358. break;
  359. case PDH_FMT_DOUBLE:
  360. data->min.doubleValue = dMin;
  361. data->max.doubleValue = dMax;
  362. data->mean.doubleValue = dMean;
  363. break;
  364. case PDH_FMT_LARGE:
  365. default:
  366. if (dMin > (DOUBLE) MAXLONGLONG) {
  367. data->min.largeValue = MAXLONGLONG;
  368. data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
  369. }
  370. else {
  371. data->min.largeValue = (LONGLONG) dMin;
  372. }
  373. if (dMax > (DOUBLE) MAXLONGLONG) {
  374. data->max.largeValue = MAXLONGLONG;
  375. data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
  376. }
  377. else {
  378. data->max.largeValue = (LONGLONG) dMax;
  379. }
  380. if (dMean > (DOUBLE) MAXLONGLONG) {
  381. data->mean.largeValue = MAXLONGLONG;
  382. data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
  383. }
  384. else {
  385. data->mean.largeValue = (LONGLONG) dMean;
  386. }
  387. break;
  388. }
  389. } __except (EXCEPTION_EXECUTE_HANDLER) {
  390. return PDH_INVALID_ARGUMENT;
  391. }
  392. return ERROR_SUCCESS;
  393. }
  394. PDH_STATUS
  395. APIENTRY
  396. PdhiComputeNoDataStats (
  397. IN PPDHI_COUNTER pCounter,
  398. IN DWORD dwFormat,
  399. IN DWORD dwFirstEntry,
  400. IN DWORD dwNumEntries,
  401. IN PPDH_RAW_COUNTER lpRawValueArray,
  402. IN PPDH_STATISTICS data
  403. )
  404. {
  405. UNREFERENCED_PARAMETER (pCounter);
  406. UNREFERENCED_PARAMETER (dwFirstEntry);
  407. UNREFERENCED_PARAMETER (dwNumEntries);
  408. UNREFERENCED_PARAMETER (lpRawValueArray);
  409. __try {
  410. data->dwFormat = dwFormat;
  411. data->count = 0;
  412. data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
  413. data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
  414. data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
  415. switch ((dwFormat & PDHI_FMT_FILTER)) {
  416. case PDH_FMT_LONG:
  417. data->min.doubleValue = 0;
  418. data->max.longValue = 0;
  419. data->mean.longValue = 0;
  420. break;
  421. case PDH_FMT_DOUBLE:
  422. data->min.doubleValue = (double)0;
  423. data->max.doubleValue = (double)0;
  424. data->mean.doubleValue = (double)0.0;
  425. break;
  426. case PDH_FMT_LARGE:
  427. default:
  428. data->min.largeValue = 0;
  429. data->max.largeValue = 0;
  430. data->mean.largeValue = 0;
  431. break;
  432. }
  433. } __except (EXCEPTION_EXECUTE_HANDLER) {
  434. return PDH_INVALID_ARGUMENT;
  435. }
  436. return ERROR_SUCCESS;
  437. }