gov.llnl.lc.infiniband.opensm.plugin.gui.chart.PortCounterXYplotPanel.java Source code

Java tutorial

Introduction

Here is the source code for gov.llnl.lc.infiniband.opensm.plugin.gui.chart.PortCounterXYplotPanel.java

Source

/************************************************************
 * Copyright (c) 2015, Lawrence Livermore National Security, LLC.
 * Produced at the Lawrence Livermore National Laboratory.
 * Written by Timothy Meier, meier3@llnl.gov, All rights reserved.
 * LLNL-CODE-673346
 *
 * This file is part of the OpenSM Monitoring Service (OMS) package.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License (as published by
 * the Free Software Foundation) version 2.1 dated February 1999.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * OUR NOTICE AND TERMS AND CONDITIONS OF THE GNU GENERAL PUBLIC LICENSE
 *
 * Our Preamble Notice
 *
 * A. This notice is required to be provided under our contract with the U.S.
 * Department of Energy (DOE). This work was produced at the Lawrence Livermore
 * National Laboratory under Contract No.  DE-AC52-07NA27344 with the DOE.
 *
 * B. Neither the United States Government nor Lawrence Livermore National
 * Security, LLC nor any of their employees, makes any warranty, express or
 * implied, or assumes any liability or responsibility for the accuracy,
 * completeness, or usefulness of any information, apparatus, product, or
 * process disclosed, or represents that its use would not infringe privately-
 * owned rights.
 *
 * C. Also, reference herein to any specific commercial products, process, or
 * services by trade name, trademark, manufacturer or otherwise does not
 * necessarily constitute or imply its endorsement, recommendation, or favoring
 * by the United States Government or Lawrence Livermore National Security,
 * LLC. The views and opinions of authors expressed herein do not necessarily
 * state or reflect those of the United States Government or Lawrence Livermore
 * National Security, LLC, and shall not be used for advertising or product
 * endorsement purposes.
 *
 *        file: PortCounterXYplotPanel.java
 *
 *  Created on: Aug 6, 2015
 *      Author: meier3
 ********************************************************************/
package gov.llnl.lc.infiniband.opensm.plugin.gui.chart;

import java.util.LinkedHashMap;

import javax.swing.JFrame;
import javax.swing.JPanel;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.time.FixedMillisecond;
import org.jfree.data.time.RegularTimePeriod;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.RefineryUtilities;

import gov.llnl.lc.infiniband.opensm.plugin.data.OMS_Collection;
import gov.llnl.lc.infiniband.opensm.plugin.data.OSM_FabricDelta;
import gov.llnl.lc.infiniband.opensm.plugin.data.OSM_FabricDeltaCollection;
import gov.llnl.lc.infiniband.opensm.plugin.data.OSM_Port;
import gov.llnl.lc.infiniband.opensm.plugin.data.OpenSmMonitorService;
import gov.llnl.lc.infiniband.opensm.plugin.data.PFM_Port.PortCounterName;
import gov.llnl.lc.infiniband.opensm.plugin.data.PFM_PortChange;
import gov.llnl.lc.infiniband.opensm.plugin.data.PFM_PortRate;
import gov.llnl.lc.infiniband.opensm.plugin.data.PFM_PortRate.PortCounterUnits;
import gov.llnl.lc.infiniband.opensm.plugin.graph.IB_Vertex;
import gov.llnl.lc.logging.CommonLogger;
import gov.llnl.lc.smt.data.SMT_UpdateService;
import gov.llnl.lc.smt.event.SmtMessage;
import gov.llnl.lc.smt.event.SmtMessageType;
import gov.llnl.lc.smt.manager.MessageManager;
import gov.llnl.lc.smt.manager.SMT_AnalysisManager;
import gov.llnl.lc.time.TimeStamp;

public class PortCounterXYplotPanel extends ChartPanel implements CommonLogger {
    private IB_Vertex Vertex;
    private OSM_Port Port;
    private PortCounterName PortCounter;
    private boolean AddExtra;
    private boolean isError;
    private TimeSeries TSeries = new TimeSeries("counts");

    private String FrameTitle;

    private long prevVal = 0;
    private TimeStamp prevTS = null;

    /**
     * A time series plot of a single port counter.  This is a multiple axis
     * plot, showing the actual value, and the delta value.  Optionally two
     * additional data sets can be displayed for correlation purposes if the
     * "includeExtra" argument is set.
     * 
     *  In the case of an Error counter, the xmit and rcv delta counts are
     *  included.
     *  
     *  In the case of a Traffic counter, the rate and % utilization values are
     *  included
     *  
     */

