diff --git a/apps/heartbeat/java/build.xml b/apps/heartbeat/java/build.xml index d506b0edf..a266f4dfe 100644 --- a/apps/heartbeat/java/build.xml +++ b/apps/heartbeat/java/build.xml @@ -1,20 +1,37 @@ - - + + + + + + + + + + - + - + + + + + + + + + + @@ -25,12 +42,16 @@ - + + + + - + + @@ -48,6 +69,7 @@ + diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/ClientEngine.java b/apps/heartbeat/java/src/net/i2p/heartbeat/ClientEngine.java index 0f85eae8d..a0ef6232d 100644 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/ClientEngine.java +++ b/apps/heartbeat/java/src/net/i2p/heartbeat/ClientEngine.java @@ -4,6 +4,7 @@ import net.i2p.data.Destination; import net.i2p.util.Clock; import net.i2p.util.I2PThread; import net.i2p.util.Log; +import net.i2p.util.Clock; /** * Responsible for actually conducting the tests, coordinating the storing of the diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/Heartbeat.java b/apps/heartbeat/java/src/net/i2p/heartbeat/Heartbeat.java index 70ad6313f..5a6fe476a 100644 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/Heartbeat.java +++ b/apps/heartbeat/java/src/net/i2p/heartbeat/Heartbeat.java @@ -30,6 +30,8 @@ import net.i2p.util.Log; * # where our private destination keys are located - if this doesn't exist, * # a new one will be created and saved there (by default, heartbeat.keys) * privateDestinationFile=heartbeat_r2.keys + * # where do we want to export the plain base64 of our destination? + * publicDestinationFile=heartbeat_r2.txt * * ## peer tests configured below: * diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/I2PAdapter.java b/apps/heartbeat/java/src/net/i2p/heartbeat/I2PAdapter.java index 015a96840..46eb8c6a2 100644 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/I2PAdapter.java +++ b/apps/heartbeat/java/src/net/i2p/heartbeat/I2PAdapter.java @@ -37,6 +37,8 @@ class I2PAdapter { private int _numHops; /** filename containing the heartbeat engine's private destination info */ private String _privateDestFile; + /** filename to store the heartbeat engine's public destination in base64*/ + private String _publicDestFile; /** our destination */ private Destination _localDest; /** who do we tell? */ @@ -53,6 +55,10 @@ class I2PAdapter { private static final String DEST_FILE_PROP = "privateDestinationFile"; /** by default, the private destination data is in "heartbeat.keys" */ private static final String DEST_FILE_DEFAULT = "heartbeat.keys"; + /** where will we export the public destination in base 64? */ + private static final String PUBLIC_DEST_FILE_PROP = "publicDestinationFile"; + /** where will we export the public destination in base 64? */ + private static final String PUBLIC_DEST_FILE_DEFAULT = "heartbeat.txt"; /** This config property defines where the I2P router is */ private static final String I2CP_HOST_PROP = "i2cpHost"; /** by default, the I2P host is "localhost" */ @@ -72,6 +78,7 @@ class I2PAdapter { */ public I2PAdapter() { _privateDestFile = null; + _publicDestFile = null; _i2cpHost = null; _i2cpPort = -1; _localDest = null; @@ -126,6 +133,7 @@ class I2PAdapter { */ void loadConfig(Properties props) { String privDestFile = props.getProperty(DEST_FILE_PROP, DEST_FILE_DEFAULT); + String pubDestFile = props.getProperty(PUBLIC_DEST_FILE_PROP, PUBLIC_DEST_FILE_DEFAULT); String host = props.getProperty(I2CP_HOST_PROP, I2CP_HOST_DEFAULT); String port = props.getProperty(I2CP_PORT_PROP, "" + I2CP_PORT_DEFAULT); String numHops = props.getProperty(NUMHOPS_PROP, "" + NUMHOPS_DEFAULT); @@ -151,6 +159,7 @@ class I2PAdapter { _numHops = hops; _privateDestFile = privDestFile; + _publicDestFile = pubDestFile; _i2cpHost = host; _i2cpPort = portNum; } @@ -165,6 +174,12 @@ class I2PAdapter { } else { props.setProperty(DEST_FILE_PROP, DEST_FILE_DEFAULT); } + + if (_publicDestFile != null) { + props.setProperty(PUBLIC_DEST_FILE_PROP, _publicDestFile); + } else { + props.setProperty(PUBLIC_DEST_FILE_PROP, PUBLIC_DEST_FILE_DEFAULT); + } if (_i2cpHost != null) { props.setProperty(I2CP_HOST_PROP, _i2cpHost); @@ -406,6 +421,18 @@ class I2PAdapter { if (_log.shouldLog(Log.INFO)) { _log.info("Existing destination loaded: [" + us.toBase64() + "]"); } + + FileOutputStream fos = null; + try { + fos = new FileOutputStream(_publicDestFile); + fos.write(us.toBase64().getBytes()); + fos.flush(); + } catch (IOException fioe) { + _log.error("Error writing out the plain destination to [" + _publicDestFile + "]", fioe); + } finally { + if (fos != null) try { fos.close(); } catch (IOException fioe) {} + } + } catch (IOException ioe) { if (fin != null) try { fin.close(); @@ -466,7 +493,9 @@ class I2PAdapter { */ private Properties getOptions() { Properties props = new Properties(); - props.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_BEST_EFFORT); + // this should be BEST_EFFORT, but i'm too lazy to update the code to handle tracking + // sessionTags and sessionKeys, marking them as delivered on pong. + props.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_GUARANTEED); props.setProperty(I2PClient.PROP_TCP_HOST, _i2cpHost); props.setProperty(I2PClient.PROP_TCP_PORT, _i2cpPort + ""); props.setProperty("tunnels.depthInbound", "" + _numHops); diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatControlPane.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatControlPane.java index 813f3a151..d2d69c32b 100644 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatControlPane.java +++ b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatControlPane.java @@ -43,6 +43,7 @@ class HeartbeatControlPane extends JPanel { _configPane.addTab(config.getTitle(), null, new JScrollPane(new PeerPlotConfigPane(config, this)), config.getSummary()); _configPane.setBackgroundAt(_configPane.getTabCount()-1, _background); _configPane.setForegroundAt(_configPane.getTabCount()-1, _foreground); + _gui.pack(); } /** diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitor.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitor.java index a4ac94c4c..57a7999ab 100644 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitor.java +++ b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitor.java @@ -6,14 +6,16 @@ import net.i2p.util.Log; /** * The HeartbeatMonitor, complete with main()! Act now, and it's only 5 easy * payments of $19.95 (plus shipping and handling)! You heard me, only _5_ - * easy payments of $19.95 (plus shipping and handling)! + * easy payments of $19.95 (plus shipping and handling)!

* * (fine print: something about some states in the US requiring the addition - * of sales tax... or something) + * of sales tax... or something)

* - * (finer print: Satan owns you. Deal with it.) + * (finer print: Satan owns you. Deal with it.)

+ * + * (even finer print: usage: HeartbeatMonitor [configFilename]) */ -public class HeartbeatMonitor implements PeerPlotStateFetcher.FetchStateReceptor { +public class HeartbeatMonitor implements PeerPlotStateFetcher.FetchStateReceptor, PeerPlotConfig.UpdateListener { private final static Log _log = new Log(HeartbeatMonitor.class); private HeartbeatMonitorState _state; private HeartbeatMonitorGUI _gui; @@ -73,6 +75,7 @@ public class HeartbeatMonitor implements PeerPlotStateFetcher.FetchStateReceptor */ public void load(String location) { PeerPlotConfig cfg = new PeerPlotConfig(location); + cfg.addListener(this); PeerPlotState state = new PeerPlotState(cfg); PeerPlotStateFetcher.fetchPeerPlotState(this, state); } @@ -99,4 +102,9 @@ public class HeartbeatMonitor implements PeerPlotStateFetcher.FetchStateReceptor else new HeartbeatMonitor().runMonitor(); } + + public void configUpdated(PeerPlotConfig config) { + _log.debug("Config updated, revamping the gui"); + _gui.stateUpdated(); + } } \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorCommandBar.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorCommandBar.java index 0ca18f174..c95aa68a3 100644 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorCommandBar.java +++ b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorCommandBar.java @@ -46,7 +46,7 @@ class HeartbeatMonitorCommandBar extends JPanel { _refreshRate.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent evt) { refreshChanged(evt); } }); _refreshRate.setEnabled(false); _refreshRate.setBackground(_gui.getBackground()); - add(_refreshRate); + //add(_refreshRate); JLabel loadLabel = new JLabel("Load from: "); loadLabel.setBackground(_gui.getBackground()); add(loadLabel); diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorGUI.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorGUI.java index 80025e1df..08b3d9e40 100644 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorGUI.java +++ b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorGUI.java @@ -10,6 +10,7 @@ import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JScrollPane; +import javax.swing.JSplitPane; class HeartbeatMonitorGUI extends JFrame { private HeartbeatMonitor _monitor; @@ -27,7 +28,7 @@ class HeartbeatMonitorGUI extends JFrame { _monitor = monitor; initializeComponents(); pack(); - setResizable(false); + //setResizable(false); setVisible(true); } @@ -39,16 +40,18 @@ class HeartbeatMonitorGUI extends JFrame { setBackground(_background); - _plotPane = new HeartbeatPlotPane(this); + _plotPane = new JFreeChartHeartbeatPlotPane(this); // new HeartbeatPlotPane(this); _plotPane.setBackground(_background); - JScrollPane pane = new JScrollPane(_plotPane); - pane.setBackground(_background); - getContentPane().add(pane, BorderLayout.CENTER); + //JScrollPane pane = new JScrollPane(_plotPane); + //pane.setBackground(_background); + getContentPane().add(new JScrollPane(_plotPane), BorderLayout.CENTER); _controlPane = new HeartbeatControlPane(this); _controlPane.setBackground(_background); getContentPane().add(_controlPane, BorderLayout.SOUTH); + //JSplitPane pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(_plotPane), new JScrollPane(_controlPane)); + //getContentPane().add(pane, BorderLayout.CENTER); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); initializeMenus(); } diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatPlotPane.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatPlotPane.java index 2fb1f64e8..699f7c8a4 100644 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatPlotPane.java +++ b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatPlotPane.java @@ -15,7 +15,7 @@ import net.i2p.util.Log; */ class HeartbeatPlotPane extends JPanel { private final static Log _log = new Log(HeartbeatPlotPane.class); - private HeartbeatMonitorGUI _gui; + protected HeartbeatMonitorGUI _gui; private JTextArea _text; /** @@ -48,9 +48,9 @@ class HeartbeatPlotPane extends JPanel { _text.setText(buf.toString()); } - private void initializeComponents() { - setBackground(new Color(255, 255, 255)); - // Dimension size = new Dimension(800, 600); + protected void initializeComponents() { + setBackground(_gui.getBackground()); + //Dimension size = new Dimension(800, 600); _text = new JTextArea("",30,80); // 16, 60); _text.setAutoscrolls(true); _text.setEditable(false); diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartAdapter.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartAdapter.java new file mode 100644 index 000000000..cb56efd2e --- /dev/null +++ b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartAdapter.java @@ -0,0 +1,234 @@ +package net.i2p.heartbeat.gui; + +import net.i2p.heartbeat.PeerData; +import net.i2p.util.Log; + +import org.jfree.data.XYSeries; +import org.jfree.data.XYSeriesCollection; +import org.jfree.data.MovingAverage; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.plot.Plot; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.axis.DateAxis; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.renderer.XYLineAndShapeRenderer; +import org.jfree.chart.renderer.XYItemRenderer; +import org.jfree.chart.renderer.XYDotRenderer; +import java.util.List; + +import javax.swing.JPanel; +import java.awt.Font; +import java.awt.Color; + +class JFreeChartAdapter { + private final static Log _log = new Log(JFreeChartAdapter.class); + private final static Color WHITE = new Color(255, 255, 255); + + ChartPanel createPanel(HeartbeatMonitorState state) { + ChartPanel panel = new ChartPanel(createChart(state)); + panel.setDisplayToolTips(true); + panel.setEnforceFileExtensions(true); + panel.setHorizontalZoom(true); + panel.setVerticalZoom(true); + panel.setMouseZoomable(true, true); + panel.getChart().setBackgroundPaint(WHITE); + return panel; + } + + JFreeChart createChart(HeartbeatMonitorState state) { + Plot plot = createPlot(state); + JFreeChart chart = new JFreeChart("I2P Heartbeat performance", Font.getFont("arial"), plot, true); + return chart; + } + + void updateChart(ChartPanel panel, HeartbeatMonitorState state) { + XYPlot plot = (XYPlot)panel.getChart().getPlot(); + plot.setDataset(getCollection(state)); + updateLines(plot, state); + } + + private long getFirst(HeartbeatMonitorState state) { + long first = -1; + for (int i = 0; i < state.getTestCount(); i++) { + List dataPoints = state.getTest(i).getCurrentData().getDataPoints(); + if ( (dataPoints != null) && (dataPoints.size() > 0) ) { + PeerData.EventDataPoint data = (PeerData.EventDataPoint)dataPoints.get(0); + if ( (first < 0) || (first > data.getPingSent()) ) + first = data.getPingSent(); + } + } + return first; + } + + Plot createPlot(HeartbeatMonitorState state) { + XYItemRenderer renderer = new XYLineAndShapeRenderer(); // new XYDotRenderer(); // + XYPlot plot = new XYPlot(getCollection(state), new DateAxis(), new NumberAxis("ms"), renderer); + updateLines(plot, state); + return plot; + } + + private void updateLines(XYPlot plot, HeartbeatMonitorState state) { + if (true) return; + if (state == null) return; + for (int i = 0; i < state.getTestCount(); i++) { + PeerPlotConfig config = state.getTest(i).getPlotConfig(); + PeerPlotConfig.PlotSeriesConfig curConfig = config.getCurrentSeriesConfig(); + XYSeriesCollection col = ((XYSeriesCollection)plot.getDataset()); + for (int j = 0; j < col.getSeriesCount(); j++) { + //XYItemRenderer renderer = plot.getRendererForDataset(col.getSeries(j)); + XYItemRenderer renderer = plot.getRendererForDataset(col); + if (col.getSeriesName(j).startsWith(config.getTitle() + " send")) { + if (curConfig.getPlotSendTime()) { + //renderer.setPaint(curConfig.getPlotLineColor()); + } + } + if (col.getSeriesName(j).startsWith(config.getTitle() + " receive")) { + if (curConfig.getPlotReceiveTime()) { + //renderer.setPaint(curConfig.getPlotLineColor()); + } + } + if (col.getSeriesName(j).startsWith(config.getTitle() + " lost")) { + if (curConfig.getPlotLostMessages()) { + //renderer.setPaint(curConfig.getPlotLineColor()); + } + } + } + } + } + + XYSeriesCollection getCollection(HeartbeatMonitorState state) { + XYSeriesCollection col = new XYSeriesCollection(); + if (state != null) { + for (int i = 0; i < state.getTestCount(); i++) { + addTest(col, state.getTest(i)); + } + } else { + XYSeries series = new XYSeries("latency", false, false); + series.add(System.currentTimeMillis(), 0); + col.addSeries(series); + } + return col; + } + + void addTest(XYSeriesCollection col, PeerPlotState state) { + PeerPlotConfig config = state.getPlotConfig(); + PeerPlotConfig.PlotSeriesConfig curConfig = config.getCurrentSeriesConfig(); + addLines(col, curConfig, config.getTitle(), state.getCurrentData().getDataPoints()); + addAverageLines(col, config, config.getTitle(), state.getCurrentData()); + } + + /** + * @param config preferences for how to display this test + * @param lineName minimal name of the test (e.g. "jxHa.32KB.60s") + * @param data List of PeerData.EventDataPoint describing all of the events in the test + */ + void addLines(XYSeriesCollection col, PeerPlotConfig.PlotSeriesConfig config, String lineName, List data) { + if (config.getPlotSendTime()) { + XYSeries sendSeries = getSendSeries(data); + sendSeries.setName(lineName + " send"); + sendSeries.setDescription("milliseconds for the ping to reach the peer"); + col.addSeries(sendSeries); + } + if (config.getPlotReceiveTime()) { + XYSeries recvSeries = getReceiveSeries(data); + recvSeries.setName(lineName + " receive"); + recvSeries.setDescription("milliseconds for the peer's pong to reach the sender"); + col.addSeries(recvSeries); + } + if (config.getPlotLostMessages()) { + XYSeries lostSeries = getLostSeries(data); + lostSeries.setName(lineName + " lost"); + lostSeries.setDescription("number of ping/pong messages lost"); + col.addSeries(lostSeries); + } + } + + /** + * Add a data series for each average that we're configured to render + * + * @param config preferences for how to display this test + * @param lineName minimal name of the test (e.g. "jxHa.32KB.60s") + * @param data List of PeerData.EventDataPoint describing all of the events in the test + */ + void addAverageLines(XYSeriesCollection col, PeerPlotConfig config, String lineName, StaticPeerData data) { + if (data.getDataPointCount() <= 0) return; + PeerData.EventDataPoint start = (PeerData.EventDataPoint)data.getDataPoints().get(0); + PeerData.EventDataPoint finish = (PeerData.EventDataPoint)data.getDataPoints().get(data.getDataPointCount()-1); + + List configs = config.getAverageSeriesConfigs(); + + for (int i = 0; i < configs.size(); i++) { + PeerPlotConfig.PlotSeriesConfig cfg = (PeerPlotConfig.PlotSeriesConfig)configs.get(i); + int minutes = (int)cfg.getPeriod()/(60*1000); + if (cfg.getPlotSendTime()) { + double time = data.getAverageSendTime(minutes); + if (time > 0) { + XYSeries series = new XYSeries(lineName + " send " + minutes + "m avg [" + time + "]", false, false); + series.add(start.getPingSent(), time); + series.add(finish.getPingSent(), time); + series.setDescription("send time, averaged over the last " + minutes + " minutes"); + col.addSeries(series); + } + } + if (cfg.getPlotReceiveTime()) { + double time = data.getAverageReceiveTime(minutes); + if (time > 0) { + XYSeries series = new XYSeries(lineName + " receive " + minutes + "m avg[" + time + "]", false, false); + series.add(start.getPingSent(), time); + series.add(finish.getPingSent(), time); + series.setDescription("receive time, averaged over the last " + minutes + " minutes"); + col.addSeries(series); + } + } + if (cfg.getPlotLostMessages()) { + double num = data.getLostMessages(minutes); + if (num > 0) { + XYSeries series = new XYSeries(lineName + " lost messages (" + num + " in " + minutes + "m)", false, false); + series.add(start.getPingSent(), num); + series.add(finish.getPingSent(), num); + series.setDescription("number of messages lost in the last " + minutes + " minutes"); + col.addSeries(series); + } + } + } + } + + XYSeries getSendSeries(List data) { + XYSeries series = new XYSeries("sent", false, false); + for (int i = 0; i < data.size(); i++) { + PeerData.EventDataPoint point = (PeerData.EventDataPoint)data.get(i); + if (point.getWasPonged()) { + series.add(point.getPingSent(), point.getPongSent()-point.getPingSent()); + } else { + // series.add(data.getPingSent(), 0); + } + } + return series; + } + + XYSeries getReceiveSeries(List data) { + XYSeries series = new XYSeries("receive", false, false); + for (int i = 0; i < data.size(); i++) { + PeerData.EventDataPoint point = (PeerData.EventDataPoint)data.get(i); + if (point.getWasPonged()) { + series.add(point.getPingSent(), point.getPongReceived()-point.getPongSent()); + } else { + // series.add(data.getPingSent(), 0); + } + } + return series; + } + XYSeries getLostSeries(List data) { + XYSeries series = new XYSeries("lost", false, false); + for (int i = 0; i < data.size(); i++) { + PeerData.EventDataPoint point = (PeerData.EventDataPoint)data.get(i); + if (point.getWasPonged()) { + //series.add(point.getPingSent(), 0); + } else { + series.add(point.getPingSent(), 1); + } + } + return series; + } +} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartHeartbeatPlotPane.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartHeartbeatPlotPane.java new file mode 100644 index 000000000..c12fd88a0 --- /dev/null +++ b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartHeartbeatPlotPane.java @@ -0,0 +1,58 @@ +package net.i2p.heartbeat.gui; + +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.JScrollPane; +import javax.swing.JLabel; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import net.i2p.heartbeat.PeerDataWriter; +import net.i2p.util.Log; + +import org.jfree.chart.ChartPanel; + +/** + * Render the graph and legend + * + */ +class JFreeChartHeartbeatPlotPane extends HeartbeatPlotPane { + private final static Log _log = new Log(JFreeChartHeartbeatPlotPane.class); + private ChartPanel _panel; + private JFreeChartAdapter _adapter; + + public JFreeChartHeartbeatPlotPane(HeartbeatMonitorGUI gui) { + super(gui); + } + + public void stateUpdated() { + if (_panel == null) { + remove(0); // remove the dummy + + _adapter = new JFreeChartAdapter(); + _panel = _adapter.createPanel(_gui.getMonitor().getState()); + _panel.setBackground(_gui.getBackground()); + add(new JScrollPane(_panel), BorderLayout.CENTER); + _gui.pack(); + } else { + _adapter.updateChart(_panel, _gui.getMonitor().getState()); + //_gui.pack(); + } + } + + protected void initializeComponents() { + // noop + setLayout(new BorderLayout()); + add(new JLabel(), BorderLayout.CENTER); + //dummy.setBackground(_gui.getBackground()); + //dummy.setPreferredSize(new Dimension(800,600)); + //add(dummy); + + //add(_panel); + + } +} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfig.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfig.java index dcb4cf4f9..5c8fe5581 100644 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfig.java +++ b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfig.java @@ -11,12 +11,14 @@ import java.util.Set; import java.util.TreeMap; import net.i2p.data.Destination; +import net.i2p.util.Log; import net.i2p.heartbeat.ClientConfig; /** * Configure how we want to render a particular clientConfig in the GUI */ class PeerPlotConfig { + private final static Log _log = new Log(PeerPlotConfig.class); /** where can we find the current state/data (either as a filename or a URL)? */ private String _location; /** what test are we defining the plot data for? */ @@ -90,7 +92,9 @@ class PeerPlotConfig { PlotSeriesConfig cfg = (PlotSeriesConfig)_averageSeriesConfigs.get(i); ordered.put(new Long(cfg.getPeriod()), cfg); } - ordered.put(new Long(minutes*60*1000), new PlotSeriesConfig(minutes*60*1000)); + Long period = new Long(minutes*60*1000); + if (!ordered.containsKey(period)) + ordered.put(period, new PlotSeriesConfig(minutes*60*1000)); List cfgs = Collections.synchronizedList(new ArrayList(ordered.size())); for (Iterator iter = ordered.values().iterator(); iter.hasNext(); ) @@ -244,6 +248,11 @@ class PeerPlotConfig { */ public PlotSeriesConfig(long period) { this(period, false, false, false, null); + if (period <= 0) { + _plotSendTime = true; + _plotReceiveTime = true; + _plotLostMessages = true; + } } diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfigPane.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfigPane.java index 8eb815740..226eb2df8 100644 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfigPane.java +++ b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfigPane.java @@ -195,10 +195,10 @@ class PeerPlotConfigPane extends JPanel implements PeerPlotConfig.UpdateListener _log.warn("Config for minutes " + _options[i]._durationMinutes + " was not found?"); continue; } - _log.debug("Refreshing view for minutes ["+ _options[i]._durationMinutes + "]: send [" + - _options[i]._send.isSelected() + "/" + cfg.getPlotSendTime() + "] recv [" + - _options[i]._recv.isSelected() + "/" + cfg.getPlotReceiveTime() + "] lost [" + - _options[i]._lost.isSelected() + "/" + cfg.getPlotLostMessages() + "]"); + //_log.debug("Refreshing view for minutes ["+ _options[i]._durationMinutes + "]: send [" + + // _options[i]._send.isSelected() + "/" + cfg.getPlotSendTime() + "] recv [" + + // _options[i]._recv.isSelected() + "/" + cfg.getPlotReceiveTime() + "] lost [" + + // _options[i]._lost.isSelected() + "/" + cfg.getPlotLostMessages() + "]"); _options[i]._send.setSelected(cfg.getPlotSendTime()); _options[i]._recv.setSelected(cfg.getPlotReceiveTime()); _options[i]._lost.setSelected(cfg.getPlotLostMessages()); @@ -289,13 +289,15 @@ class PeerPlotConfigPane extends JPanel implements PeerPlotConfig.UpdateListener if (g < 0) g = -g; int b = _rnd.nextInt(255); if (b < 0) b = -b; - _color.setBackground(new Color(r, g, b)); + //_color.setBackground(new Color(r, g, b)); + _color.setBackground(_background); _send.addActionListener(new UpdateListener(OptionLine.this, _durationMinutes)); _recv.addActionListener(new UpdateListener(OptionLine.this, _durationMinutes)); _lost.addActionListener(new UpdateListener(OptionLine.this, _durationMinutes)); _all.addActionListener(new UpdateListener(OptionLine.this, _durationMinutes)); _color.addActionListener(new ChooseColor(durationMinutes, _color)); + _color.setEnabled(false); } } @@ -318,22 +320,12 @@ class PeerPlotConfigPane extends JPanel implements PeerPlotConfig.UpdateListener */ public void actionPerformed(ActionEvent evt) { PeerPlotConfig.PlotSeriesConfig cfg = getConfig(_minutes); - if (cfg == null) { - _log.error("wtf, why is there no config for " + _minutes + "?"); - - List configs = _config.getAverageSeriesConfigs(); - for (int i = 0; i < configs.size(); i++) { - PeerPlotConfig.PlotSeriesConfig conf = (PeerPlotConfig.PlotSeriesConfig)configs.get(i); - _log.debug("We know about " + conf.getPeriod()); - } - return; - } cfg.getPlotConfig().disableEvents(); _log.debug("Updating data for minutes ["+ _line._durationMinutes + "]: send [" + _line._send.isSelected() + "/" + cfg.getPlotSendTime() + "] recv [" + _line._recv.isSelected() + "/" + cfg.getPlotReceiveTime() + "] lost [" + - _line._lost.isSelected() + "/" + cfg.getPlotLostMessages() + "]"); + _line._lost.isSelected() + "/" + cfg.getPlotLostMessages() + "]: config = " + cfg); boolean force = _line._all.isSelected(); cfg.setPlotSendTime(_line._send.isSelected() || force); diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/StaticPeerData.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/StaticPeerData.java index 9b1289578..e0b36b094 100644 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/StaticPeerData.java +++ b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/StaticPeerData.java @@ -91,7 +91,11 @@ class StaticPeerData extends PeerData { * @return milliseconds average, or -1 if we dont track that period */ public double getAverageSendTime(int period) { - return ((Integer)_averageSendTimes.get(new Integer(period))).doubleValue(); + Integer i = (Integer)_averageSendTimes.get(new Integer(period)); + if (i == null) + return -1; + else + return i.doubleValue(); } @@ -102,7 +106,11 @@ class StaticPeerData extends PeerData { * @return milliseconds average, or -1 if we dont track that period */ public double getAverageReceiveTime(int period) { - return ((Integer)_averageReceiveTimes.get(new Integer(period))).doubleValue(); + Integer i = (Integer)_averageReceiveTimes.get(new Integer(period)); + if (i == null) + return -1; + else + return i.doubleValue(); } /** @@ -112,7 +120,11 @@ class StaticPeerData extends PeerData { * @return number of lost messages in the period, or -1 if we dont track that period */ public double getLostMessages(int period) { - return ((Integer)_lostMessages.get(new Integer(period))).doubleValue(); + Integer i = (Integer)_lostMessages.get(new Integer(period)); + if (i == null) + return -1; + else + return i.doubleValue(); } /* (non-Javadoc)