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.

702 lines
17 KiB

  1. /*****************************************************************************
  2. *
  3. * Grafdata.c - This module handles the non-drawing functions of the graph,
  4. * such as allocating linked structures and their memory, freeing it,
  5. * unlinking, starting and stopping the timer,
  6. * setting up the first graph (CPU), and all the numeric functions for
  7. * the different counter types.
  8. *
  9. * Microsoft Confidential
  10. * Copyright (c) 1992-1993 Microsoft Corporation
  11. *
  12. *
  13. ****************************************************************************/
  14. //==========================================================================//
  15. // Includes //
  16. //==========================================================================//
  17. #include <stdio.h> // for sprintf
  18. #include "setedit.h" // main perfmon declarations
  19. #include "grafdata.h" // external declarations for this file
  20. #include <float.h> // for FLT_MAX constant
  21. #include "addline.h" // for AddLine, EditLine
  22. #include "counters.h" // for Counter_Counter, et al.
  23. #include "graph.h" // for SizeGraphComponents
  24. #include "pmemory.h" // for MemoryXXX (mallloc-type) routines
  25. #include "perfdata.h" // for UpdateLines
  26. #include "legend.h"
  27. #include "system.h" // for SystemGet
  28. #include "utils.h"
  29. #include "line.h" // for LineFree
  30. // #include "valuebar.h" // for StatusTimer
  31. #include "fileopen.h" // for FileGetName
  32. #include "fileutil.h" // for FileRead...
  33. #include "menuids.h" // for IDM_VIEWCHART
  34. #include "perfmops.h" // for ExportFileHeader
  35. #include "status.h" // for StatusLineReady
  36. extern BOOL SaveFileHandler(HWND hWnd,DWORD type) ;
  37. // this macro is used in doing a simple DDA (Digital Differential Analyzer)
  38. // * 10 + 5 is to make the result round up with .5
  39. #define DDA_DISTRIBUTE(TotalTics, numOfData) \
  40. ((TotalTics * 10 / numOfData) + 5) / 10
  41. #define szSmallValueFormat TEXT("%10.3f")
  42. #define szLargeValueFormat TEXT("%10.0f")
  43. //==========================================================================//
  44. // Local Data //
  45. //==========================================================================//
  46. //==========================================================================//
  47. // Local Functions //
  48. //==========================================================================//
  49. /****************************************************************************
  50. * eUpdateMinMaxAve -
  51. ****************************************************************************/
  52. void eUpdateMinMaxAve (FLOAT eValue, PLINESTRUCT pLineStruct, INT iValidValues,
  53. INT iTotalValidPoints, INT iDataPoint, INT gMaxPoints)
  54. {
  55. INT i ;
  56. INT iDataNum = iTotalValidPoints ;
  57. FLOAT eMin,
  58. eMax,
  59. eSum,
  60. eNewValue ;
  61. eMax = eMin = eValue ;
  62. eSum = eValue ;
  63. if (iValidValues == iTotalValidPoints)
  64. {
  65. for (i=0 ; i < iValidValues ; i++)
  66. {
  67. if (i == iDataPoint)
  68. {
  69. // skip the data point we are going to replace
  70. continue ;
  71. }
  72. eNewValue = pLineStruct->lnValues[i] ;
  73. eSum += eNewValue ;
  74. if (eNewValue > eMax)
  75. {
  76. eMax = eNewValue ;
  77. }
  78. if (eNewValue < eMin)
  79. {
  80. eMin = eNewValue ;
  81. }
  82. }
  83. }
  84. else
  85. {
  86. // special case when we start the new line in the middle of the chart
  87. for (i = iDataPoint, iTotalValidPoints-- ;
  88. iTotalValidPoints > 0 ;
  89. iTotalValidPoints-- )
  90. {
  91. i-- ;
  92. if (i < 0)
  93. {
  94. // for the wrap-around case..
  95. i = gMaxPoints - 1 ;
  96. }
  97. if (i == iDataPoint)
  98. {
  99. // skip the data point we are going to replace
  100. continue ;
  101. }
  102. eNewValue = pLineStruct->lnValues[i] ;
  103. eSum += eNewValue ;
  104. if (eNewValue > eMax)
  105. {
  106. eMax = eNewValue ;
  107. }
  108. if (eNewValue < eMin)
  109. {
  110. eMin = eNewValue ;
  111. }
  112. }
  113. }
  114. pLineStruct->lnMinValue = eMin ;
  115. pLineStruct->lnMaxValue = eMax ;
  116. if (iDataNum)
  117. {
  118. pLineStruct->lnAveValue = eSum / (FLOAT) iDataNum ;
  119. }
  120. else
  121. {
  122. pLineStruct->lnAveValue = (FLOAT) 0.0 ;
  123. }
  124. }
  125. BOOL HandleGraphTimer (void)
  126. {
  127. return(TRUE);
  128. }
  129. VOID GetGraphConfig(PGRAPHSTRUCT pGraph)
  130. {
  131. LoadRefreshSettings(pGraph);
  132. LoadLineGraphSettings(pGraph);
  133. // Init the structure
  134. pGraph->pLineFirst = NULL;
  135. //NOTE: put the rest of this in Config
  136. pGraph->gOptions.bLegendChecked = TRUE;
  137. pGraph->gOptions.bMenuChecked = TRUE;
  138. pGraph->gOptions.bLabelsChecked = TRUE;
  139. pGraph->gOptions.bVertGridChecked = FALSE;
  140. pGraph->gOptions.bHorzGridChecked = FALSE;
  141. pGraph->gOptions.bStatusBarChecked = TRUE;
  142. pGraph->gOptions.GraphVGrid = TRUE;
  143. pGraph->gOptions.GraphHGrid = TRUE;
  144. pGraph->gOptions.HistVGrid = TRUE;
  145. pGraph->gOptions.HistHGrid = TRUE;
  146. pGraph->gOptions.iGraphOrHistogram = LINE_GRAPH; // vs. BAR_GRAPH
  147. pGraph->gOptions.iVertMax = DEF_GRAPH_VMAX;
  148. return;
  149. }
  150. BOOL InsertGraph (HWND hWnd)
  151. {
  152. PGRAPHSTRUCT pGraph;
  153. pGraph = MemoryAllocate (sizeof (GRAPHSTRUCT)) ;
  154. if (!pGraph)
  155. return (FALSE) ;
  156. pGraphs = pGraph;
  157. GetGraphConfig(pGraph);
  158. pGraph->bManualRefresh = FALSE ;
  159. pGraph->gMaxValues = DEFAULT_MAX_VALUES;
  160. pGraph->pptDataPoints = NULL ;
  161. pGraph->pDataTime = NULL ;
  162. pGraph->hWnd = hWnd ;
  163. pGraph->bModified = TRUE ; // creating a graph means it's been modified
  164. pGraph->Visual.iColorIndex = 0 ;
  165. pGraph->Visual.iWidthIndex = 0 ;
  166. pGraph->Visual.iStyleIndex = 0 ;
  167. return(TRUE) ;
  168. }
  169. BOOL ChartInsertLine (PGRAPHSTRUCT pGraph,
  170. PLINE pLine)
  171. /*
  172. Effect: Insert the line pLine into the graph pGraph and
  173. allocate space for the graph's number of values.
  174. Returns: Whether the line could be added and space allocated.
  175. See Also: LineAllocate (line.c), ChartDeleteLine.
  176. */
  177. { // ChartInsertLine
  178. PLINE pLineEquivalent ;
  179. INT i ;
  180. FLOAT *pTempPts;
  181. HPEN tempPen ;
  182. pGraph->bModified = TRUE ;
  183. pLineEquivalent = FindEquivalentLine (pLine, pGraph->pLineFirst) ;
  184. if (pLineEquivalent)
  185. {
  186. if (bMonitorDuplicateInstances) {
  187. pLine->dwInstanceIndex = pLineEquivalent->dwInstanceIndex + 1;
  188. } else {
  189. pLineEquivalent->Visual = pLine->Visual ;
  190. pLineEquivalent->iScaleIndex = pLine->iScaleIndex ;
  191. pLineEquivalent->eScale = pLine->eScale ;
  192. tempPen = pLineEquivalent->hPen ;
  193. pLineEquivalent->hPen = pLine->hPen ;
  194. pLine->hPen = tempPen ;
  195. return FALSE ;
  196. }
  197. }
  198. LineAppend (&pGraph->pLineFirst, pLine) ;
  199. // Add the line to the legend, resize the legend window, and then
  200. // select the new line as the current legend item. Do it in this
  201. // sequence to avoid the legend scroll bar momentarily appearing and
  202. // then disappearing, since the resize will obviate the scroll bar.
  203. LegendAddItem (hWndGraphLegend, pLine) ;
  204. if (!bDelayAddAction)
  205. {
  206. SizeGraphComponents (hWndGraph) ;
  207. LegendSetSelection (hWndGraphLegend,
  208. LegendNumItems (hWndGraphLegend) - 1) ;
  209. }
  210. return (TRUE) ;
  211. } // ChartInsertLine
  212. VOID ChartDeleteLine (PGRAPHSTRUCT pGraph,
  213. PLINESTRUCT pLine)
  214. {
  215. PLINESTRUCT npLine;
  216. pGraph->bModified = TRUE ;
  217. if (pGraph->pLineFirst == pLine)
  218. pGraph->pLineFirst = pLine->pLineNext;
  219. else
  220. {
  221. for (npLine = pGraph->pLineFirst; npLine; npLine = npLine->pLineNext)
  222. {
  223. if (npLine->pLineNext == pLine)
  224. npLine->pLineNext = pLine->pLineNext;
  225. }
  226. }
  227. if (!pGraph->pLineFirst)
  228. {
  229. ResetGraph (pGraph) ;
  230. }
  231. else
  232. {
  233. // BuildNewValueListForGraph () ;
  234. }
  235. // Delete the legend entry for this line.
  236. // If the line was highlighted then this will undo the highlight.
  237. LegendDeleteItem (hWndGraphLegend, pLine) ;
  238. LineFree (pLine) ;
  239. SizeGraphComponents (hWndGraph) ;
  240. }
  241. FLOAT Counter_Queuelen(PLINESTRUCT pLine)
  242. {
  243. return((FLOAT)0.0);
  244. // pLine;
  245. }
  246. void ClearGraphDisplay (PGRAPHSTRUCT pGraph)
  247. {
  248. PLINESTRUCT pLine;
  249. // reset the timeline data
  250. // pGraph->gKnownValue = -1 ;
  251. // pGraph->gTimeLine.iValidValues = 0 ;
  252. // pGraph->gTimeLine.xLastTime = 0 ;
  253. // memset (pGraph->pDataTime, 0, sizeof(SYSTEMTIME) * pGraph->gMaxValues) ;
  254. // loop through lines,
  255. // If one of the lines is highlighted then do the calculations
  256. // for average, min, & max on that line.
  257. // for (pLine=pGraph->pLineFirst; pLine; pLine=pLine->pLineNext)
  258. // { // for
  259. // pLine->bFirstTime = 2 ;
  260. // pLine->lnMinValue = FLT_MAX ;
  261. // pLine->lnMaxValue = - FLT_MAX ;
  262. // pLine->lnAveValue = 0.0F ;
  263. // pLine->lnValidValues = 0 ;
  264. // memset (pLine->lnValues, 0, sizeof(FLOAT) * pGraph->gMaxValues) ;
  265. // }
  266. // StatusTimer (hWndGraphStatus, TRUE) ;
  267. }
  268. void ResetGraphView (HWND hWndGraph)
  269. {
  270. PGRAPHSTRUCT pGraph ;
  271. pGraph = GraphData (hWndGraph) ;
  272. if (!pGraph)
  273. {
  274. return ;
  275. }
  276. ChangeSaveFileName (NULL, IDM_VIEWCHART) ;
  277. if (pGraph->pSystemFirst)
  278. {
  279. ResetGraph (pGraph) ;
  280. }
  281. } // ResetGraphView
  282. void ResetGraph (PGRAPHSTRUCT pGraph)
  283. {
  284. ClearLegend (hWndGraphLegend) ;
  285. if (pGraph->pLineFirst)
  286. {
  287. FreeLines (pGraph->pLineFirst) ;
  288. pGraph->pLineFirst = NULL ;
  289. }
  290. if (pGraph->pSystemFirst)
  291. {
  292. FreeSystems (pGraph->pSystemFirst) ;
  293. pGraph->pSystemFirst = NULL ;
  294. }
  295. pGraph->gKnownValue = -1 ;
  296. pGraph->gTimeLine.iValidValues = 0 ;
  297. pGraph->gTimeLine.xLastTime = 0 ;
  298. // reset visual data
  299. pGraph->Visual.iColorIndex = 0 ;
  300. pGraph->Visual.iWidthIndex = 0 ;
  301. pGraph->Visual.iStyleIndex = 0 ;
  302. // memset (pGraph->pDataTime, 0, sizeof(SYSTEMTIME) * pGraph->gMaxValues) ;
  303. SizeGraphComponents (hWndGraph) ;
  304. InvalidateRect(hWndGraph, NULL, TRUE) ;
  305. }
  306. BOOL AddChart (HWND hWndParent)
  307. {
  308. PLINE pCurrentLine = CurrentGraphLine (hWndGraph) ;
  309. return (AddLine (hWndParent,
  310. &(pGraphs->pSystemFirst),
  311. &(pGraphs->Visual),
  312. pCurrentLine ? pCurrentLine->lnSystemName : NULL,
  313. LineTypeChart)) ;
  314. }
  315. BOOL EditChart (HWND hWndParent)
  316. { // EditChart
  317. return (EditLine (hWndParent,
  318. &(pGraphs->pSystemFirst),
  319. CurrentGraphLine (hWndGraph),
  320. LineTypeChart)) ;
  321. }
  322. BOOL QuerySaveChart (HWND hWndParent, PGRAPHSTRUCT pGraph)
  323. /*
  324. Effect: If the graph pGraph is modified, put up a message
  325. box allowing the user to save the current graph.
  326. Return whether the caller should proceed to load in
  327. a new or otherwise trash the current graph.
  328. */
  329. { // QuerySaveChart
  330. #ifdef KEEP_QUERY
  331. int iReturn ;
  332. if (!pGraph->bModified)
  333. return (TRUE) ;
  334. iReturn = MessageBoxResource (hWndParent,
  335. IDS_SAVECHART, IDS_MODIFIEDCHART,
  336. MB_YESNOCANCEL | MB_ICONASTERISK) ;
  337. if (iReturn == IDCANCEL)
  338. return (FALSE) ;
  339. if (iReturn == IDYES)
  340. SaveChart (hWndGraph, 0, 0) ;
  341. return (TRUE) ;
  342. #endif
  343. return (TRUE) ; // we don't want to query nor save change
  344. } // QuerySaveChart
  345. void GraphAddAction ()
  346. {
  347. PGRAPHSTRUCT pGraph ;
  348. pGraph = GraphData (hWndGraph) ;
  349. SizeGraphComponents (hWndGraph) ;
  350. LegendSetSelection (hWndGraphLegend,
  351. LegendNumItems (hWndGraphLegend) - 1) ;
  352. }
  353. BOOL OpenChartVer1 (HANDLE hFile,
  354. DISKCHART *pDiskChart,
  355. PGRAPHSTRUCT pGraph)
  356. { // OpenChartVer1
  357. bDelayAddAction = TRUE ;
  358. pGraph->Visual = pDiskChart->Visual ;
  359. pGraph->gOptions = pDiskChart->gOptions ;
  360. pGraph->gMaxValues = pDiskChart->gMaxValues ;
  361. pGraph->bManualRefresh = pDiskChart->bManualRefresh ;
  362. pGraphs->gInterval = (INT) (pGraph->gOptions.eTimeInterval * (FLOAT) 1000.0) ;
  363. ReadLines (hFile, pDiskChart->dwNumLines,
  364. &(pGraph->pSystemFirst), &(pGraph->pLineFirst), IDM_VIEWCHART) ;
  365. bDelayAddAction = FALSE ;
  366. GraphAddAction () ;
  367. return (TRUE) ;
  368. } // OpenChartVer1
  369. BOOL OpenChart (HWND hWndGraph,
  370. HANDLE hFile,
  371. DWORD dwMajorVersion,
  372. DWORD dwMinorVersion,
  373. BOOL bChartFile)
  374. { // OpenChart
  375. PGRAPHSTRUCT pGraph ;
  376. DISKCHART DiskChart ;
  377. BOOL bSuccess = TRUE ;
  378. pGraph = pGraphs ;
  379. if (!pGraph)
  380. {
  381. bSuccess = FALSE ;
  382. goto Exit0 ;
  383. }
  384. if (!FileRead (hFile, &DiskChart, sizeof (DISKCHART)))
  385. {
  386. bSuccess = FALSE ;
  387. goto Exit0 ;
  388. }
  389. switch (dwMajorVersion)
  390. {
  391. case (1):
  392. SetHourglassCursor() ;
  393. ResetGraphView (hWndGraph) ;
  394. OpenChartVer1 (hFile, &DiskChart, pGraph) ;
  395. // change to chart view if we are opening a
  396. // chart file
  397. if (bChartFile && iPerfmonView != IDM_VIEWCHART)
  398. {
  399. SendMessage (hWndMain, WM_COMMAND, (LONG)IDM_VIEWCHART, 0L) ;
  400. }
  401. if (iPerfmonView == IDM_VIEWCHART)
  402. {
  403. SetPerfmonOptions (&DiskChart.perfmonOptions) ;
  404. }
  405. SetArrowCursor() ;
  406. break ;
  407. } // switch
  408. Exit0:
  409. if (bChartFile)
  410. {
  411. CloseHandle (hFile) ;
  412. }
  413. return (bSuccess) ;
  414. } // OpenChart
  415. BOOL SaveChart (HWND hWndGraph, HANDLE hInputFile, BOOL bGetFileName)
  416. {
  417. PGRAPHSTRUCT pGraph ;
  418. PLINE pLine ;
  419. HANDLE hFile ;
  420. DISKCHART DiskChart ;
  421. PERFFILEHEADER FileHeader ;
  422. TCHAR szFileName [256] ;
  423. BOOL newFileName = FALSE ;
  424. if (hInputFile)
  425. {
  426. // use the input file handle if it is available
  427. // this is the case for saving workspace data
  428. hFile = hInputFile ;
  429. }
  430. else
  431. {
  432. if (pChartFullFileName)
  433. {
  434. lstrcpy (szFileName, pChartFullFileName) ;
  435. }
  436. if (bGetFileName || pChartFullFileName == NULL)
  437. {
  438. // if (!pChartFullFileName)
  439. // {
  440. // StringLoad (IDS_GRAPH_FNAME, szFileName) ;
  441. // }
  442. if (!FileGetName (hWndGraph, IDS_CHARTFILE, szFileName))
  443. {
  444. return (FALSE) ;
  445. }
  446. newFileName = TRUE ;
  447. }
  448. hFile = FileHandleCreate (szFileName) ;
  449. if (hFile && hFile != INVALID_HANDLE_VALUE && newFileName)
  450. {
  451. ChangeSaveFileName (szFileName, IDM_VIEWCHART) ;
  452. }
  453. else if (!hFile || hFile == INVALID_HANDLE_VALUE)
  454. {
  455. DlgErrorBox (hWndGraph, ERR_CANT_OPEN, szFileName) ;
  456. }
  457. }
  458. if (!hFile || hFile == INVALID_HANDLE_VALUE)
  459. return (FALSE) ;
  460. pGraph = pGraphs ;
  461. if (!pGraph)
  462. {
  463. if (!hInputFile || hInputFile == INVALID_HANDLE_VALUE)
  464. {
  465. CloseHandle (hFile) ;
  466. }
  467. return (FALSE) ;
  468. }
  469. if (!hInputFile || hInputFile == INVALID_HANDLE_VALUE)
  470. {
  471. // only need to write file header if not workspace
  472. memset (&FileHeader, 0, sizeof (FileHeader)) ;
  473. lstrcpy (FileHeader.szSignature, szPerfChartSignature) ;
  474. FileHeader.dwMajorVersion = ChartMajorVersion ;
  475. FileHeader.dwMinorVersion = ChartMinorVersion ;
  476. if (!FileWrite (hFile, &FileHeader, sizeof (PERFFILEHEADER)))
  477. {
  478. goto Exit0 ;
  479. }
  480. }
  481. DiskChart.Visual = pGraph->Visual ;
  482. DiskChart.gOptions = pGraph->gOptions ;
  483. DiskChart.gMaxValues = pGraph->gMaxValues ;
  484. DiskChart.dwNumLines = NumLines (pGraph->pLineFirst) ;
  485. DiskChart.bManualRefresh = pGraph->bManualRefresh ;
  486. DiskChart.perfmonOptions = Options ;
  487. if (!FileWrite (hFile, &DiskChart, sizeof (DISKCHART)))
  488. {
  489. goto Exit0 ;
  490. }
  491. for (pLine = pGraph->pLineFirst ;
  492. pLine ;
  493. pLine = pLine->pLineNext)
  494. { // for
  495. if (!WriteLine (pLine, hFile))
  496. {
  497. goto Exit0 ;
  498. }
  499. } // for
  500. if (!hInputFile || hInputFile == INVALID_HANDLE_VALUE)
  501. {
  502. CloseHandle (hFile) ;
  503. }
  504. return (TRUE) ;
  505. Exit0:
  506. if (!hInputFile || hInputFile == INVALID_HANDLE_VALUE)
  507. {
  508. CloseHandle (hFile) ;
  509. // only need to report error if not workspace
  510. DlgErrorBox (hWndGraph, ERR_SETTING_FILE, szFileName) ;
  511. }
  512. return (FALSE) ;
  513. } // SaveChart
  514. #define TIME_TO_WRITE 6
  515. typedef struct CHARTDATAPOINTSTRUCT
  516. {
  517. int iLogIndex ;
  518. int xDispDataPoint ;
  519. } CHARTDATAPOINT, *PCHARTDATAPOINT ;
  520. BOOL ToggleGraphRefresh (HWND hWnd)
  521. { // ToggleGraphRefresh
  522. PGRAPHSTRUCT pGraph ;
  523. pGraph = GraphData (hWnd) ;
  524. pGraph->bManualRefresh = !pGraph->bManualRefresh ;
  525. return (pGraph->bManualRefresh) ;
  526. } // ToggleGraphRefresh
  527. BOOL GraphRefresh (HWND hWnd)
  528. { // GraphRefresh
  529. PGRAPHSTRUCT pGraph ;
  530. pGraph = GraphData (hWnd) ;
  531. return (pGraph->bManualRefresh) ;
  532. } // GraphRefresh