    public PortCounterXYplotPanel() {
        // this is the normal constructor
        super(null);
    }

    public PortCounterXYplotPanel(String title) {
        this();
        // this is the normal constructor
        FrameTitle = title;
    }

    /************************************************************
     * Method Name:
     *  getTSeries
     **/
    /**
     * Returns the value of tSeries
     *
     * @return the tSeries
     *
     ***********************************************************/

    public TimeSeries getTSeries() {
        return TSeries;
    }

    /************************************************************
     * Method Name:
     *  PortCounterXYplot
    **/
    /**
     * A time series plot of a single port counter.  This is a multiple axis
     * plot, showing the actual value, and the delta value.  Optionally two
     * additional data sets can be displayed for correlation purposes if the
     * "includeExtra" argument is set.
     * 
     *  In the case of an Error counter, the xmit and rcv delta counts are
     *  included.
     *  
     *  In the case of a Traffic counter, the rate and % utilization values are
     *  included
     *
     * @see     XYPlot
     *
     * @param vertex        the parent node of the port
     * @param port          the parent port of the counter
     * @param portCounter   the specific counter to be plotted
     * @param includeExtra  true if extra counter values should be plotted
     ***********************************************************/
    public PortCounterXYplotPanel(IB_Vertex vertex, OSM_Port port, PortCounterName portCounter,
            boolean includeExtra) {
        // this is the normal constructor
        this(portCounter.getName() + "   [" + vertex.getName() + "   (" + port.getOSM_PortKey() + ")]");

        this.Vertex = vertex;
        this.Port = port;
        this.PortCounter = portCounter;
        this.AddExtra = includeExtra;
        isError = PortCounterName.PFM_ERROR_COUNTERS.contains(portCounter);

        // create the first simple plot of the absolute counter values, quick
        JFreeChart chart = createChart();

        if (chart == null) {
            // need at least two datapoints to this chart to make sense
            logger.severe("Chart unavailable, cannot create the XY Panel");
            return;
        }

        this.setChart(chart);
        this.setPreferredSize(new java.awt.Dimension(600, 270));
        this.setDomainZoomable(true);
        this.setRangeZoomable(true);

        this.setMouseWheelEnabled(true);

        // now fire off a worker thread to add the other axis (1 to 3 more) which
        // can take noticeable time

        // TODO Needs more work and testing, plots and tables seem to be missing things and colored wrong
        PortCounterPlotWorker worker1 = new PortCounterPlotWorker(chart, port, portCounter, includeExtra, isError);

        worker1.execute();
    }

