< prev index next >

application/org.openjdk.jmc.flightrecorder.ui/src/main/java/org/openjdk/jmc/flightrecorder/ui/pages/ClassLoadingPage.java

Print this page




  15  * and the following disclaimer.
  16  * 
  17  * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
  18  * conditions and the following disclaimer in the documentation and/or other materials provided with
  19  * the distribution.
  20  * 
  21  * 3. Neither the name of the copyright holder nor the names of its contributors may be used to
  22  * endorse or promote products derived from this software without specific prior written permission.
  23  * 
  24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  26  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  27  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
  31  * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32  */
  33 package org.openjdk.jmc.flightrecorder.ui.pages;
  34 



  35 import java.util.ArrayList;


  36 import java.util.LinkedHashMap;
  37 import java.util.List;
  38 import java.util.Map;

  39 import java.util.stream.Collectors;
  40 import java.util.stream.Stream;
  41 
  42 import org.eclipse.jface.action.IAction;
  43 import org.eclipse.jface.resource.ImageDescriptor;
  44 import org.eclipse.swt.SWT;
  45 import org.eclipse.swt.custom.CTabFolder;
  46 import org.eclipse.swt.custom.SashForm;
  47 import org.eclipse.swt.layout.GridData;
  48 import org.eclipse.swt.layout.GridLayout;
  49 import org.eclipse.swt.widgets.Composite;
  50 import org.eclipse.swt.widgets.Control;
  51 import org.eclipse.ui.forms.widgets.Form;
  52 import org.eclipse.ui.forms.widgets.FormToolkit;
  53 
  54 import org.openjdk.jmc.common.IState;
  55 import org.openjdk.jmc.common.IWritableState;
  56 import org.openjdk.jmc.common.item.Aggregators;

  57 import org.openjdk.jmc.common.item.IAttribute;
  58 import org.openjdk.jmc.common.item.IItemCollection;
  59 import org.openjdk.jmc.common.item.IItemFilter;
  60 import org.openjdk.jmc.common.item.ItemFilters;
  61 import org.openjdk.jmc.common.item.RangeMatchPolicy;
  62 import org.openjdk.jmc.common.unit.IQuantity;
  63 import org.openjdk.jmc.common.unit.IRange;
  64 import org.openjdk.jmc.common.unit.UnitLookup;
  65 import org.openjdk.jmc.flightrecorder.JfrAttributes;
  66 import org.openjdk.jmc.flightrecorder.jdk.JdkAttributes;
  67 import org.openjdk.jmc.flightrecorder.jdk.JdkFilters;
  68 import org.openjdk.jmc.flightrecorder.jdk.JdkQueries;
  69 import org.openjdk.jmc.flightrecorder.jdk.JdkTypeIDs;
  70 import org.openjdk.jmc.flightrecorder.rules.util.JfrRuleTopics;
  71 import org.openjdk.jmc.flightrecorder.ui.FlightRecorderUI;
  72 import org.openjdk.jmc.flightrecorder.ui.IDataPageFactory;
  73 import org.openjdk.jmc.flightrecorder.ui.IDisplayablePage;
  74 import org.openjdk.jmc.flightrecorder.ui.IPageContainer;
  75 import org.openjdk.jmc.flightrecorder.ui.IPageDefinition;
  76 import org.openjdk.jmc.flightrecorder.ui.IPageUI;


 114                 public ImageDescriptor getImageDescriptor(IState state) {
 115                         return FlightRecorderUI.getDefault().getMCImageDescriptor(ImageConstants.PAGE_CLASSLOADING);
 116                 }
 117 
 118                 @Override
 119                 public String[] getTopics(IState state) {
 120                         return new String[] {JfrRuleTopics.CLASS_LOADING_TOPIC};
 121                 }
 122 
 123                 @Override
 124                 public IDisplayablePage createPage(IPageDefinition dpd, StreamModel items, IPageContainer editor) {
 125                         return new ClassLoadingPage(dpd, items, editor);
 126                 }
 127         }
 128 
 129         private static final IItemFilter TABLE_FILTER = ItemFilters.or(JdkQueries.CLASS_LOAD.getFilter(),
 130                         JdkQueries.CLASS_UNLOAD.getFilter());
 131         private static final ItemHistogramBuilder CLASSLOADER_HISTOGRAM = new ItemHistogramBuilder();
 132         private static final ItemListBuilder CLASS_LOADING_LIST = new ItemListBuilder();
 133         private static final ItemListBuilder CLASS_UNLOADING_LIST = new ItemListBuilder();


 134         private static final Map<String, Boolean> LEGEND_ITEMS = new LinkedHashMap<>();
 135         private static final String LOADED_COUNT = "loadedCount"; //$NON-NLS-1$
 136         private static final String UNLOADED_COUNT = "unloadedCount"; //$NON-NLS-1$
 137         private static final String CLASS_LOAD = "classLoad"; //$NON-NLS-1$
 138         private static final String CLASS_UNLOAD = "classUnload"; //$NON-NLS-1$
 139 
 140         static {
 141                 CLASSLOADER_HISTOGRAM.addColumn(LOADED_COUNT,
 142                                 Aggregators.count(Messages.ClassLoadingPage_AGGR_CLASSES_LOADED_BY_CLASSLOADER,
 143                                                 Messages.ClassLoadingPage_AGGR_CLASSES_LOADED_BY_CLASSLOADER_DESC,
 144                                                 ItemFilters.type(JdkTypeIDs.CLASS_LOAD)));
 145                 CLASSLOADER_HISTOGRAM.addColumn(UNLOADED_COUNT,
 146                                 Aggregators.count(Messages.ClassLoadingPage_AGGR_CLASSES_UNLOADED_BY_CLASSLOADER,
 147                                                 Messages.ClassLoadingPage_AGGR_CLASSES_UNLOADED_BY_CLASSLOADER_DESC,
 148                                                 ItemFilters.type(JdkTypeIDs.CLASS_UNLOAD)));
 149 
 150                 CLASS_LOADING_LIST.addColumn(JdkAttributes.CLASS_LOADED);
 151                 CLASS_LOADING_LIST.addColumn(JdkAttributes.CLASS_DEFINING_CLASSLOADER);
 152                 CLASS_LOADING_LIST.addColumn(JdkAttributes.CLASS_INITIATING_CLASSLOADER);
 153                 CLASS_LOADING_LIST.addColumn(JfrAttributes.START_TIME);
 154                 CLASS_LOADING_LIST.addColumn(JfrAttributes.DURATION);
 155                 CLASS_LOADING_LIST.addColumn(JfrAttributes.END_TIME);
 156                 CLASS_LOADING_LIST.addColumn(JfrAttributes.EVENT_THREAD);

 157                 CLASS_UNLOADING_LIST.addColumn(JfrAttributes.EVENT_TIMESTAMP);
 158                 CLASS_UNLOADING_LIST.addColumn(JfrAttributes.EVENT_THREAD);
 159                 CLASS_UNLOADING_LIST.addColumn(JdkAttributes.CLASS_UNLOADED);
 160                 CLASS_UNLOADING_LIST.addColumn(JdkAttributes.CLASS_DEFINING_CLASSLOADER);
 161 















 162                 // FIXME: Need to make a label provider for this
 163                 // FIXME: Want to have this in the same order
 164 
 165                 LEGEND_ITEMS.put(JdkAttributes.CLASSLOADER_LOADED_COUNT.getIdentifier(), Boolean.TRUE);
 166                 LEGEND_ITEMS.put(JdkAttributes.CLASSLOADER_UNLOADED_COUNT.getIdentifier(), Boolean.FALSE);
 167                 LEGEND_ITEMS.put(CLASS_LOAD, Boolean.TRUE);
 168                 LEGEND_ITEMS.put(CLASS_UNLOAD, Boolean.FALSE);
 169         }
 170 
 171         private class ClassLoadingUi implements IPageUI {
 172 
 173                 private final ChartCanvas classLoadingChart;
 174                 private final ItemList classLoadingTable;
 175                 private final ItemList classUnloadingTable;


 176                 private FilterComponent classLoadingFilter;
 177                 private FilterComponent classUnloadingFilter;


 178                 private final SashForm sash;
 179                 private final IPageContainer pageContainer;
 180                 private IItemCollection selectionItems;
 181                 private ItemHistogram classloaderHistogram;
 182                 private FilterComponent classloaderHistogramFilter;
 183                 private final IAction classLoadAction = DataPageToolkit.createTypeCheckAction(CLASS_LOAD, JdkTypeIDs.CLASS_LOAD,
 184                                 Messages.ClassLoadingPage_CLASS_LOADING_ACTION, Messages.ClassLoadingPage_CLASS_LOADING_ACTION_DESC,
 185                                 b -> updateChart());
 186                 private final IAction classUnloadAction = DataPageToolkit.createTypeCheckAction(CLASS_UNLOAD,
 187                                 JdkTypeIDs.CLASS_UNLOAD, Messages.ClassLoadingPage_CLASS_UNLOADING_ACTION,
 188                                 Messages.ClassLoadingPage_CLASS_UNLOADING_ACTION_DESC, b -> updateChart());
 189                 private final Stream<IAction> statsActions = Stream
 190                                 .of(JdkAttributes.CLASSLOADER_LOADED_COUNT, JdkAttributes.CLASSLOADER_UNLOADED_COUNT)
 191                                 .map(a -> DataPageToolkit.createAttributeCheckAction(a, b -> updateChart()));
 192                 private final List<IAction> allChartSeriesActions = Stream
 193                                 .concat(Stream.of(classLoadAction, classUnloadAction), statsActions).collect(Collectors.toList());
 194                 private CTabFolder tabFolder;

 195                 private XYChart chart;
 196                 private IRange<IQuantity> timeRange;
 197                 private FlavorSelector flavorSelector;
 198 
 199                 ClassLoadingUi(Composite parent, FormToolkit toolkit, IPageContainer pageContainer, IState state) {
 200                         this.pageContainer = pageContainer;
 201 
 202                         Form form = DataPageToolkit.createForm(parent, toolkit, getName(), getIcon());
 203 
 204                         sash = new SashForm(form.getBody(), SWT.VERTICAL);
 205 
 206                         Composite chartComp = new Composite(sash, SWT.NONE);
 207                         chartComp.setLayout(new GridLayout());
 208                         Control legend = ActionUiToolkit.buildCheckboxControl(chartComp, allChartSeriesActions.stream(), false);
 209                         legend.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
 210                         ActionToolkit.loadCheckState(state.getChild(CHART), allChartSeriesActions.stream());
 211 
 212                         chart = new XYChart(pageContainer.getRecordingRange(), RendererToolkit.empty(), 180);
 213                         chart.setVisibleRange(timelineRange.getStart(), timelineRange.getEnd());
 214                         chart.addVisibleRangeListener(r -> timelineRange = r);
 215                         classLoadingChart = new ChartCanvas(chartComp);
 216                         classLoadingChart.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
 217                         DataPageToolkit.createChartTimestampTooltip(classLoadingChart);
 218                         DataPageToolkit.setChart(classLoadingChart, chart, pageContainer::showSelection, this::onChartSelection);
 219                         SelectionStoreActionToolkit.addSelectionStoreRangeActions(pageContainer.getSelectionStore(), chart,
 220                                         JfrAttributes.LIFETIME, Messages.ClassLoadingPage_CLASS_LOADING_TIMELINE_SELECTION,
 221                                         classLoadingChart.getContextMenu());
 222 
 223                         classloaderHistogram = CLASSLOADER_HISTOGRAM.buildWithoutBorder(sash,


 224                                         JdkAttributes.CLASS_DEFINING_CLASSLOADER, TableSettings.forState(state.getChild(HISTOGRAM)));
 225                         classloaderHistogramFilter = FilterComponent.createFilterComponent(classloaderHistogram, null,
 226                                         getDataSource().getItems().apply(JdkFilters.CLASS_LOAD_OR_UNLOAD),
 227                                         pageContainer.getSelectionStore()::getSelections, this::onHistogramFilterChange);
 228                         classloaderHistogram.getManager().getViewer().addSelectionChangedListener(
 229                                         e -> pageContainer.showSelection(classloaderHistogram.getSelection().getItems()));
 230                         MCContextMenuManager classLoaderHistogramMm = MCContextMenuManager
 231                                         .create(classloaderHistogram.getManager().getViewer().getControl());
 232                         ColumnMenusFactory.addDefaultMenus(classloaderHistogram.getManager(), classLoaderHistogramMm);
 233                         SelectionStoreActionToolkit.addSelectionStoreActions(pageContainer.getSelectionStore(),
 234                                         classloaderHistogram, Messages.ClassLoadingPage_CLASS_LOADING_HISTOGRAM_SELECTION,
 235                                         classLoaderHistogramMm);
 236                         classLoaderHistogramMm.add(classloaderHistogramFilter.getShowFilterAction());
 237                         classLoaderHistogramMm.add(classloaderHistogramFilter.getShowSearchAction());
 238                         classloaderHistogramFilter.loadState(state.getChild(HISTOGRAM_FILTER));


 239 
 240                         ItemHistogramWithInput.chain(classloaderHistogram, this::updateTables);
 241 



























 242                         tabFolder = new CTabFolder(sash, SWT.NONE);
 243 
 244                         classLoadingTable = CLASS_LOADING_LIST.buildWithoutBorder(tabFolder,
 245                                         TableSettings.forState(state.getChild(CLASS_LOADING_TABLE)));
 246                         classLoadingTable.getManager().getViewer().addSelectionChangedListener(e -> pageContainer
 247                                         .showSelection(ItemCollectionToolkit.build(classLoadingTable.getSelection().get())));
 248                         classLoadingFilter = FilterComponent.createFilterComponent(classLoadingTable, null,
 249                                         getDataSource().getItems().apply(JdkFilters.CLASS_LOAD),
 250                                         pageContainer.getSelectionStore()::getSelections, this::onClassLoadFilterChange);
 251                         MCContextMenuManager classLoadingTableMm = MCContextMenuManager
 252                                         .create(classLoadingTable.getManager().getViewer().getControl());
 253                         ColumnMenusFactory.addDefaultMenus(classLoadingTable.getManager(), classLoadingTableMm);
 254                         SelectionStoreActionToolkit.addSelectionStoreActions(pageContainer.getSelectionStore(), classLoadingTable,
 255                                         Messages.ClassLoadingPage_CLASS_LOADING_LIST_SELECTION, classLoadingTableMm);
 256                         classLoadingTableMm.add(classLoadingFilter.getShowFilterAction());
 257                         classLoadingTableMm.add(classLoadingFilter.getShowSearchAction());
 258                         classLoadingFilter.loadState(state.getChild(CLASS_LOADING_FILTER));
 259                         DataPageToolkit.addTabItem(tabFolder, classLoadingFilter.getComponent(),
 260                                         Messages.ClassLoadingPage_CLASS_LOADING_TAB_TITLE);
 261 


















 262                         classUnloadingTable = CLASS_UNLOADING_LIST.buildWithoutBorder(tabFolder,
 263                                         TableSettings.forState(state.getChild(CLASS_UNLOADING_TABLE)));
 264                         classUnloadingTable.getManager().getViewer().addSelectionChangedListener(e -> pageContainer
 265                                         .showSelection(ItemCollectionToolkit.build(classUnloadingTable.getSelection().get())));
 266                         classUnloadingFilter = FilterComponent.createFilterComponent(classUnloadingTable, null,
 267                                         getDataSource().getItems().apply(JdkFilters.CLASS_UNLOAD),
 268                                         pageContainer.getSelectionStore()::getSelections, this::onClassUnloadFilterChange);
 269                         MCContextMenuManager classUnloadingTableMm = MCContextMenuManager
 270                                         .create(classUnloadingTable.getManager().getViewer().getControl());
 271                         ColumnMenusFactory.addDefaultMenus(classUnloadingTable.getManager(), classUnloadingTableMm);
 272                         SelectionStoreActionToolkit.addSelectionStoreActions(pageContainer.getSelectionStore(), classUnloadingTable,
 273                                         Messages.ClassLoadingPage_CLASS_UNLOADING_LIST_SELECTION, classUnloadingTableMm);
 274                         classUnloadingTableMm.add(classUnloadingFilter.getShowFilterAction());
 275                         classUnloadingTableMm.add(classUnloadingFilter.getShowSearchAction());
 276                         classUnloadingFilter.loadState(state.getChild(CLASS_UNLOADING_FILTER));
 277                         DataPageToolkit.addTabItem(tabFolder, classUnloadingFilter.getComponent(),
 278                                         Messages.ClassLoadingPage_CLASS_UNLOADING_TAB_TITLE);
 279 
 280                         tabFolder.setSelection(tabFolderIndex);

 281 
 282                         PersistableSashForm.loadState(sash, state.getChild(SASH));
 283                         flavorSelector = FlavorSelector.itemsWithTimerange(form, TABLE_FILTER, getDataSource().getItems(),
 284                                         pageContainer, this::onInputSelected, this::onShow, flavorSelectorState);
 285                         addResultActions(form);
 286 
 287                         onHistogramFilterChange(histogramFilter);
 288                         onClassLoadFilterChange(classLoadTableFilter);
 289                         onClassUnloadFilterChange(classUnloadTableFilter);


 290 
 291                         classloaderHistogram.getManager().setSelectionState(histogramSelection);
 292                         classLoadingTable.getManager().setSelectionState(classLoadingTableSelection);
 293                         classUnloadingTable.getManager().setSelectionState(classUnloadingTableSelection);


 294                 }
 295 
 296                 private void onHistogramFilterChange(IItemFilter filter) {
 297                         classloaderHistogramFilter.filterChangeHelper(filter, classloaderHistogram,
 298                                         getDataSource().getItems().apply(JdkFilters.CLASS_LOAD_OR_UNLOAD));
 299                         if (classLoadingFilter != null) {
 300                                 classLoadingFilter.notifyListener();
 301                         }
 302                         if (classUnloadingFilter != null) {
 303                                 classUnloadingFilter.notifyListener();
 304                         }






 305                         histogramFilter = filter;
 306                 }
 307 
 308                 private void onClassLoadFilterChange(IItemFilter filter) {
 309                         classLoadingFilter.filterChangeHelper(filter, classLoadingTable,
 310                                         getDataSource().getItems().apply(JdkFilters.CLASS_LOAD));
 311                         classLoadTableFilter = filter;
 312                 }
 313 
 314                 private void onClassUnloadFilterChange(IItemFilter filter) {
 315                         classUnloadingFilter.filterChangeHelper(filter, classUnloadingTable,
 316                                         getDataSource().getItems().apply(JdkFilters.CLASS_UNLOAD));
 317                         classUnloadTableFilter = filter;
 318                 }
 319 












 320                 @Override
 321                 public void saveTo(IWritableState state) {
 322                         PersistableSashForm.saveState(sash, state.createChild(SASH));
 323                         classloaderHistogram.getManager().getSettings().saveState(state.createChild(HISTOGRAM));
 324                         classLoadingTable.getManager().getSettings().saveState(state.createChild(CLASS_LOADING_TABLE));
 325                         classUnloadingTable.getManager().getSettings().saveState(state.createChild(CLASS_UNLOADING_TABLE));


 326                         classloaderHistogramFilter.saveState(state.createChild(HISTOGRAM_FILTER));
 327                         classLoadingFilter.saveState(state.createChild(CLASS_LOADING_FILTER));
 328                         classUnloadingFilter.saveState(state.createChild(CLASS_UNLOADING_FILTER));


 329                         ActionToolkit.saveCheckState(state.createChild(CHART), allChartSeriesActions.stream());
 330 
 331                         saveToLocal();
 332                 }
 333 
 334                 private void saveToLocal() {
 335                         histogramSelection = classloaderHistogram.getManager().getSelectionState();
 336                         classLoadingTableSelection = classLoadingTable.getManager().getSelectionState();
 337                         classUnloadingTableSelection = classUnloadingTable.getManager().getSelectionState();


 338                         tabFolderIndex = tabFolder.getSelectionIndex();
 339                         flavorSelectorState = flavorSelector.getFlavorSelectorState();
 340                 }
 341 
 342                 private void onShow(Boolean show) {
 343                         IRange<IQuantity> range = show ? timeRange : pageContainer.getRecordingRange();
 344                         chart.setVisibleRange(range.getStart(), range.getEnd());
 345                         updateChart();
 346                 }
 347 
 348                 private void onInputSelected(IItemCollection items, IRange<IQuantity> timeRange) {
 349                         selectionItems = items;
 350                         this.timeRange = timeRange;
 351                         updateHistogram(getItems());
 352                         updateTables(getItems());
 353                         updateChart();
 354                 }
 355 
 356                 private IItemCollection getItems() {
 357                         return selectionItems != null ? selectionItems : getDataSource().getItems();


 378                                                 Messages.ClassLoadingPage_AGGR_CLASSES_UNLOADED_DESC, getItems().apply(JdkFilters.CLASS_UNLOAD),
 379                                                 Aggregators.count(Messages.ClassLoadingPage_AGGR_CLASSES_UNLOADED,
 380                                                                 Messages.ClassLoadingPage_AGGR_CLASSES_UNLOADED_DESC, JdkFilters.CLASS_UNLOAD),
 381                                                 TypeLabelProvider.getColor(JdkTypeIDs.CLASS_UNLOAD)));
 382                         }
 383                         classLoadingChart.replaceRenderer(RendererToolkit.uniformRows(rows));
 384                 }
 385 
 386                 private boolean isAttributeEnabled(IAttribute<IQuantity> attr) {
 387                         return allChartSeriesActions.stream().filter(a -> attr.getIdentifier().equals(a.getId())).findAny().get()
 388                                         .isChecked();
 389                 }
 390 
 391                 private void updateHistogram(IItemCollection items) {
 392                         if (classloaderHistogram != null) {
 393                                 classloaderHistogram.show(items.apply(JdkFilters.CLASS_LOAD_OR_UNLOAD));
 394                         }
 395                 }
 396 
 397                 private void updateTables(IItemCollection selectedItems) {
 398                         if (classLoadingTable != null && classUnloadingTable != null) {

 399                                 classLoadingTable.show(selectedItems.apply(JdkQueries.CLASS_LOAD.getFilter()));
 400                                 classUnloadingTable.show(selectedItems.apply(JdkQueries.CLASS_UNLOAD.getFilter()));

 401                         }
 402                 }
 403 
 404                 private void onChartSelection(IRange<IQuantity> range) {
 405                         // FIXME: Make this depend on the legend as well? And maybe on which chart row has been selected?
 406                         IItemCollection itemsInRange = range != null ? getItems().apply(ItemFilters
 407                                         .matchRange(RangeMatchPolicy.CENTER_CONTAINED_IN_RIGHT_OPEN, JfrAttributes.LIFETIME, range))
 408                                         : getItems();
 409                         updateTables(itemsInRange);
 410                         updateHistogram(itemsInRange);
 411                 }
 412 
 413         }
 414 
 415         private static final String SASH = "sash"; //$NON-NLS-1$
 416         private static final String HISTOGRAM = "histogram"; //$NON-NLS-1$
 417         private static final String HISTOGRAM_FILTER = "histogramFilter"; //$NON-NLS-1$
 418         private static final String CLASS_LOADING_TABLE = "classLoadingTable"; //$NON-NLS-1$
 419         private static final String CLASS_UNLOADING_TABLE = "classUnloadingTable"; //$NON-NLS-1$


 420         private static final String CLASS_LOADING_FILTER = "classLoadingFilter"; //$NON-NLS-1$
 421         private static final String CLASS_UNLOADING_FILTER = "classUnloadingFilter"; //$NON-NLS-1$


 422         private static final String CHART = "chart"; //$NON-NLS-1$
 423 
 424         @Override
 425         public IPageUI display(Composite parent, FormToolkit toolkit, IPageContainer pageContainer, IState state) {
 426                 return new ClassLoadingUi(parent, toolkit, pageContainer, state);
 427         }
 428 
 429         private SelectionState histogramSelection;
 430         private SelectionState classLoadingTableSelection;
 431         private SelectionState classUnloadingTableSelection;


 432         private IItemFilter histogramFilter;
 433         private IItemFilter classLoadTableFilter;
 434         private IItemFilter classUnloadTableFilter;


 435         private int tabFolderIndex = 0;
 436         private IRange<IQuantity> timelineRange;
 437         private FlavorSelectorState flavorSelectorState;
 438 
 439         public ClassLoadingPage(IPageDefinition dpd, StreamModel items, IPageContainer editor) {
 440                 super(dpd, items, editor);
 441                 timelineRange = editor.getRecordingRange();
 442         }
 443 
 444         @Override
 445         public IItemFilter getDefaultSelectionFilter() {
 446                 return ItemFilters.or(TABLE_FILTER, JdkFilters.CLASS_LOAD_STATISTICS);
 447         }
 448 
 449 }


  15  * and the following disclaimer.
  16  * 
  17  * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
  18  * conditions and the following disclaimer in the documentation and/or other materials provided with
  19  * the distribution.
  20  * 
  21  * 3. Neither the name of the copyright holder nor the names of its contributors may be used to
  22  * endorse or promote products derived from this software without specific prior written permission.
  23  * 
  24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  26  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  27  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
  31  * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32  */
  33 package org.openjdk.jmc.flightrecorder.ui.pages;
  34 
  35 
  36 import static org.openjdk.jmc.common.item.ItemQueryBuilder.fromWhere;
  37 
  38 import java.util.ArrayList;
  39 import java.util.HashSet;
  40 import java.util.Iterator;
  41 import java.util.LinkedHashMap;
  42 import java.util.List;
  43 import java.util.Map;
  44 import java.util.Set;
  45 import java.util.stream.Collectors;
  46 import java.util.stream.Stream;
  47 
  48 import org.eclipse.jface.action.IAction;
  49 import org.eclipse.jface.resource.ImageDescriptor;
  50 import org.eclipse.swt.SWT;
  51 import org.eclipse.swt.custom.CTabFolder;
  52 import org.eclipse.swt.custom.SashForm;
  53 import org.eclipse.swt.layout.GridData;
  54 import org.eclipse.swt.layout.GridLayout;
  55 import org.eclipse.swt.widgets.Composite;
  56 import org.eclipse.swt.widgets.Control;
  57 import org.eclipse.ui.forms.widgets.Form;
  58 import org.eclipse.ui.forms.widgets.FormToolkit;
  59 import org.openjdk.jmc.common.IMCClassLoader;
  60 import org.openjdk.jmc.common.IState;
  61 import org.openjdk.jmc.common.IWritableState;
  62 import org.openjdk.jmc.common.item.Aggregators;
  63 import org.openjdk.jmc.common.item.IAggregator;
  64 import org.openjdk.jmc.common.item.IAttribute;
  65 import org.openjdk.jmc.common.item.IItemCollection;
  66 import org.openjdk.jmc.common.item.IItemFilter;
  67 import org.openjdk.jmc.common.item.ItemFilters;
  68 import org.openjdk.jmc.common.item.RangeMatchPolicy;
  69 import org.openjdk.jmc.common.unit.IQuantity;
  70 import org.openjdk.jmc.common.unit.IRange;
  71 import org.openjdk.jmc.common.unit.UnitLookup;
  72 import org.openjdk.jmc.flightrecorder.JfrAttributes;
  73 import org.openjdk.jmc.flightrecorder.jdk.JdkAttributes;
  74 import org.openjdk.jmc.flightrecorder.jdk.JdkFilters;
  75 import org.openjdk.jmc.flightrecorder.jdk.JdkQueries;
  76 import org.openjdk.jmc.flightrecorder.jdk.JdkTypeIDs;
  77 import org.openjdk.jmc.flightrecorder.rules.util.JfrRuleTopics;
  78 import org.openjdk.jmc.flightrecorder.ui.FlightRecorderUI;
  79 import org.openjdk.jmc.flightrecorder.ui.IDataPageFactory;
  80 import org.openjdk.jmc.flightrecorder.ui.IDisplayablePage;
  81 import org.openjdk.jmc.flightrecorder.ui.IPageContainer;
  82 import org.openjdk.jmc.flightrecorder.ui.IPageDefinition;
  83 import org.openjdk.jmc.flightrecorder.ui.IPageUI;


 121                 public ImageDescriptor getImageDescriptor(IState state) {
 122                         return FlightRecorderUI.getDefault().getMCImageDescriptor(ImageConstants.PAGE_CLASSLOADING);
 123                 }
 124 
 125                 @Override
 126                 public String[] getTopics(IState state) {
 127                         return new String[] {JfrRuleTopics.CLASS_LOADING_TOPIC};
 128                 }
 129 
 130                 @Override
 131                 public IDisplayablePage createPage(IPageDefinition dpd, StreamModel items, IPageContainer editor) {
 132                         return new ClassLoadingPage(dpd, items, editor);
 133                 }
 134         }
 135 
 136         private static final IItemFilter TABLE_FILTER = ItemFilters.or(JdkQueries.CLASS_LOAD.getFilter(),
 137                         JdkQueries.CLASS_UNLOAD.getFilter());
 138         private static final ItemHistogramBuilder CLASSLOADER_HISTOGRAM = new ItemHistogramBuilder();
 139         private static final ItemListBuilder CLASS_LOADING_LIST = new ItemListBuilder();
 140         private static final ItemListBuilder CLASS_UNLOADING_LIST = new ItemListBuilder();
 141         private static final ItemListBuilder CLASS_DEFINE_LIST = new ItemListBuilder();
 142         private static final ItemListBuilder CLASS_LOADER_STATISTICS_LIST = new ItemListBuilder();
 143         private static final Map<String, Boolean> LEGEND_ITEMS = new LinkedHashMap<>();
 144         private static final String LOADED_COUNT = "loadedCount"; //$NON-NLS-1$
 145         private static final String UNLOADED_COUNT = "unloadedCount"; //$NON-NLS-1$
 146         private static final String CLASS_LOAD = "classLoad"; //$NON-NLS-1$
 147         private static final String CLASS_UNLOAD = "classUnload"; //$NON-NLS-1$
 148 
 149         static {
 150                 CLASSLOADER_HISTOGRAM.addColumn(LOADED_COUNT,
 151                                 Aggregators.count(Messages.ClassLoadingPage_AGGR_CLASSES_LOADED_BY_CLASSLOADER,
 152                                                 Messages.ClassLoadingPage_AGGR_CLASSES_LOADED_BY_CLASSLOADER_DESC,
 153                                                 ItemFilters.type(JdkTypeIDs.CLASS_LOAD)));
 154                 CLASSLOADER_HISTOGRAM.addColumn(UNLOADED_COUNT,
 155                                 Aggregators.count(Messages.ClassLoadingPage_AGGR_CLASSES_UNLOADED_BY_CLASSLOADER,
 156                                                 Messages.ClassLoadingPage_AGGR_CLASSES_UNLOADED_BY_CLASSLOADER_DESC,
 157                                                 ItemFilters.type(JdkTypeIDs.CLASS_UNLOAD)));
 158 
 159                 CLASS_LOADING_LIST.addColumn(JdkAttributes.CLASS_LOADED);
 160                 CLASS_LOADING_LIST.addColumn(JdkAttributes.CLASS_DEFINING_CLASSLOADER);
 161                 CLASS_LOADING_LIST.addColumn(JdkAttributes.CLASS_INITIATING_CLASSLOADER);
 162                 CLASS_LOADING_LIST.addColumn(JfrAttributes.START_TIME);
 163                 CLASS_LOADING_LIST.addColumn(JfrAttributes.DURATION);
 164                 CLASS_LOADING_LIST.addColumn(JfrAttributes.END_TIME);
 165                 CLASS_LOADING_LIST.addColumn(JfrAttributes.EVENT_THREAD);
 166                 
 167                 CLASS_UNLOADING_LIST.addColumn(JfrAttributes.EVENT_TIMESTAMP);
 168                 CLASS_UNLOADING_LIST.addColumn(JfrAttributes.EVENT_THREAD);
 169                 CLASS_UNLOADING_LIST.addColumn(JdkAttributes.CLASS_UNLOADED);
 170                 CLASS_UNLOADING_LIST.addColumn(JdkAttributes.CLASS_DEFINING_CLASSLOADER);
 171                 
 172                 CLASS_DEFINE_LIST.addColumn(JfrAttributes.START_TIME);
 173                 CLASS_DEFINE_LIST.addColumn(JdkAttributes.CLASS_DEFINING_CLASSLOADER);
 174                 CLASS_DEFINE_LIST.addColumn(JdkAttributes.CLASS_DEFINED);
 175                 CLASS_DEFINE_LIST.addColumn(JfrAttributes.EVENT_THREAD);
 176                 
 177                 CLASS_LOADER_STATISTICS_LIST.addColumn(JdkAttributes.ANONYMOUS_BLOCK_SIZE);
 178                 CLASS_LOADER_STATISTICS_LIST.addColumn(JdkAttributes.ANONYMOUS_CHUNK_SIZE);
 179                 CLASS_LOADER_STATISTICS_LIST.addColumn(JdkAttributes.ANONYMOUS_CLASS_COUNT);
 180                 CLASS_LOADER_STATISTICS_LIST.addColumn(JdkAttributes.BLOCK_SIZE);
 181                 CLASS_LOADER_STATISTICS_LIST.addColumn(JdkAttributes.CHUNK_SIZE);
 182                 CLASS_LOADER_STATISTICS_LIST.addColumn(JdkAttributes.CLASS_COUNT);
 183                 CLASS_LOADER_STATISTICS_LIST.addColumn(JdkAttributes.CLASS_LOADER_DATA);
 184                 CLASS_LOADER_STATISTICS_LIST.addColumn(JdkAttributes.PARENT_CLASSLOADER);
 185                 CLASS_LOADER_STATISTICS_LIST.addColumn(JdkAttributes.CLASSLOADER);
 186                 CLASS_LOADER_STATISTICS_LIST.addColumn(JfrAttributes.START_TIME);
 187                 // FIXME: Need to make a label provider for this
 188                 // FIXME: Want to have this in the same order
 189 
 190                 LEGEND_ITEMS.put(JdkAttributes.CLASSLOADER_LOADED_COUNT.getIdentifier(), Boolean.TRUE);
 191                 LEGEND_ITEMS.put(JdkAttributes.CLASSLOADER_UNLOADED_COUNT.getIdentifier(), Boolean.FALSE);
 192                 LEGEND_ITEMS.put(CLASS_LOAD, Boolean.TRUE);
 193                 LEGEND_ITEMS.put(CLASS_UNLOAD, Boolean.FALSE);
 194         }
 195 
 196         private class ClassLoadingUi implements IPageUI {
 197 
 198                 private final ChartCanvas classLoadingChart;
 199                 private final ItemList classLoadingTable;
 200                 private final ItemList classUnloadingTable;
 201                 private final ItemList classDefineTable;
 202                 private final ItemList classLoaderStatisticsTable;
 203                 private FilterComponent classLoadingFilter;
 204                 private FilterComponent classUnloadingFilter;
 205                 private FilterComponent classDefineFilter;
 206                 private FilterComponent classLoaderStatisticsFilter;
 207                 private final SashForm sash;
 208                 private final IPageContainer pageContainer;
 209                 private IItemCollection selectionItems;
 210                 private ItemHistogram classloaderHistogram;
 211                 private FilterComponent classloaderHistogramFilter;
 212                 private final IAction classLoadAction = DataPageToolkit.createTypeCheckAction(CLASS_LOAD, JdkTypeIDs.CLASS_LOAD,
 213                                 Messages.ClassLoadingPage_CLASS_LOADING_ACTION, Messages.ClassLoadingPage_CLASS_LOADING_ACTION_DESC,
 214                                 b -> updateChart());
 215                 private final IAction classUnloadAction = DataPageToolkit.createTypeCheckAction(CLASS_UNLOAD,
 216                                 JdkTypeIDs.CLASS_UNLOAD, Messages.ClassLoadingPage_CLASS_UNLOADING_ACTION,
 217                                 Messages.ClassLoadingPage_CLASS_UNLOADING_ACTION_DESC, b -> updateChart());
 218                 private final Stream<IAction> statsActions = Stream
 219                                 .of(JdkAttributes.CLASSLOADER_LOADED_COUNT, JdkAttributes.CLASSLOADER_UNLOADED_COUNT)
 220                                 .map(a -> DataPageToolkit.createAttributeCheckAction(a, b -> updateChart()));
 221                 private final List<IAction> allChartSeriesActions = Stream
 222                                 .concat(Stream.of(classLoadAction, classUnloadAction), statsActions).collect(Collectors.toList());
 223                 private CTabFolder tabFolder;
 224                 private CTabFolder classloaderFolder;
 225                 private XYChart chart;
 226                 private IRange<IQuantity> timeRange;
 227                 private FlavorSelector flavorSelector;
 228 
 229                 ClassLoadingUi(Composite parent, FormToolkit toolkit, IPageContainer pageContainer, IState state) {
 230                         this.pageContainer = pageContainer;
 231 
 232                         Form form = DataPageToolkit.createForm(parent, toolkit, getName(), getIcon());
 233 
 234                         sash = new SashForm(form.getBody(), SWT.VERTICAL);
 235 
 236                         Composite chartComp = new Composite(sash, SWT.NONE);
 237                         chartComp.setLayout(new GridLayout());
 238                         Control legend = ActionUiToolkit.buildCheckboxControl(chartComp, allChartSeriesActions.stream(), false);
 239                         legend.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
 240                         ActionToolkit.loadCheckState(state.getChild(CHART), allChartSeriesActions.stream());
 241 
 242                         chart = new XYChart(pageContainer.getRecordingRange(), RendererToolkit.empty(), 180);
 243                         chart.setVisibleRange(timelineRange.getStart(), timelineRange.getEnd());
 244                         chart.addVisibleRangeListener(r -> timelineRange = r);
 245                         classLoadingChart = new ChartCanvas(chartComp);
 246                         classLoadingChart.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
 247                         DataPageToolkit.createChartTimestampTooltip(classLoadingChart);
 248                         DataPageToolkit.setChart(classLoadingChart, chart, pageContainer::showSelection, this::onChartSelection);
 249                         SelectionStoreActionToolkit.addSelectionStoreRangeActions(pageContainer.getSelectionStore(), chart,
 250                                         JfrAttributes.LIFETIME, Messages.ClassLoadingPage_CLASS_LOADING_TIMELINE_SELECTION,
 251                                         classLoadingChart.getContextMenu());
 252 
 253                         classloaderFolder = new CTabFolder(sash, SWT.NONE);
 254 
 255                         classloaderHistogram = CLASSLOADER_HISTOGRAM.buildWithoutBorder(classloaderFolder,
 256                                         JdkAttributes.CLASS_DEFINING_CLASSLOADER, TableSettings.forState(state.getChild(HISTOGRAM)));
 257                         classloaderHistogramFilter = FilterComponent.createFilterComponent(classloaderHistogram, null,
 258                                         getDataSource().getItems().apply(JdkFilters.CLASS_LOAD_OR_UNLOAD),
 259                                         pageContainer.getSelectionStore()::getSelections, this::onHistogramFilterChange);
 260                         classloaderHistogram.getManager().getViewer().addSelectionChangedListener(
 261                                         e -> pageContainer.showSelection(classloaderHistogram.getSelection().getItems()));
 262                         MCContextMenuManager classLoaderHistogramMm = MCContextMenuManager
 263                                         .create(classloaderHistogram.getManager().getViewer().getControl());
 264                         ColumnMenusFactory.addDefaultMenus(classloaderHistogram.getManager(), classLoaderHistogramMm);
 265                         SelectionStoreActionToolkit.addSelectionStoreActions(pageContainer.getSelectionStore(),
 266                                         classloaderHistogram, Messages.ClassLoadingPage_CLASS_LOADING_HISTOGRAM_SELECTION,
 267                                         classLoaderHistogramMm);
 268                         classLoaderHistogramMm.add(classloaderHistogramFilter.getShowFilterAction());
 269                         classLoaderHistogramMm.add(classloaderHistogramFilter.getShowSearchAction());
 270                         classloaderHistogramFilter.loadState(state.getChild(HISTOGRAM_FILTER));
 271                         DataPageToolkit.addTabItem(classloaderFolder, classloaderHistogramFilter.getComponent(),
 272                                         Messages.ClassLoadingPage_CLASS_LOADER_TAB);
 273 
 274                         ItemHistogramWithInput.chain(classloaderHistogram, this::updateTables);
 275 
 276                         classLoaderStatisticsTable = CLASS_LOADER_STATISTICS_LIST.buildWithoutBorder(classloaderFolder,
 277                                         TableSettings.forState(state.getChild(CLASS_LOADER_STATISTICS_TABLE)));
 278                         classLoaderStatisticsTable.getManager().getViewer().addSelectionChangedListener(e -> {
 279                                 // The standard aggregators will skip the null classloader, so we need to do this manually.
 280                                 IItemCollection selection = ItemCollectionToolkit.build(classLoaderStatisticsTable.getSelection().get());
 281                                 Stream<IMCClassLoader> stream = ItemCollectionToolkit.values(selection, JdkAttributes.CLASSLOADER).get().distinct();
 282                                 Set<IMCClassLoader> selected = stream.collect(Collectors.toSet());
 283                                 IItemFilter selectionFilter =  ItemFilters.and(ItemFilters.or(JdkFilters.CLASS_LOAD_OR_UNLOAD,
 284                                 JdkFilters.CLASS_DEFINE), ItemFilters.memberOf(JdkAttributes.CLASS_DEFINING_CLASSLOADER, selected));
 285                                 IItemCollection filteredItems = getDataSource().getItems().apply(selectionFilter);
 286                                 pageContainer.showSelection(filteredItems);
 287                                 updateTables(filteredItems);
 288                         });
 289                         classLoaderStatisticsFilter = FilterComponent.createFilterComponent(classLoaderStatisticsTable, null,
 290                                         getDataSource().getItems().apply(JdkFilters.CLASS_LOADER_STATISTICS),
 291                                         pageContainer.getSelectionStore()::getSelections, this::onClassLoaderStatisticsFilterChange);
 292                         MCContextMenuManager classLoaderStatisticsTableMm = MCContextMenuManager
 293                                         .create(classLoaderStatisticsTable.getManager().getViewer().getControl());
 294                         ColumnMenusFactory.addDefaultMenus(classLoaderStatisticsTable.getManager(), classLoaderStatisticsTableMm);
 295                         SelectionStoreActionToolkit.addSelectionStoreActions(pageContainer.getSelectionStore(), classLoaderStatisticsTable,
 296                                         Messages.ClassLoadingPage_CLASS_LOADER_STATISTICS_LIST_SELECTION, classLoaderStatisticsTableMm);
 297                         classLoaderStatisticsTableMm.add(classLoaderStatisticsFilter.getShowFilterAction());
 298                         classLoaderStatisticsTableMm.add(classLoaderStatisticsFilter.getShowSearchAction());
 299                         classLoaderStatisticsFilter.loadState(state.getChild(CLASS_LOADER_STATISTICS_FILTER));
 300                         DataPageToolkit.addTabItem(classloaderFolder, classLoaderStatisticsFilter.getComponent(),
 301                                         Messages.ClassLoadingPage_CLASS_LOADER_STATISTICS_TAB_TITLE);
 302 
 303                         tabFolder = new CTabFolder(sash, SWT.NONE);
 304 
 305                         classLoadingTable = CLASS_LOADING_LIST.buildWithoutBorder(tabFolder,
 306                                         TableSettings.forState(state.getChild(CLASS_LOADING_TABLE)));
 307                         classLoadingTable.getManager().getViewer().addSelectionChangedListener(e -> pageContainer
 308                                         .showSelection(ItemCollectionToolkit.build(classLoadingTable.getSelection().get())));
 309                         classLoadingFilter = FilterComponent.createFilterComponent(classLoadingTable, null,
 310                                         getDataSource().getItems().apply(JdkFilters.CLASS_LOAD),
 311                                         pageContainer.getSelectionStore()::getSelections, this::onClassLoadFilterChange);
 312                         MCContextMenuManager classLoadingTableMm = MCContextMenuManager
 313                                         .create(classLoadingTable.getManager().getViewer().getControl());
 314                         ColumnMenusFactory.addDefaultMenus(classLoadingTable.getManager(), classLoadingTableMm);
 315                         SelectionStoreActionToolkit.addSelectionStoreActions(pageContainer.getSelectionStore(), classLoadingTable,
 316                                         Messages.ClassLoadingPage_CLASS_LOADING_LIST_SELECTION, classLoadingTableMm);
 317                         classLoadingTableMm.add(classLoadingFilter.getShowFilterAction());
 318                         classLoadingTableMm.add(classLoadingFilter.getShowSearchAction());
 319                         classLoadingFilter.loadState(state.getChild(CLASS_LOADING_FILTER));
 320                         DataPageToolkit.addTabItem(tabFolder, classLoadingFilter.getComponent(),
 321                                         Messages.ClassLoadingPage_CLASS_LOADING_TAB_TITLE);
 322                         
 323                         classDefineTable = CLASS_DEFINE_LIST.buildWithoutBorder(tabFolder,
 324                                         TableSettings.forState(state.getChild(CLASS_DEFINE_TABLE)));
 325                         classDefineTable.getManager().getViewer().addSelectionChangedListener(e -> pageContainer
 326                                         .showSelection(ItemCollectionToolkit.build(classDefineTable.getSelection().get())));
 327                         classDefineFilter = FilterComponent.createFilterComponent(classDefineTable, null,
 328                                         getDataSource().getItems().apply(JdkFilters.CLASS_DEFINE),
 329                                         pageContainer.getSelectionStore()::getSelections, this::onClassDefineFilterChange);
 330                         MCContextMenuManager classDefineTableMm = MCContextMenuManager
 331                                         .create(classDefineTable.getManager().getViewer().getControl());
 332                         ColumnMenusFactory.addDefaultMenus(classDefineTable.getManager(), classDefineTableMm);
 333                         SelectionStoreActionToolkit.addSelectionStoreActions(pageContainer.getSelectionStore(), classDefineTable,
 334                                         Messages.ClassLoadingPage_CLASS_DEFINE_LIST_SELECTION, classDefineTableMm);
 335                         classDefineTableMm.add(classDefineFilter.getShowFilterAction());
 336                         classDefineTableMm.add(classDefineFilter.getShowSearchAction());
 337                         classDefineFilter.loadState(state.getChild(CLASS_DEFINE_FILTER));
 338                         DataPageToolkit.addTabItem(tabFolder, classDefineFilter.getComponent(),
 339                                         Messages.ClassLoadingPage_CLASS_DEFINE_TAB_TITLE);
 340 
 341                         classUnloadingTable = CLASS_UNLOADING_LIST.buildWithoutBorder(tabFolder,
 342                                         TableSettings.forState(state.getChild(CLASS_UNLOADING_TABLE)));
 343                         classUnloadingTable.getManager().getViewer().addSelectionChangedListener(e -> pageContainer
 344                                         .showSelection(ItemCollectionToolkit.build(classUnloadingTable.getSelection().get())));
 345                         classUnloadingFilter = FilterComponent.createFilterComponent(classUnloadingTable, null,
 346                                         getDataSource().getItems().apply(JdkFilters.CLASS_UNLOAD),
 347                                         pageContainer.getSelectionStore()::getSelections, this::onClassUnloadFilterChange);
 348                         MCContextMenuManager classUnloadingTableMm = MCContextMenuManager
 349                                         .create(classUnloadingTable.getManager().getViewer().getControl());
 350                         ColumnMenusFactory.addDefaultMenus(classUnloadingTable.getManager(), classUnloadingTableMm);
 351                         SelectionStoreActionToolkit.addSelectionStoreActions(pageContainer.getSelectionStore(), classUnloadingTable,
 352                                         Messages.ClassLoadingPage_CLASS_UNLOADING_LIST_SELECTION, classUnloadingTableMm);
 353                         classUnloadingTableMm.add(classUnloadingFilter.getShowFilterAction());
 354                         classUnloadingTableMm.add(classUnloadingFilter.getShowSearchAction());
 355                         classUnloadingFilter.loadState(state.getChild(CLASS_UNLOADING_FILTER));
 356                         DataPageToolkit.addTabItem(tabFolder, classUnloadingFilter.getComponent(),
 357                                         Messages.ClassLoadingPage_CLASS_UNLOADING_TAB_TITLE);
 358 
 359                         tabFolder.setSelection(tabFolderIndex);
 360                         classloaderFolder.setSelection(tabFolderIndex);
 361 
 362                         PersistableSashForm.loadState(sash, state.getChild(SASH));
 363                         flavorSelector = FlavorSelector.itemsWithTimerange(form, TABLE_FILTER, getDataSource().getItems(),
 364                                         pageContainer, this::onInputSelected, this::onShow, flavorSelectorState);
 365                         addResultActions(form);
 366 
 367                         onHistogramFilterChange(histogramFilter);
 368                         onClassLoadFilterChange(classLoadTableFilter);
 369                         onClassUnloadFilterChange(classUnloadTableFilter);
 370                         onClassDefineFilterChange(classDefineTableFilter);
 371                         onClassLoaderStatisticsFilterChange(classLoaderStatisticsTableFilter);
 372 
 373                         classloaderHistogram.getManager().setSelectionState(histogramSelection);
 374                         classLoadingTable.getManager().setSelectionState(classLoadingTableSelection);
 375                         classUnloadingTable.getManager().setSelectionState(classUnloadingTableSelection);
 376                         classDefineTable.getManager().setSelectionState(classDefineTableSelection);
 377                         classLoaderStatisticsTable.getManager().setSelectionState(classLoaderStatisticsTableSelection);
 378                 }
 379 
 380                 private void onHistogramFilterChange(IItemFilter filter) {
 381                         classloaderHistogramFilter.filterChangeHelper(filter, classloaderHistogram,
 382                                         getDataSource().getItems().apply(ItemFilters.or(JdkFilters.CLASS_LOAD_OR_UNLOAD, JdkFilters.CLASS_DEFINE)));
 383                         if (classLoadingFilter != null) {
 384                                 classLoadingFilter.notifyListener();
 385                         }
 386                         if (classUnloadingFilter != null) {
 387                                 classUnloadingFilter.notifyListener();
 388                         }
 389                         if (classDefineFilter != null) {
 390                                 classDefineFilter.notifyListener();
 391                         }
 392                         if (classLoaderStatisticsFilter != null) {
 393                                 classLoaderStatisticsFilter.notifyListener();
 394                         }
 395                         histogramFilter = filter;
 396                 }
 397 
 398                 private void onClassLoadFilterChange(IItemFilter filter) {
 399                         classLoadingFilter.filterChangeHelper(filter, classLoadingTable,
 400                                         getDataSource().getItems().apply(JdkFilters.CLASS_LOAD));
 401                         classLoadTableFilter = filter;
 402                 }
 403 
 404                 private void onClassUnloadFilterChange(IItemFilter filter) {
 405                         classUnloadingFilter.filterChangeHelper(filter, classUnloadingTable,
 406                                         getDataSource().getItems().apply(JdkFilters.CLASS_UNLOAD));
 407                         classUnloadTableFilter = filter;
 408                 }
 409                 
 410                 private void onClassDefineFilterChange(IItemFilter filter) {
 411                         classDefineFilter.filterChangeHelper(filter, classDefineTable,
 412                                         getDataSource().getItems().apply(JdkFilters.CLASS_DEFINE));
 413                         classDefineTableFilter = filter;
 414                 }
 415                 
 416                 private void onClassLoaderStatisticsFilterChange(IItemFilter filter) {
 417                         classLoaderStatisticsFilter.filterChangeHelper(filter, classLoaderStatisticsTable,
 418                                         getDataSource().getItems().apply(JdkFilters.CLASS_LOADER_STATISTICS));
 419                         classLoaderStatisticsTableFilter = filter;
 420                 }
 421         
 422                 @Override
 423                 public void saveTo(IWritableState state) {
 424                         PersistableSashForm.saveState(sash, state.createChild(SASH));
 425                         classloaderHistogram.getManager().getSettings().saveState(state.createChild(HISTOGRAM));
 426                         classLoadingTable.getManager().getSettings().saveState(state.createChild(CLASS_LOADING_TABLE));
 427                         classUnloadingTable.getManager().getSettings().saveState(state.createChild(CLASS_UNLOADING_TABLE));
 428                         classDefineTable.getManager().getSettings().saveState(state.createChild(CLASS_DEFINE_TABLE));
 429                         classLoaderStatisticsTable.getManager().getSettings().saveState(state.createChild(CLASS_LOADER_STATISTICS_TABLE));
 430                         classloaderHistogramFilter.saveState(state.createChild(HISTOGRAM_FILTER));
 431                         classLoadingFilter.saveState(state.createChild(CLASS_LOADING_FILTER));
 432                         classUnloadingFilter.saveState(state.createChild(CLASS_UNLOADING_FILTER));
 433                         classDefineFilter.saveState(state.createChild(CLASS_DEFINE_FILTER));
 434                         classLoaderStatisticsFilter.saveState(state.createChild(CLASS_LOADER_STATISTICS_FILTER));
 435                         ActionToolkit.saveCheckState(state.createChild(CHART), allChartSeriesActions.stream());
 436 
 437                         saveToLocal();
 438                 }
 439 
 440                 private void saveToLocal() {
 441                         histogramSelection = classloaderHistogram.getManager().getSelectionState();
 442                         classLoadingTableSelection = classLoadingTable.getManager().getSelectionState();
 443                         classUnloadingTableSelection = classUnloadingTable.getManager().getSelectionState();
 444                         classDefineTableSelection = classDefineTable.getManager().getSelectionState();
 445                         classLoaderStatisticsTableSelection = classLoaderStatisticsTable.getManager().getSelectionState();
 446                         tabFolderIndex = tabFolder.getSelectionIndex();
 447                         flavorSelectorState = flavorSelector.getFlavorSelectorState();
 448                 }
 449 
 450                 private void onShow(Boolean show) {
 451                         IRange<IQuantity> range = show ? timeRange : pageContainer.getRecordingRange();
 452                         chart.setVisibleRange(range.getStart(), range.getEnd());
 453                         updateChart();
 454                 }
 455 
 456                 private void onInputSelected(IItemCollection items, IRange<IQuantity> timeRange) {
 457                         selectionItems = items;
 458                         this.timeRange = timeRange;
 459                         updateHistogram(getItems());
 460                         updateTables(getItems());
 461                         updateChart();
 462                 }
 463 
 464                 private IItemCollection getItems() {
 465                         return selectionItems != null ? selectionItems : getDataSource().getItems();


 486                                                 Messages.ClassLoadingPage_AGGR_CLASSES_UNLOADED_DESC, getItems().apply(JdkFilters.CLASS_UNLOAD),
 487                                                 Aggregators.count(Messages.ClassLoadingPage_AGGR_CLASSES_UNLOADED,
 488                                                                 Messages.ClassLoadingPage_AGGR_CLASSES_UNLOADED_DESC, JdkFilters.CLASS_UNLOAD),
 489                                                 TypeLabelProvider.getColor(JdkTypeIDs.CLASS_UNLOAD)));
 490                         }
 491                         classLoadingChart.replaceRenderer(RendererToolkit.uniformRows(rows));
 492                 }
 493 
 494                 private boolean isAttributeEnabled(IAttribute<IQuantity> attr) {
 495                         return allChartSeriesActions.stream().filter(a -> attr.getIdentifier().equals(a.getId())).findAny().get()
 496                                         .isChecked();
 497                 }
 498 
 499                 private void updateHistogram(IItemCollection items) {
 500                         if (classloaderHistogram != null) {
 501                                 classloaderHistogram.show(items.apply(JdkFilters.CLASS_LOAD_OR_UNLOAD));
 502                         }
 503                 }
 504 
 505                 private void updateTables(IItemCollection selectedItems) {
 506                         if (classLoadingTable != null && classUnloadingTable != null && classDefineTable != null
 507                                         && classLoaderStatisticsTable != null) {
 508                                 classLoadingTable.show(selectedItems.apply(JdkQueries.CLASS_LOAD.getFilter()));
 509                                 classUnloadingTable.show(selectedItems.apply(JdkQueries.CLASS_UNLOAD.getFilter()));
 510                                 classDefineTable.show(selectedItems.apply(JdkQueries.CLASS_DEFINE.getFilter()));
 511                         }
 512                 }
 513 
 514                 private void onChartSelection(IRange<IQuantity> range) {
 515                         // FIXME: Make this depend on the legend as well? And maybe on which chart row has been selected?
 516                         IItemCollection itemsInRange = range != null ? getItems().apply(ItemFilters
 517                                         .matchRange(RangeMatchPolicy.CENTER_CONTAINED_IN_RIGHT_OPEN, JfrAttributes.LIFETIME, range))
 518                                         : getItems();
 519                         updateTables(itemsInRange);
 520                         updateHistogram(itemsInRange);
 521                 }
 522 
 523         }
 524 
 525         private static final String SASH = "sash"; //$NON-NLS-1$
 526         private static final String HISTOGRAM = "histogram"; //$NON-NLS-1$
 527         private static final String HISTOGRAM_FILTER = "histogramFilter"; //$NON-NLS-1$
 528         private static final String CLASS_LOADING_TABLE = "classLoadingTable"; //$NON-NLS-1$
 529         private static final String CLASS_UNLOADING_TABLE = "classUnloadingTable"; //$NON-NLS-1$
 530         private static final String CLASS_DEFINE_TABLE = "classDefineTable"; //$NON-NLS-1$
 531         private static final String CLASS_LOADER_STATISTICS_TABLE = "classLoaderStatisticsTable"; //$NON-NLS-1$
 532         private static final String CLASS_LOADING_FILTER = "classLoadingFilter"; //$NON-NLS-1$
 533         private static final String CLASS_UNLOADING_FILTER = "classUnloadingFilter"; //$NON-NLS-1$
 534         private static final String CLASS_DEFINE_FILTER = "classDefineFilter"; //$NON-NLS-1$
 535         private static final String CLASS_LOADER_STATISTICS_FILTER = "classLoaderStatisticsFilter"; //$NON-NLS-1$
 536         private static final String CHART = "chart"; //$NON-NLS-1$
 537 
 538         @Override
 539         public IPageUI display(Composite parent, FormToolkit toolkit, IPageContainer pageContainer, IState state) {
 540                 return new ClassLoadingUi(parent, toolkit, pageContainer, state);
 541         }
 542 
 543         private SelectionState histogramSelection;
 544         private SelectionState classLoadingTableSelection;
 545         private SelectionState classUnloadingTableSelection;
 546         private SelectionState classDefineTableSelection;
 547         private SelectionState classLoaderStatisticsTableSelection;
 548         private IItemFilter histogramFilter;
 549         private IItemFilter classLoadTableFilter;
 550         private IItemFilter classUnloadTableFilter;
 551         private IItemFilter classDefineTableFilter;
 552         private IItemFilter classLoaderStatisticsTableFilter;
 553         private int tabFolderIndex = 0;
 554         private IRange<IQuantity> timelineRange;
 555         private FlavorSelectorState flavorSelectorState;
 556 
 557         public ClassLoadingPage(IPageDefinition dpd, StreamModel items, IPageContainer editor) {
 558                 super(dpd, items, editor);
 559                 timelineRange = editor.getRecordingRange();
 560         }
 561 
 562         @Override
 563         public IItemFilter getDefaultSelectionFilter() {
 564                 return ItemFilters.or(TABLE_FILTER, JdkFilters.CLASS_LOAD_STATISTICS);
 565         }
 566 
 567 }
< prev index next >