home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 39 / IOPROG_39.ISO / SOFT / sdkjava40.exe / data1.cab / fg_Samples / Samples / Profiler / heapmon / clsview.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-04  |  14.3 KB  |  476 lines

  1. // clsview.cpp
  2. //
  3. // Created 10/05/98
  4. //
  5. // (C)Copyright 1998-1999 Microsoft Corporation, All rights reserved.
  6. //
  7.  
  8. #include "pch.hpp"
  9. #pragma hdrstop
  10.  
  11. #include "clsview.hpp"
  12. #include "hpmonmgr.hpp"
  13.  
  14.  
  15. BOOL ClassListViewer::s_fRegisteredClass = FALSE;
  16.  
  17.  
  18. //static
  19. LRESULT CALLBACK ClassListViewer::WndProc (HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
  20. {
  21.     ClassListViewer *clv = (ClassListViewer*)GetWindowLong(wnd, GWL_USERDATA);
  22.     
  23.     switch (msg)
  24.     {
  25.     case WM_SIZE:
  26.         {
  27.             RECT rc;
  28.             GetClientRect(wnd, &rc);
  29.             MoveWindow(clv->m_list, rc.left, rc.top, rc.right, rc.bottom, TRUE);
  30.         }
  31.         break;
  32.  
  33.     case WM_NOTIFY:
  34.         {
  35.             //int idCtrl = (int)wParam; 
  36.             NMHDR *pnmh = (NMHDR*)lParam; 
  37.  
  38.             switch (pnmh->code)
  39.             {
  40.             case LVN_GETDISPINFO:
  41.                 {
  42.                     NMLVDISPINFO *pnmv = (NMLVDISPINFO*)lParam; 
  43.                     LVITEM *pitem  = &pnmv->item;
  44.  
  45.                     if (pitem->mask & LVIF_TEXT)
  46.                     {
  47.                         ClassDataSnapshot *pdata = NULL;
  48.  
  49.                         if (pitem->mask & LVIF_PARAM)
  50.                         {
  51.                             pdata = (ClassDataSnapshot*)pitem->lParam;
  52.                         }
  53.                         else
  54.                         {
  55.                             LVITEM lvi;
  56.                             lvi.mask = LVIF_PARAM;
  57.                             lvi.iItem = pitem->iItem;
  58.                             lvi.iSubItem = 0;
  59.                             if (ListView_GetItem(clv->m_list, &lvi))
  60.                                 pdata = (ClassDataSnapshot*)pitem->lParam;
  61.                         }
  62.                         
  63.                         if (pdata != NULL)
  64.                         {
  65.                             int col = pitem->iSubItem;
  66.                             switch (col)
  67.                             {
  68.                             case CLV_COL_CLASSNAME:
  69.                                 {
  70.                                     PCSTR clsname = clv->m_mgr->FetchIDFriendlyName(pdata->id);
  71.                                     if (clsname != NULL)
  72.                                     {
  73.                                         FitText(pitem->pszText, pitem->cchTextMax, clsname);
  74.                                         return 0;
  75.                                     }
  76.                                 }
  77.                                 break;
  78.                                 
  79.                             case CLV_COL_TOTALINSTANCES:
  80.                                 FormatNumber(pitem->pszText, pitem->cchTextMax, "%I64u", pdata->totalinstances);
  81.                                 return 0;
  82.                                 
  83.                             case CLV_COL_LIVEINSTANCES:
  84.                                 if (pdata->valid)
  85.                                     FormatNumber(pitem->pszText, pitem->cchTextMax, "%u", pdata->liveinstances);
  86.                                 else
  87.                                     FitText(pitem->pszText, pitem->cchTextMax, "<not available>");
  88.                                 return 0;
  89.                                 
  90.                             case CLV_COL_LIVESIZE:
  91.                                 if (pdata->valid)
  92.                                     FormatNumber(pitem->pszText, pitem->cchTextMax, "%u", pdata->livesize);
  93.                                 else
  94.                                     FitText(pitem->pszText, pitem->cchTextMax, "<not available>");
  95.                                 return 0;
  96.  
  97.                             default:
  98.                                 {
  99.                                     col -= CLV_NUM_COLUMNS;
  100.                                     
  101.                                     if (clv->m_mgr->SupportsAllocatedSize())
  102.                                     {
  103.                                         if (col == 0)
  104.                                         {
  105.                                             if (pdata->valid)
  106.                                                 FormatNumber(pitem->pszText, pitem->cchTextMax, "%u", pdata->totalsize);
  107.                                             else
  108.                                                 FitText(pitem->pszText, pitem->cchTextMax, "<not available>");
  109.                                             return 0;
  110.                                         }
  111.  
  112.                                         col--;
  113.                                     }
  114.  
  115.                                     if (clv->m_mgr->SupportsObjectAging())
  116.                                     {
  117.                                         if (col == 0)
  118.                                         {
  119.                                             if (pdata->valid)
  120.                                             {
  121.                                                 if (pdata->liveinstances == 0)
  122.                                                     FitText(pitem->pszText, pitem->cchTextMax, "---");
  123.                                                 else
  124.                                                     FormatNumber(pitem->pszText, pitem->cchTextMax, "%u", pdata->agesum / pdata->liveinstances);
  125.                                             }
  126.                                             else
  127.                                             {
  128.                                                 FitText(pitem->pszText, pitem->cchTextMax, "<not available>");
  129.                                             }
  130.                                             return 0;
  131.                                         }
  132.  
  133.                                         col--;
  134.                                     }
  135.                                 }
  136.                                 break;
  137.                             }
  138.                         }
  139.                     }
  140.                 }
  141.                 break;
  142.  
  143.             case LVN_COLUMNCLICK:
  144.                 {
  145.                     NMLISTVIEW *pnmlv = (NMLISTVIEW*)lParam;
  146.                     if (pnmlv->iSubItem == clv->m_sortcol)
  147.                     {
  148.                         clv->m_sortdir = -clv->m_sortdir;
  149.                     }
  150.                     else
  151.                     {
  152.                         clv->m_sortcol = pnmlv->iSubItem;
  153.                         if (pnmlv->iSubItem == 0)
  154.                             clv->m_sortdir = 1;
  155.                         else
  156.                             clv->m_sortdir = -1;
  157.                     }
  158.  
  159.                     ListView_SortItems(clv->m_list, &SortColumnCB, clv);
  160.  
  161.                     return 0;                    
  162.                 }
  163.                 break;
  164.             }
  165.         }
  166.         break;
  167.  
  168.     case CVWM_SNAPSHOT: {
  169.         int nitems = ListView_GetItemCount(clv->m_list);
  170.         for (int iitem = 0; iitem < nitems; iitem++)
  171.         {
  172.             LVITEM lvi;
  173.             lvi.iItem = iitem;
  174.             lvi.iSubItem = 0;
  175.             lvi.mask = LVIF_PARAM;
  176.             if (ListView_GetItem(clv->m_list, &lvi))
  177.             {
  178.                 ClassDataSnapshot *pdata = (ClassDataSnapshot*)lvi.lParam;
  179.                 ASSERT(pdata);
  180.  
  181.                 clv->UpdateClassData(pdata);
  182.             }
  183.         }
  184.         break; }
  185.     }
  186.  
  187.     return clv->BaseWndProc(wnd, msg, wParam, lParam);
  188. }
  189.  
  190.  
  191. BOOL ClassListViewer::OnCreateWindow ()
  192. {
  193.     BOOL result;
  194.  
  195.     HINSTANCE hinst = m_mgr->GetInstance();
  196.  
  197.     RECT rc;
  198.  
  199.     GetClientRect(m_hwnd, &rc);
  200.  
  201.     result = (m_list = CreateWindow(
  202.             WC_LISTVIEW,
  203.             NULL,
  204.             WS_CHILD | LVS_REPORT,
  205.             rc.left, rc.top, rc.right, rc.bottom,
  206.             m_hwnd,
  207.             NULL,
  208.             hinst,
  209.             NULL)) != NULL;
  210.  
  211.     if (result)
  212.     {
  213.         static PSTR colnames[] = {
  214.                 "Class",
  215.                 "Total instances",
  216.                 "Live instances",
  217.                 "Live size",
  218.         };
  219.  
  220.         unsigned nextracols = 0;
  221.         if (m_mgr->SupportsAllocatedSize())
  222.             nextracols++;
  223.         if (m_mgr->SupportsObjectAging())
  224.             nextracols++;
  225.  
  226.         unsigned ncols = CLV_NUM_COLUMNS + nextracols;
  227.  
  228.         unsigned spaceleft = rc.right - rc.left;
  229.  
  230.         LVCOLUMN lvc;
  231.         lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
  232.         lvc.fmt = LVCFMT_CENTER;
  233.  
  234.         lvc.cx = spaceleft/3;
  235.  
  236.         unsigned i = 0;
  237.         for (;;)
  238.         {
  239.             if (i < CLV_NUM_COLUMNS)
  240.             {
  241.                 lvc.pszText = colnames[i];
  242.             }
  243.             else
  244.             {
  245.                 unsigned extrai = i - CLV_NUM_COLUMNS;
  246.                 if (m_mgr->SupportsAllocatedSize())
  247.                 {
  248.                     if (extrai == 0)
  249.                         lvc.pszText = "total size allocated";
  250.                     extrai--;
  251.                 }
  252.                 if (m_mgr->SupportsObjectAging())
  253.                 {
  254.                     if (extrai == 0)
  255.                         lvc.pszText = "average age";
  256.                     extrai--;
  257.                 }
  258.             }
  259.         
  260.             result = (ListView_InsertColumn(m_list, i, &lvc) != -1);
  261.             if (!result)
  262.                 break;
  263.  
  264.             i++;
  265.             if (i >= ncols)
  266.                 break;
  267.             spaceleft -= lvc.cx;
  268.             lvc.cx = spaceleft / (ncols-i);
  269.         }
  270.     }
  271.  
  272.     if (result)
  273.     {
  274.         m_mgr->IterateIDs(&PopulateListCB, this);
  275.     }
  276.  
  277.     if (result)
  278.     {
  279.         ShowWindow(m_list, SW_SHOWNA);
  280.     }
  281.  
  282.     return result;
  283. }
  284.  
  285.  
  286. //static
  287. int ClassListViewer::PopulateListCB (ID id, PVOID token)
  288. {
  289.     ClassListViewer *clv = (ClassListViewer*)token;
  290.  
  291.     if (id->type == ID_CLASS)
  292.     {
  293.         clv->AddClass((CLASSID)id);
  294.     }
  295.  
  296.     return 1;
  297. }
  298.  
  299.  
  300. BOOL ClassListViewer::AddClass (CLASSID cls)
  301. {
  302.     ASSERT(m_mgr->CanSendUIMessages());
  303.  
  304.     BOOL result = FALSE;
  305.  
  306.     ClassDataSnapshot *pdata = new(ClassDataSnapshot());
  307.     if (pdata)
  308.     {
  309.         ZeroMemory(pdata, sizeof(*pdata));
  310.  
  311.         pdata->id = cls;
  312.  
  313.         UpdateClassData(pdata);
  314.     
  315.         LVITEM lvi;
  316.         lvi.mask = LVIF_PARAM | LVIF_TEXT;
  317.         lvi.lParam = (LPARAM)pdata;
  318.         lvi.pszText = LPSTR_TEXTCALLBACK;
  319.         lvi.iItem = ListView_GetItemCount(m_list);
  320.         lvi.iSubItem = 0;
  321.         result = ListView_InsertItem(m_list, &lvi) != -1;
  322.  
  323.         if (!result)
  324.             delete(pdata);
  325.     }
  326.  
  327.     return result;
  328. }
  329.  
  330.  
  331. VOID ClassListViewer::UpdateClassData (ClassDataSnapshot *pdata)
  332. {
  333.     CLASSID cls = pdata->id;
  334.  
  335.     __int64 totalinstances;
  336.     IJavaEventMonitorIDInfo2 *vminfo = m_mgr->GetVMInfoInterface();
  337.     if (vminfo->ClassInformation(cls->vmid, NULL, NULL, NULL, NULL, &totalinstances) == S_OK)
  338.     {
  339.         if (m_mgr->GetCurrentGCInfo() != NULL)
  340.             ASSERT(totalinstances >= cls->liveinstances);
  341.         pdata->totalinstances = totalinstances;
  342.     }
  343.     vminfo->Release();
  344.  
  345.     if (m_mgr->GetCurrentGCInfo())
  346.         pdata->valid = TRUE;
  347.  
  348.     if (pdata->valid)
  349.     {
  350.         pdata->liveinstances = cls->liveinstances;
  351.         pdata->livesize = cls->livesize;
  352.         pdata->totalsize = cls->totalsize;
  353.         pdata->liveinstances = cls->liveinstances;
  354.         pdata->agesum = cls->agesum;
  355.     }
  356. }
  357.  
  358.  
  359. //static
  360. int CALLBACK ClassListViewer::SortColumnCB (LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  361. {
  362.     ClassListViewer *clv = (ClassListViewer*)lParamSort;
  363.     ClassDataSnapshot *pdata1 = (ClassDataSnapshot*)lParam1;
  364.     ClassDataSnapshot *pdata2 = (ClassDataSnapshot*)lParam2;
  365.  
  366.     int cmp = 0;
  367.  
  368.     unsigned col = clv->m_sortcol;
  369.     switch (col)
  370.     {
  371.     case CLV_COL_CLASSNAME:
  372.         {
  373.             PCSTR clsname1 = clv->m_mgr->FetchIDFriendlyName(pdata1->id);
  374.             PCSTR clsname2 = clv->m_mgr->FetchIDFriendlyName(pdata2->id);
  375.             if (clsname1 != NULL && clsname2 != NULL)
  376.                 cmp = strcmp(clsname1, clsname2);
  377.         }
  378.         break;
  379.         
  380.     case CLV_COL_TOTALINSTANCES:
  381.         __int64 diff;
  382.         diff = pdata1->totalinstances - pdata2->totalinstances;
  383.         if (diff > 0)
  384.             cmp = 1;
  385.         else if (diff == 0)
  386.             cmp = 0;
  387.         else
  388.             cmp = -1;
  389.         break;
  390.         
  391.     case CLV_COL_LIVEINSTANCES:
  392.         if (pdata1->valid && pdata2->valid)
  393.             cmp = pdata1->liveinstances - pdata2->liveinstances;
  394.         break;
  395.         
  396.     case CLV_COL_LIVESIZE:
  397.         if (pdata1->valid && pdata2->valid)
  398.             cmp = pdata1->livesize - pdata2->livesize;
  399.         break;
  400.  
  401.     default:
  402.         col -= CLV_NUM_COLUMNS;
  403.         
  404.         if (clv->m_mgr->SupportsAllocatedSize())
  405.         {
  406.             if (col == 0)
  407.             {
  408.                 if (pdata1->valid && pdata2->valid)
  409.                     cmp = pdata1->totalsize - pdata2->totalsize;
  410.  
  411.                 break;
  412.             }
  413.  
  414.             col--;
  415.         }
  416.  
  417.         if (clv->m_mgr->SupportsObjectAging())
  418.         {
  419.             if (col == 0)
  420.             {
  421.                 if (pdata1->valid && pdata2->valid)
  422.                 {
  423.                     unsigned age1 = 0;
  424.                     unsigned age2 = 0;
  425.                     if (pdata1->liveinstances != 0)
  426.                         age1 = pdata1->agesum / pdata1->liveinstances;
  427.                     if (pdata2->liveinstances != 0)
  428.                         age2 = pdata2->agesum / pdata2->liveinstances;
  429.                     cmp = age1 - age2;
  430.                 }
  431.  
  432.                 break;
  433.             }
  434.  
  435.             col--;
  436.         }
  437.     }
  438.  
  439.     return cmp * clv->m_sortdir;
  440. }
  441.  
  442.  
  443. BOOL ClassListViewer::Initialize (HeapMonitorManager *mgr)
  444. {
  445.     BOOL result = TRUE;
  446.  
  447.     if (!s_fRegisteredClass)
  448.     {
  449.         WNDCLASS wc;
  450.         ZeroMemory(&wc, sizeof(wc));
  451.         wc.lpfnWndProc = &WndProc;
  452.         wc.hInstance = mgr->GetInstance();
  453.         wc.lpszClassName = WC_HEAPMONITOR_CLASSLISTVIEWER;
  454.         wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  455.         wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  456.         result = RegisterClass(&wc);
  457.  
  458.         s_fRegisteredClass = result;
  459.     }
  460.  
  461.     if (result)
  462.     {
  463.         HeapMonitorClientRegistrationInfo reginfo;
  464.         ZeroMemory(®info, sizeof(reginfo));
  465.  
  466.         reginfo.EventMask = HMC_CLASS_EVENTS | HMC_HEAP_EVENTS;
  467.         reginfo.StoppedEventMask = HMC_HEAP_EVENTS;
  468.         reginfo.StoppedInfoMask = HMC_INFO_HEAP_OBJECTS;
  469.  
  470.         result = BaseInitialize(mgr, WC_HEAPMONITOR_CLASSLISTVIEWER, "Per-Class Info", ®info);
  471.     }
  472.  
  473.     return result;
  474. }
  475.  
  476.