    //  private class PortCounterPlotWorkerOrig extends SwingWorker<Void, Void>
    //  {
    //    JFreeChart Chart = null;
    //    
    //    public PortCounterPlotWorkerOrig(JFreeChart chart)
    //    {
    //      super();
    //      Chart = chart;
    //     }
    //
    //    @Override
    //    protected Void doInBackground() throws Exception
    //    {
    //      // 1.  counter value (already done, just add following to this)
    //      // 2.  delta/period
    //      //
    //      //    -- if error counter --
    //      // 3.  include xmit and rcv traffic deltas? (own scale)
    //      //
    //      //
    //      //    -- if traffic counter --
    //      // 3.  include rate and utilization values?
    //      //
    //      
    //      // this is a SwingWorker thread from its pool, give it a recognizable name
    //     Thread.currentThread().setName("PortCounterPlotWorkerOrig");
    //      
    //      logger.info( "Worker Building Plot");
    //      SMT_UpdateService updateService = SMT_UpdateService.getInstance();
    //      OMS_Collection history = updateService.getCollection();
    //      OSM_FabricDeltaCollection deltaHistory = history.getOSM_FabricDeltaCollection();
    //
    //      XYPlot plot = (XYPlot) Chart.getPlot();
    // 
    //      // AXIS 2 - the change, or delta value of the desired counter
    //      NumberAxis axis2 = new NumberAxis(PortCounterAxisLabel.DELTA.getName());
    //      axis2.setFixedDimension(10.0);
    //      axis2.setAutoRangeIncludesZero(false);
    //      plot.setRangeAxis(1, axis2);
    //      
    //      XYDataset dataset2 = createDeltaDataset(deltaHistory, PortCounter, PortCounterAxisLabel.DELTA.getName());
    //        plot.setDataset(1, dataset2);
    //        plot.mapDatasetToRangeAxis(1, 1);
    //        XYItemRenderer renderer2 = new StandardXYItemRenderer();
    //        plot.setRenderer(1, renderer2);
    //        
    //        // the other two axis are optional, and vary depending on the
    //        // type of counter
    //        NumberAxis axis3 = null;
    //        XYDataset dataset3 = null;
    //        XYItemRenderer renderer3 = null;
    //        NumberAxis axis4 = null;
    //        XYDataset dataset4 = null;
    //        XYItemRenderer renderer4 = null;
    //
    //        
    //        if(AddExtra)
    //        {
    //          if(isError)
    //          {
    //            
    //            // add rcv deltas
    //            PortCounterName pcr = PortCounterName.rcv_data;
    //            axis3 = new NumberAxis(PortCounterAxisLabel.RCV_DELTA.getName());
    //            axis3.setFixedDimension(10.0);
    //            axis3.setAutoRangeIncludesZero(false);
    //            plot.setRangeAxis(2, axis3);
    //
    //            dataset3 = createDeltaDataset(deltaHistory, pcr, pcr.getName());
    //            plot.setDataset(2, dataset3);
    //            plot.mapDatasetToRangeAxis(2, 2);
    //            renderer3 = new StandardXYItemRenderer();
    //            plot.setRenderer(2, renderer3);
    //            
    //            // add xmit deltas
    //            pcr = PortCounterName.xmit_data;
    //            axis4 = new NumberAxis(PortCounterAxisLabel.XMT_DELTA.getName());
    //            axis4.setFixedDimension(10.0);
    //            axis4.setAutoRangeIncludesZero(false);
    //            plot.setRangeAxis(3, axis4);
    //
    //            dataset4 = createDeltaDataset(deltaHistory, pcr, pcr.getName());
    //            plot.setDataset(3, dataset4);
    //            plot.mapDatasetToRangeAxis(3, 3);
    //            renderer4 = new StandardXYItemRenderer();
    //            plot.setRenderer(3, renderer4);
    //            
    //            // use a common scale for both xmit and rcv counters
    //            double minRange = axis3.getLowerBound() < axis4.getLowerBound() ? axis3.getLowerBound(): axis4.getLowerBound();
    //            double maxRange = axis3.getUpperBound() < axis4.getUpperBound() ? axis4.getUpperBound(): axis3.getUpperBound();
    //            axis3.setAutoRange(false);
    //            axis4.setAutoRange(false);
    //            axis3.setRange(minRange, maxRange);
    //            axis4.setRange(minRange, maxRange);
    //          }
    //          else
    //          {
    //            // add rate
    //            PortCounterName pcr = PortCounter;
    //            axis3 = new NumberAxis(pcr.getName() + " " + PortCounterAxisLabel.RATE.getUnits());
    //            axis3.setFixedDimension(10.0);
    //            axis3.setAutoRangeIncludesZero(true);
    //            plot.setRangeAxis(2, axis3);
    //
    //            dataset3 = createRateDataset(deltaHistory, pcr, PortCounterAxisLabel.RATE.getName());
    //            plot.setDataset(2, dataset3);
    //            plot.mapDatasetToRangeAxis(2, 2);
    //            renderer3 = new StandardXYItemRenderer();
    //            plot.setRenderer(2, renderer3);
    //            
    //            // add utilization
    //            axis4 = new NumberAxis(pcr.getName() + " " + PortCounterAxisLabel.UTILIZATION.getUnits());
    //            axis4.setFixedDimension(10.0);
    //   //         axis4.setAutoRangeIncludesZero(true);
    //            axis4.setRange(0.0, 100.0);
    //            plot.setRangeAxis(3, axis4);
    //
    //            dataset4 = createUtilizationDataset(deltaHistory, pcr, PortCounterAxisLabel.UTILIZATION.getName());
    //            plot.setDataset(3, dataset4);
    //            plot.mapDatasetToRangeAxis(3, 3);
    //            renderer4 = new StandardXYItemRenderer();
    //            plot.setRenderer(3, renderer4);
    //          }
    //        }
    //        ChartUtilities.applyCurrentTheme(Chart);
    //        
    //        Color c1 = Color.black;
    //        Color c2 = Color.blue;
    //        
    //        Color c3 = Color.green;
    //        Color c4 = Color.magenta;
    //        
    //        Color ce = Color.red;
    //             
    //        if(isError)
    //          c2 = ce;
    //        
    //        // change the series and axis colours after the theme has
    //        // been applied...
    //        plot.getRenderer().setSeriesPaint(0, c1);
    //
    //        renderer2.setSeriesPaint(0, c2);
    //        axis2.setLabelPaint(c2);
    //        axis2.setTickLabelPaint(c2);
    //        
    //        if(AddExtra)
    //        {
    //          renderer3.setSeriesPaint(0, c3);
    //          axis3.setLabelPaint(c3);
    //          axis3.setTickLabelPaint(c3);
    //          
    //          renderer4.setSeriesPaint(0, c4);
    //          axis4.setLabelPaint(c4);
    //          axis4.setTickLabelPaint(c4);
    //        }
    //
    //      return null;
    //    }
    //    
    //    @Override
    //    public void done()
    //    {
    //      // completion notification
    //      logger.info( "Worker Done Building Plot");
    //      MessageManager.getInstance().postMessage(new SmtMessage(SmtMessageType.SMT_MSG_INFO, "Worker Done Building Plot"));
    //     }
    //  }

    private JFreeChart createChart() {
        // 1.  counter value
        //
        // -- see worker thread for following axis --
        //
        // 2.  delta/period
        //
        //    -- if error counter --
        // 3.  include xmit and rcv traffic deltas? (own scale)
        //
        //
        //    -- if traffic counter --
        // 3.  include rate and utilization values?
        //

        SMT_UpdateService updateService = SMT_UpdateService.getInstance();
        OMS_Collection history = updateService.getCollection();

        if ((history == null) || (history.getSize() < 2)) {
            // need at least two datapoints to this chart to make sense
            logger.severe("OMS Delta unavailable, cannot createChart(), must wait for more historical snapshots");
            MessageManager.getInstance().postMessage(
                    new SmtMessage(SmtMessageType.SMT_MSG_SEVERE, "Cannot build chart without historical data"));
            return null;
        }

        MessageManager.getInstance()
                .postMessage(new SmtMessage(SmtMessageType.SMT_MSG_INFO, "Worker Building Plot"));
        long deltaPeriod = history.getAveDeltaSeconds();

        // the primary dataset of the desired counter which will be axis1  
        XYDataset dataset1 = createDataset(history);

        // setup the chart for the desired counter
        JFreeChart chart = ChartFactory.createTimeSeriesChart(
                PortCounter.getName() + "   [" + Vertex.getName() + " port " + Port.getPortNumber() + "]",
                "Time of Day", PortCounterAxisLabel.COUNTS.getName(), dataset1, true, true, false);

        chart.addSubtitle(new TextTitle("Port Counter Activity (" + deltaPeriod + " sec. delta)"));
        XYPlot plot = (XYPlot) chart.getPlot();
        plot.setOrientation(PlotOrientation.VERTICAL);
        plot.setDomainPannable(true);
        plot.setRangePannable(true);
        plot.getRangeAxis().setFixedDimension(15.0);

        return chart;
    }

    /**
     * Creates a sample dataset.
     *
     * @param name  the dataset name.
     * @param base  the starting value.
     * @param start  the starting period.
     * @param count  the number of values to generate.
     *
     * @return The dataset.
     */
    private XYDataset createDataset(OMS_Collection history) {
        // iterate through the collection, and build up a time series
        for (int j = 0; j < history.getSize(); j++) {
            OpenSmMonitorService osm = history.getOMS(j);

            // find the desired port counter, in this instance
            LinkedHashMap<String, OSM_Port> pL = osm.getFabric().getOSM_Ports();
            OSM_Port p = pL.get(OSM_Port.getOSM_PortKey(Port));
            long lValue = prevVal;
            TimeStamp ts = prevTS;
            if ((p != null) && (p.pfmPort != null)) {
                lValue = p.pfmPort.getCounter(PortCounter);
                ts = p.pfmPort.getCounterTimeStamp();
                prevVal = lValue;
                prevTS = ts;
            }

            RegularTimePeriod ms = new FixedMillisecond(ts.getTimeInMillis());
            //      TSeries.add(ms, (double)lValue);
            TSeries.addOrUpdate(ms, (double) lValue);
        }
        TimeSeriesCollection dataset = new TimeSeriesCollection();
        dataset.addSeries(TSeries);

        return dataset;
    }

    private XYDataset createDeltaDataset(OSM_FabricDeltaCollection deltaHistory, PortCounterName pcn,
            String seriesName) {
        TimeSeries series = new TimeSeries(seriesName);

        // iterate through the collection, and build up a time series
        for (int j = 0; j < deltaHistory.getSize(); j++) {
            OSM_FabricDelta delta = deltaHistory.getOSM_FabricDelta(j);

            // find the desired port counter, in this instance
            LinkedHashMap<String, PFM_PortChange> pcL = delta.getPortChanges();
            PFM_PortChange pC = pcL.get(OSM_Port.getOSM_PortKey(Port));
            long lValue = pC.getDelta_port_counter(pcn);

            // correct for missing time periods
            int deltaSeconds = delta.getDeltaSeconds();
            long sweepPeriod = delta.getFabric2().getPerfMgrSweepSecs();
            if (sweepPeriod < deltaSeconds) {
                // graph is reported as counts per period, so if the period is too long, interpolate
                lValue *= sweepPeriod;
                lValue /= deltaSeconds;
            }
            TimeStamp ts = pC.getCounterTimeStamp();

            RegularTimePeriod ms = new FixedMillisecond(ts.getTimeInMillis());
            series.add(ms, (double) lValue);
        }
        TimeSeriesCollection dataset = new TimeSeriesCollection();
        dataset.addSeries(series);

        return dataset;
    }

    private XYDataset createRateDataset(OSM_FabricDeltaCollection deltaHistory, PortCounterName pcn,
            String seriesName) {
        TimeSeries series = new TimeSeries(seriesName);

        // iterate through the collection, and build up a time series
        for (int j = 0; j < deltaHistory.getSize(); j++) {
            OSM_FabricDelta delta = deltaHistory.getOSM_FabricDelta(j);

            // find the desired port counter, in this instance
            PFM_PortChange pC = delta.getPortChange(Port);
            long lValue = PFM_PortRate.getChangeRateLong(pC, pcn, PortCounterUnits.MEGABYTES);
            TimeStamp ts = pC.getCounterTimeStamp();

            RegularTimePeriod ms = new FixedMillisecond(ts.getTimeInMillis());
            series.add(ms, (double) lValue);
        }
        TimeSeriesCollection dataset = new TimeSeriesCollection();
        dataset.addSeries(series);

        return dataset;
    }

    private XYDataset createUtilizationDataset(OSM_FabricDeltaCollection deltaHistory, PortCounterName pcn,
            String seriesName) {
        TimeSeries series = new TimeSeries(seriesName);

        // iterate through the collection, and build up a time series
        for (int j = 0; j < deltaHistory.getSize(); j++) {
            OSM_FabricDelta delta = deltaHistory.getOSM_FabricDelta(j);

            // find the desired port counter, in this instance
            LinkedHashMap<String, PFM_PortChange> pcL = delta.getPortChanges();
            PFM_PortChange pC = pcL.get(OSM_Port.getOSM_PortKey(Port));
            PFM_PortRate pR = new PFM_PortRate(pC);
            TimeStamp ts = pC.getCounterTimeStamp();

            // convert rate to utilization
            double lValue = SMT_AnalysisManager.getInstance().getDeltaAnalysis().getPortUtilization(pR, pcn);

            RegularTimePeriod ms = new FixedMillisecond(ts.getTimeInMillis());
            series.add(ms, lValue);
        }
        TimeSeriesCollection dataset = new TimeSeriesCollection();
        dataset.addSeries(series);

        return dataset;
    }

    /**
     * Creates a panel for the XY Plot
     *
     * @return A panel.
     */
    public JPanel createPlotPanel() {
        JFreeChart chart = createChart();
        ChartPanel panel = new ChartPanel(chart);
        panel.setMouseWheelEnabled(true);
        return panel;
    }

    /**
     * Starting point for the demonstration application.
     *
     * @param args  ignored.
     */
    public static void main(String[] args) {
        JFrame jf = new JFrame();

        PortCounterXYplotPanel demo = new PortCounterXYplotPanel("JFreeChart: PortCounterXYplot.java");
        jf.getContentPane().add(demo);
        jf.pack();
        RefineryUtilities.centerFrameOnScreen(jf);
        jf.setVisible(true);
    }

}