summaryrefslogtreecommitdiff
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/IceGridGUI/Coordinator.java114
-rw-r--r--java/src/IceGridGUI/LiveDeployment/GraphView.java1252
-rw-r--r--java/src/IceGridGUI/LiveDeployment/MetricsViewEditor.java88
-rw-r--r--java/src/IceGridGUI/LiveDeployment/Node.java11
-rw-r--r--java/src/IceGridGUI/LiveDeployment/Root.java163
-rw-r--r--java/src/IceGridGUI/LiveDeployment/Server.java38
-rw-r--r--java/src/IceGridGUI/LiveDeploymentPane.java23
7 files changed, 1674 insertions, 15 deletions
diff --git a/java/src/IceGridGUI/Coordinator.java b/java/src/IceGridGUI/Coordinator.java
index 208093d2ab5..85993ae32da 100644
--- a/java/src/IceGridGUI/Coordinator.java
+++ b/java/src/IceGridGUI/Coordinator.java
@@ -66,6 +66,10 @@ import com.jgoodies.looks.plastic.PlasticLookAndFeel;
import IceGrid.*;
+import IceGridGUI.LiveDeployment.GraphView;
+import IceGridGUI.LiveDeployment.GraphView.GraphType;
+import IceGridGUI.LiveDeployment.GraphView.GraphCategory;
+
//
// This class coordinates the communications between the various objects
// that make up the IceGrid GUI.
@@ -346,6 +350,20 @@ public class Coordinator
_newTemplateMenu.add(_appActionsForMenu.get(IceGridGUI.Application.TreeNode.NEW_TEMPLATE_SERVER_ICEBOX));
_newTemplateMenu.add(_appActionsForMenu.get(IceGridGUI.Application.TreeNode.NEW_TEMPLATE_SERVICE));
+
+ //
+ // New Graph sub-menu
+ //
+ _newMenu.addSeparator();
+ _newGraphMenu = new JMenu("Graph");
+ _newGraphMenu.setEnabled(false);
+ _newMenu.add(_newGraphMenu);
+ _newGraphMenu.add(_newDispatchGraph);
+ _newGraphMenu.add(_newInvocationGraph);
+ _newGraphMenu.add(_newConnectionsGraph);
+ _newGraphMenu.add(_newThreadsGraph);
+ _newGraphMenu.add(_newBandwidthGraph);
+
fileMenu.addSeparator();
fileMenu.add(_login);
fileMenu.add(_logout);
@@ -1959,6 +1977,22 @@ public class Coordinator
{
public void actionPerformed(ActionEvent e)
{
+ if(_graphViews.size() > 0)
+ {
+ if(JOptionPane.YES_OPTION != JOptionPane.showConfirmDialog(getMainFrame(),
+ "Close all open Graph Views and logout?",
+ "Confirm logout",
+ JOptionPane.YES_NO_OPTION))
+ {
+ return;
+ }
+
+ java.util.List<GraphView> views = new java.util.ArrayList<GraphView>(_graphViews);
+ for(GraphView v : views)
+ {
+ v.close();
+ }
+ }
_sessionKeeper.logout(true);
}
};
@@ -1998,6 +2032,54 @@ public class Coordinator
"Release exclusive write access on the registry");
_releaseExclusiveWriteAccess.setEnabled(false);
+ _newDispatchGraph = new AbstractAction("Dispatch")
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ _graphViews.add(new GraphView(Coordinator.this, GraphType.TotalAverageGraphType,
+ GraphCategory.DispatchGraphCategory, "Operation Dispatch",
+ "Dispatch"));
+ }
+ };
+
+ _newInvocationGraph = new AbstractAction("Invocation")
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ _graphViews.add(new GraphView(Coordinator.this, GraphType.TotalAverageGraphType,
+ GraphCategory.InvocationsGraphCategory, "Remote Invocation",
+ "Invocation"));
+ }
+ };
+
+ _newConnectionsGraph = new AbstractAction("Connections")
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ _graphViews.add(new GraphView(Coordinator.this, GraphType.CurrentCountGraphType,
+ GraphCategory.ConnectionsGraphCategory, "Connections",
+ "Connection"));
+ }
+ };
+
+ _newThreadsGraph = new AbstractAction("Threads")
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ _graphViews.add(new GraphView(Coordinator.this, GraphType.CurrentCountGraphType,
+ GraphCategory.ThreadsGraphCategory, "Threads", "Thread"));
+ }
+ };
+
+ _newBandwidthGraph = new AbstractAction("Bandwidth")
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ _graphViews.add(new GraphView(Coordinator.this, GraphType.BandwidhGraphType,
+ GraphCategory.BandwidthGraphCategory, "Bandwidth", "Connection"));
+ }
+ };
+
_showLiveDeploymentFilters = new AbstractAction("Filter live deployment")
{
public void actionPerformed(ActionEvent e)
@@ -2530,6 +2612,23 @@ public class Coordinator
void exit(int status)
{
+ if(_graphViews.size() > 0)
+ {
+ if(JOptionPane.YES_OPTION != JOptionPane.showConfirmDialog(getMainFrame(),
+ "Close all open windows and exit?",
+ "Confirm exit",
+ JOptionPane.YES_NO_OPTION))
+ {
+ return;
+ }
+
+ java.util.List<GraphView> views = new java.util.ArrayList<GraphView>(_graphViews);
+ for(GraphView v : views)
+ {
+ v.close();
+ }
+ }
+
if(_openChooser != null)
{
File dir = _openChooser.getCurrentDirectory();
@@ -2702,6 +2801,11 @@ public class Coordinator
_serviceMenu.setEnabled(false);
}
+ public void removeGraphView(GraphView view)
+ {
+ _graphViews.remove(view);
+ }
+
public boolean traceObservers()
{
return _traceObservers;
@@ -2726,6 +2830,7 @@ public class Coordinator
{
_connected = connected;
_statusBar.setConnected(connected);
+ _newGraphMenu.setEnabled(connected);
}
public boolean connected()
@@ -2791,6 +2896,12 @@ public class Coordinator
private Action _acquireExclusiveWriteAccess;
private Action _releaseExclusiveWriteAccess;
+ private Action _newDispatchGraph;
+ private Action _newInvocationGraph;
+ private Action _newConnectionsGraph;
+ private Action _newThreadsGraph;
+ private Action _newBandwidthGraph;
+
private Action _showLiveDeploymentFilters;
private Action _openApplicationFromFile;
private Action _openApplicationFromRegistry;
@@ -2841,6 +2952,7 @@ public class Coordinator
private JMenu _newServerMenu;
private JMenu _newServiceMenu;
private JMenu _newTemplateMenu;
+ private JMenu _newGraphMenu;
private JMenu _appMenu;
private JMenu _nodeMenu;
private JMenu _registryMenu;
@@ -2858,5 +2970,7 @@ public class Coordinator
private String _fileParser;
private boolean _connected;
+ private java.util.List<GraphView> _graphViews = new java.util.ArrayList<GraphView>();
+
static private final int HISTORY_MAX_SIZE = 20;
}
diff --git a/java/src/IceGridGUI/LiveDeployment/GraphView.java b/java/src/IceGridGUI/LiveDeployment/GraphView.java
new file mode 100644
index 00000000000..c8f89c909ad
--- /dev/null
+++ b/java/src/IceGridGUI/LiveDeployment/GraphView.java
@@ -0,0 +1,1252 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2012 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceGridGUI.LiveDeployment;
+
+import java.util.Map;
+import java.util.List;
+import java.util.HashMap;
+import java.util.ArrayList;
+
+import java.util.Date;
+import java.util.TimeZone;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Font;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.BorderFactory;
+
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSpinner;
+import javax.swing.JTable;
+import javax.swing.JOptionPane;
+import javax.swing.KeyStroke;
+import javax.swing.SwingUtilities;
+import javax.swing.SpinnerNumberModel;
+import javax.swing.SwingConstants;
+
+import javax.swing.table.DefaultTableModel;
+
+import javafx.application.Platform;
+
+import javafx.embed.swing.JFXPanel;
+
+import javafx.scene.chart.LineChart;
+import javafx.scene.chart.NumberAxis;
+import javafx.scene.chart.XYChart;
+
+import javafx.scene.control.cell.PropertyValueFactory;
+import javafx.scene.control.cell.TextFieldTableCell;
+
+import javafx.scene.Scene;
+
+import javafx.util.StringConverter;
+
+import com.jgoodies.forms.layout.FormLayout;
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.factories.Borders;
+import com.jgoodies.forms.builder.ButtonBarBuilder;
+
+import IceGrid.*;
+import IceGridGUI.*;
+
+public class GraphView extends JFrame
+{
+
+ public enum GraphCategory
+ {
+ DispatchGraphCategory,
+ InvocationsGraphCategory,
+ ConnectionsGraphCategory,
+ ThreadsGraphCategory,
+ BandwidthGraphCategory
+ }
+
+ public enum GraphType
+ {
+ TotalAverageGraphType,
+ CurrentCountGraphType,
+ BandwidhGraphType
+ }
+
+ class TimeFormatter extends StringConverter<java.lang.Number>
+ {
+ TimeFormatter()
+ {
+ _dateFormat.setTimeZone(TimeZone.getDefault());
+ }
+
+ @Override
+ public synchronized String toString(Number timestamp)
+ {
+ Date date = new Date(timestamp.longValue());
+ if(date.getTime() < 1000)
+ {
+ //
+ // When the x axis is first draw we don't have times to display.
+ //
+ return "";
+ }
+ else
+ {
+ return _dateFormat.format(date);
+ }
+ }
+
+ @Override
+ public synchronized Number fromString(String time)
+ {
+ try
+ {
+ long t = _dateFormat.parse(time).getTime();
+ return t;
+ }
+ catch(java.text.ParseException e)
+ {
+ return 0;
+ }
+ }
+
+ public synchronized void setDateFormat(String format)
+ {
+ _dateFormat = new SimpleDateFormat(format);
+ }
+
+ private DateFormat _dateFormat = new SimpleDateFormat(getDateFormat());
+ }
+
+ class TransferHandler extends javax.swing.TransferHandler
+ {
+ @Override
+ public boolean
+ canImport(TransferHandler.TransferSupport support)
+ {
+ boolean supported = false;
+ for(DataFlavor f : support.getDataFlavors())
+ {
+ if(f.getMimeType().equals(NodeMimeType) || f.getMimeType().equals(ServerMimeType) ||
+ f.getMimeType().equals(MetricsViewMimeType))
+ {
+ supported = true;
+ break;
+ }
+ }
+ return supported;
+ }
+
+ @Override
+ public boolean
+ importData(TransferHandler.TransferSupport support)
+ {
+ if(!canImport(support))
+ {
+ return false;
+ }
+
+ Transferable t = support.getTransferable();
+
+ for(DataFlavor flavor : support.getDataFlavors())
+ {
+ try
+ {
+ if(flavor.getMimeType().equals(NodeMimeType))
+ {
+ Node node = (Node)t.getTransferData(flavor);
+ importNode(node);
+ break;
+ }
+ else if(flavor.getMimeType().equals(ServerMimeType))
+ {
+ Server server = (Server)t.getTransferData(flavor);
+ importServer(server);
+ break;
+ }
+ else if(flavor.getMimeType().equals(MetricsViewMimeType))
+ {
+ MetricsView metricsView = (MetricsView)t.getTransferData(flavor);
+ importMetricsView(metricsView);
+ break;
+ }
+ }
+ catch(UnsupportedFlavorException ex)
+ {
+ }
+ catch(java.io.IOException ex)
+ {
+ }
+ }
+
+ return true;
+ }
+ }
+
+ private void importNode(Node node)
+ {
+ List<Server> servers = node.getServers();
+ for(Server s : servers)
+ {
+ importServer(s);
+ }
+ }
+
+ private void importServer(Server server)
+ {
+ List<MetricsView> metrics = server.getMetrics();
+ for(MetricsView m : metrics)
+ {
+ importMetricsView(m);
+ }
+ }
+
+ private void importMetricsView(MetricsView metricsView)
+ {
+ Server server = (Server)metricsView.getParent();
+ Node node = (Node)server.getParent();
+ MetricsViewInfo s = new MetricsViewInfo(node.getId(), server.getId(), metricsView.getId());
+ if(!_metrics.contains(s))
+ {
+ if(_metrics.size() == 0)
+ {
+ startRefreshThread();
+ }
+ _metrics.add(s);
+ addSeries(s, metricsView.data().get(_key));
+ }
+ }
+
+ class MetricsViewTargetInfo
+ {
+ MetricsViewTargetInfo(MetricsViewInfo parent, String id)
+ {
+ this.parent = parent;
+ this.id = id;
+ this.total = 0;
+ this.totalLifetime = 0;
+ }
+
+ @Override
+ public boolean equals(Object other)
+ {
+ if(other == null)
+ {
+ return false;
+ }
+ else if(other == this)
+ {
+ return true;
+ }
+ else if(!(other instanceof MetricsViewTargetInfo))
+ {
+ return false;
+ }
+ MetricsViewTargetInfo that = (MetricsViewTargetInfo)other;
+ return this.parent.equals(that.parent) && this.id.equals(that.id);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return IceInternal.HashUtil.hashAdd(parent.hashCode(), id);
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append(parent.toString());
+ sb.append(" - ");
+ sb.append(id);
+ return sb.toString();
+ }
+
+ public String id;
+ public MetricsViewInfo parent;
+ //
+ // Totals from last delta.
+ //
+ public long total;
+ public long totalLifetime;
+ };
+
+ class BandwidhMetricsInfo extends MetricsViewTargetInfo
+ {
+ BandwidhMetricsInfo(MetricsViewInfo parent, String id, boolean in)
+ {
+ super(parent, id);
+ this.in = in;
+ }
+
+ @Override public boolean
+ equals(Object other)
+ {
+ if(other == null)
+ {
+ return false;
+ }
+ else if(other == this)
+ {
+ return true;
+ }
+ else if(!(other instanceof BandwidhMetricsInfo))
+ {
+ return false;
+ }
+ BandwidhMetricsInfo that = (BandwidhMetricsInfo)other;
+ return super.equals(that) && this.in == that.in;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return IceInternal.HashUtil.hashAdd(super.hashCode(), in);
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append(super.toString());
+ sb.append(" - ");
+ sb.append((in ? "bytes received" : "bytes sent"));
+ return sb.toString();
+ }
+
+ public boolean in;
+ };
+
+ public class MetricsViewInfo
+ {
+ MetricsViewInfo(String node, String server, String view)
+ {
+ this.node = node;
+ this.server = server;
+ this.view = view;
+ }
+
+ @Override
+ public boolean equals(Object other)
+ {
+ if(other == null)
+ {
+ return false;
+ }
+ else if(other == this)
+ {
+ return true;
+ }
+ else if(!(other instanceof MetricsViewInfo))
+ {
+ return false;
+ }
+ MetricsViewInfo that = (MetricsViewInfo)other;
+ return this.node.equals(that.node) && this.server.equals(that.server) && this.view.equals(that.view);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int h = IceInternal.HashUtil.hashAdd(5381, node);
+ h = IceInternal.HashUtil.hashAdd(h, server);
+ return IceInternal.HashUtil.hashAdd(h, view);
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append(node);
+ sb.append(" - ");
+ sb.append(server);
+ sb.append(" - ");
+ sb.append(view);
+ return sb.toString();
+ }
+
+ public String node;
+ public String server;
+ public String view;
+ }
+
+ public class DeltaInfo
+ {
+ public DeltaInfo(long total, long totalLifetime)
+ {
+ this.total = total;
+ this.totalLifetime = totalLifetime;
+ }
+
+ public long total;
+ public long totalLifetime;
+ }
+
+ private class RefreshThread extends Thread
+ {
+ RefreshThread(long period)
+ {
+ _period = period;
+ _done = false;
+ }
+
+ synchronized void setRefreshPeriod(long period)
+ {
+ _period = period;
+ }
+
+ synchronized long getRefreshPeriod()
+ {
+ return _period;
+ }
+
+ synchronized public void
+ run()
+ {
+ while(true)
+ {
+ ArrayList<MetricsViewInfo> metrics = null;
+ synchronized(GraphView.this)
+ {
+ metrics = new ArrayList<MetricsViewInfo>(_metrics);
+ }
+ for(final MetricsViewInfo m : metrics)
+ {
+ Ice.Identity adminId = new Ice.Identity(m.server, _coordinator.getServerAdminCategory());
+ Ice.ObjectPrx admin = _coordinator.getAdmin().ice_identity(adminId);
+ IceMX.Callback_MetricsAdmin_getMetricsView cb = new IceMX.Callback_MetricsAdmin_getMetricsView()
+ {
+ public void response(final java.util.Map<java.lang.String, IceMX.Metrics[]> data)
+ {
+ addDelta(m, data, System.currentTimeMillis());
+ }
+
+ public void exception(final Ice.LocalException e)
+ {
+ // XXX
+ }
+
+ public void exception(final Ice.UserException e)
+ {
+ // XXX
+ }
+ };
+ try
+ {
+ IceMX.MetricsAdminPrx metricsAdmin =
+ IceMX.MetricsAdminPrxHelper.uncheckedCast(admin.ice_facet("MetricsAdmin"));
+ metricsAdmin.begin_getMetricsView(m.view, cb);
+ }
+ catch(Ice.LocalException e)
+ {
+ // XXX
+ }
+ }
+ if(!_done)
+ {
+ try
+ {
+ wait(getRefreshPeriod());
+ }
+ catch(InterruptedException ex)
+ {
+ }
+ }
+
+ if(_done)
+ {
+ break;
+ }
+ }
+ }
+
+ synchronized public void
+ done()
+ {
+ if(!_done)
+ {
+ _done = true;
+ notify();
+ }
+ }
+
+ private long _period;
+ private boolean _done = false;
+ }
+
+ public GraphView(Coordinator coordinator, GraphType type, GraphCategory category, final String title, String key)
+ {
+ _coordinator = coordinator;
+ _type = type;
+ _category = category;
+ setTitle(title);
+ _key = key;
+
+ //
+ // Don't destroy JavaFX when the frame is disposed.
+ //
+ Platform.setImplicitExit(false);
+
+ setIconImage(Utils.getIcon("/icons/16x16/grid.png").getImage());
+
+ setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+
+ addWindowListener(new WindowAdapter()
+ {
+ public void windowClosing(WindowEvent e)
+ {
+ close();
+ }
+ });
+
+ //
+ // Create actions
+ //
+ Action removeMetrics = new AbstractAction("Remove Metrics")
+ {
+ public void actionPerformed(ActionEvent event)
+ {
+ final DefaultTableModel model = new DefaultTableModel()
+ {
+ public Class getColumnClass(int column)
+ {
+ if(column == 3)
+ {
+ return Boolean.class;
+ }
+ else
+ {
+ return String.class;
+ }
+ }
+
+ public boolean isCellEditable(int row, int column)
+ {
+ return column == 3;
+ }
+ };
+ model.addColumn("Node");
+ model.addColumn("Server");
+ model.addColumn("View");
+ model.addColumn("Show");
+
+ for(MetricsViewInfo m : _metrics)
+ {
+ model.addRow(new Object[]{m.node, m.server, m.view, true});
+ }
+
+ JTable table = new JTable(model);
+ table.setPreferredSize(new Dimension(450, 300));
+ table.setPreferredScrollableViewportSize(table.getPreferredSize());
+ table.setCellSelectionEnabled(false);
+ table.setOpaque(false);
+ JScrollPane scrollPane = new JScrollPane(table);
+
+ JOptionPane.showMessageDialog(GraphView.this, scrollPane, "Select Servers",
+ JOptionPane.PLAIN_MESSAGE);
+
+ for(int i = 0; i < model.getRowCount(); ++i)
+ {
+ //
+ // Remove unselected metrics from the graph.
+ //
+ boolean selected = ((Boolean)model.getValueAt(i, 3)).booleanValue();
+ if(!selected)
+ {
+ MetricsViewInfo serverData = new MetricsViewInfo((String)model.getValueAt(i, 0),
+ (String)model.getValueAt(i, 1),
+ (String)model.getValueAt(i, 2));
+ _metrics.remove(serverData);
+ if(_metrics.size() == 0)
+ {
+ stopRefreshThread();
+ }
+ removeSeries(serverData);
+ }
+ }
+ }
+ };
+ removeMetrics.setEnabled(true);
+
+ //
+ // Graph preferences.
+ //
+ Action preferences = new AbstractAction("Preferences")
+ {
+ public void actionPerformed(ActionEvent event)
+ {
+ //
+ // SpinnerNumberModel to set a refresh period.
+ //
+ // min value is 500 ms == 0.5 seconds
+ // max value is 60 * 1000 ms == 60 seconds == 1 minute
+ //
+ SpinnerNumberModel refreshPeriod = new SpinnerNumberModel(getRefreshPeriod(), 500, 60 * 1000, 1);
+ JPanel refreshPanel;
+ {
+ DefaultFormBuilder builder =
+ new DefaultFormBuilder(new FormLayout("pref,2dlu,pref:grow", "pref"));
+ builder.append("Refresh period (ms):", new JSpinner(refreshPeriod));
+ refreshPanel = builder.getPanel();
+ }
+
+ //
+ // SpinnerNumberModel to set the number of symbols to keep in X axis.
+ //
+ // min value is 10
+ // max value is 100
+ //
+ SpinnerNumberModel horizontalAxisSymbolCount =
+ new SpinnerNumberModel(_horizontaSymbolsCount, 5, 100, 1);
+
+ //
+ // JComboBox to select time format used in X Axis
+ //
+ JComboBox<String> dateFormats = new JComboBox<String>(_dateFormats);
+ dateFormats.setSelectedItem(getDateFormat());
+ JPanel xAxisPanel;
+ {
+ DefaultFormBuilder builder =
+ new DefaultFormBuilder(new FormLayout("pref,2dlu,pref:grow", "pref"));
+ builder.append("Number of horizontal symbols:", new JSpinner(horizontalAxisSymbolCount));
+ builder.append("Time format:", dateFormats);
+
+ xAxisPanel = builder.getPanel();
+ }
+
+ //
+ // JComboBox to select Y Axis units.
+ //
+ JComboBox<String> units = null;
+ JPanel yAxisPanel = null;
+ if(_type == GraphType.BandwidhGraphType || _type == GraphType.TotalAverageGraphType)
+ {
+ if(_type == GraphType.BandwidhGraphType)
+ {
+ units = new JComboBox<String>(_bandwidthUnits);
+ units.setSelectedIndex(getBandwidthUnitIndex());
+ }
+ else
+ {
+ units = new JComboBox<String>(_timeUnits);
+ units.setSelectedIndex(getTimeUnitIndex());
+ }
+
+
+ {
+ DefaultFormBuilder builder =
+ new DefaultFormBuilder(new FormLayout("pref,2dlu,pref:grow", "pref"));
+ builder.append("Units:", units);
+ yAxisPanel = builder.getPanel();
+ }
+ }
+
+ FormLayout layout = new FormLayout("fill:pref:grow", "pref");
+ final DefaultFormBuilder builder = new DefaultFormBuilder(layout);
+ builder.border(Borders.DIALOG);
+ builder.appendSeparator("Refresh Thread");
+ builder.append(refreshPanel);
+ builder.nextLine();
+ builder.appendSeparator("Horizontal Axis");
+ builder.append(xAxisPanel);
+ if(yAxisPanel != null)
+ {
+ builder.appendSeparator("Vertical Axis");
+ builder.append(yAxisPanel);
+ }
+
+ class PreferencesDialog extends JDialog
+ {
+ PreferencesDialog(JFrame owner)
+ {
+ super(owner, true);
+ setTitle("Graph Preferences");
+ setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+
+ JButton okButton = new JButton("OK");
+ ActionListener okListener = new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ _option = JOptionPane.OK_OPTION;
+ setVisible(false);
+ dispose();
+ }
+ };
+
+ ActionListener cancelListener = new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ setVisible(false);
+ dispose();
+ }
+ };
+
+ okButton.addActionListener(okListener);
+ getRootPane().setDefaultButton(okButton);
+ KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
+ getRootPane().registerKeyboardAction(cancelListener, stroke,
+ JComponent.WHEN_IN_FOCUSED_WINDOW);
+
+ final JComponent buttonBar = new ButtonBarBuilder().addGlue()
+ .addButton(okButton)
+ .addGlue().build();
+ buttonBar.setBorder(Borders.DIALOG);
+
+ Container contentPane = getContentPane();
+ contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
+ contentPane.add(builder.getPanel());
+ contentPane.add(buttonBar);
+ pack();
+ setResizable(false);
+ setLocationRelativeTo(owner);
+ }
+
+ int showDialog()
+ {
+ setVisible(true);
+ return _option;
+ }
+
+ private int _option = JOptionPane.CLOSED_OPTION;
+ };
+ //
+ // Disabled the default dialog action, so we can use Enter for commit table cells edit.
+ //
+ PreferencesDialog dialog = new PreferencesDialog(GraphView.this);
+
+ if(dialog.showDialog() != JOptionPane.OK_OPTION)
+ {
+ return;
+ }
+ setRefreshPeriod(refreshPeriod.getNumber().longValue());
+ setHorizontalSymbolsCount(horizontalAxisSymbolCount.getNumber().intValue());
+ setDateFormat((String)dateFormats.getSelectedItem());
+ if((_type == GraphType.BandwidhGraphType && getBandwidthUnitIndex() != units.getSelectedIndex()) ||
+ _type == GraphType.TotalAverageGraphType && getTimeUnitIndex() != units.getSelectedIndex())
+ {
+ final int index = units.getSelectedIndex();
+ final float cf = conversionFactor(index);
+ final String label = yAxisLabel(index);
+
+ if(_type == GraphType.BandwidhGraphType)
+ {
+ setBandwidthUnitIndex(index);
+ }
+ else
+ {
+ setTimeUnitIndex(index);
+ }
+
+ //
+ // Update the graph in JavaFX thread.
+ //
+ Platform.runLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ _yAxis.setLabel(label);
+ for(XYChart.Series<Number, Number> series : _chart.getData())
+ {
+ for(XYChart.Data<Number, Number> item : series.getData())
+ {
+ item.setYValue(item.getYValue().floatValue() * cf);
+ }
+ }
+ }
+ });
+ }
+ }
+ };
+
+ //
+ // Create menus
+ //
+ JMenuBar menuBar = new JMenuBar();
+
+ // Create a menu
+ JMenu fileMenu = new JMenu("File");
+ fileMenu.setMnemonic(java.awt.event.KeyEvent.VK_F);
+ fileMenu.add(removeMetrics);
+ fileMenu.add(preferences);
+ menuBar.add(fileMenu);
+
+ setJMenuBar(menuBar);
+
+ JLabel dropTarget = new JLabel("Drop runtime components here to add it to the graph.");
+ dropTarget.setBorder(new CompoundBorder(BorderFactory.createLineBorder(java.awt.Color.gray, 5, true),
+ new EmptyBorder(20, 20, 20, 20)));
+ dropTarget.setHorizontalAlignment(SwingConstants.CENTER);
+ Font f = dropTarget.getFont();
+ dropTarget.setFont(f.deriveFont(f.getStyle(), f.getSize() + 8));
+ dropTarget.setTransferHandler(new TransferHandler());
+
+
+ final JFXPanel fxPanel = new JFXPanel();
+ DefaultFormBuilder builder = new DefaultFormBuilder(new FormLayout("fill:pref:grow", "fill:pref:grow, pref"));
+ builder.append(fxPanel);
+ builder.nextLine();
+ builder.append(dropTarget);
+ builder.nextLine();
+
+ JPanel panel = builder.getPanel();
+ panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+ setContentPane(panel);
+ setPreferredSize(new Dimension(800, 600));
+ pack();
+ //
+ // initialize the scene in JavaFX thread.
+ //
+ Platform.runLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ _xAxis = new NumberAxis();
+ _yAxis = new NumberAxis();
+ _chart = new LineChart<Number, Number>(_xAxis, _yAxis);
+
+ _xAxis.setLabel("Time (HH:mm:ss)");
+ _xAxis.setTickLabelFormatter(_timeFormater);
+ _xAxis.setForceZeroInRange(false);
+ _yAxis.setLabel(yAxisLabel(getUnitsSelectedIndex()));
+ _chart.setTitle(title);
+ _chart.setAnimated(true);
+ fxPanel.setScene(new Scene(_chart));
+ }
+ });
+ setLocationRelativeTo(_coordinator.getMainFrame());
+ setVisible(true);
+ }
+
+ public void close()
+ {
+ stopRefreshThread();
+ setVisible(false);
+ _coordinator.removeGraphView(GraphView.this);
+ dispose();
+ }
+
+ synchronized private void startRefreshThread()
+ {
+ if(_refreshThread == null)
+ {
+ _refreshThread = new RefreshThread(getRefreshPeriod());
+ _refreshThread.start();
+ }
+ }
+
+ synchronized private void stopRefreshThread()
+ {
+ if(_refreshThread != null)
+ {
+ _refreshThread.done();
+ _refreshThread = null;
+ }
+ }
+
+ synchronized private void setHorizontalSymbolsCount(int count)
+ {
+ _horizontaSymbolsCount = count;
+ }
+
+ synchronized private int getHorizontalSymbolsCount()
+ {
+ return _horizontaSymbolsCount;
+ }
+
+ void addDelta(MetricsViewInfo info, java.util.Map<java.lang.String, IceMX.Metrics[]> data,
+ final long timestamp)
+ {
+ IceMX.Metrics[] metrics = data.get(_key);
+ Map<MetricsViewTargetInfo, XYChart.Series<Number, Number>> seriesSeq = _series.get(info);
+ if(seriesSeq == null)
+ {
+ return;
+ }
+
+ if(metrics != null)
+ {
+ if(_type == GraphType.TotalAverageGraphType)
+ {
+ for(IceMX.Metrics m : metrics)
+ {
+ MetricsViewTargetInfo targetInfo = new MetricsViewTargetInfo(info, m.id);
+ XYChart.Series<Number, Number> series = seriesSeq.get(targetInfo);
+ if(series == null)
+ {
+ continue;
+ }
+
+ float value = 0;
+ DeltaInfo delta = _deltas.get(targetInfo);
+ if(delta == null)
+ {
+ delta = new DeltaInfo(m.total, m.totalLifetime);
+ _deltas.put(targetInfo, delta);
+ continue; // We need two meassurements to calculate delta AVG.
+ }
+ long deltaTotal = (m.total - delta.total);
+ value = deltaTotal == 0 ? 0.0f :
+ (m.totalLifetime - delta.totalLifetime) / deltaTotal;
+ delta.total = m.total;
+ delta.totalLifetime = m.totalLifetime;
+ addDelta(series, timestamp, value * _timeUnitsFactors[getTimeUnitIndex()]);
+ }
+ }
+ else if(_type == GraphType.CurrentCountGraphType)
+ {
+ for(IceMX.Metrics m : metrics)
+ {
+ MetricsViewTargetInfo targetInfo = new MetricsViewTargetInfo(info, m.id);
+ XYChart.Series<Number, Number> series = seriesSeq.get(targetInfo);
+ if(series == null)
+ {
+ continue;
+ }
+ float value = 0;
+ value = m.current;
+ addDelta(series, timestamp, value);
+ }
+ }
+ else if(_type == GraphType.BandwidhGraphType)
+ {
+ for(IceMX.Metrics m : metrics)
+ {
+ IceMX.ConnectionMetrics cm = (IceMX.ConnectionMetrics)m;
+ for(boolean in : new boolean[]{true, false})
+ {
+ MetricsViewTargetInfo targetInfo = new BandwidhMetricsInfo(info, m.id, in);
+ XYChart.Series<Number, Number> series = seriesSeq.get(targetInfo);
+ if(series == null)
+ {
+ continue;
+ }
+
+ float value = 0;
+ DeltaInfo delta = _deltas.get(targetInfo);
+ if(delta == null)
+ {
+ if(in)
+ {
+ delta = new DeltaInfo(cm.receivedBytes, timestamp);
+ }
+ else
+ {
+ delta = new DeltaInfo(cm.sentBytes, timestamp);
+ }
+ _deltas.put(targetInfo, delta);
+ continue; // We need two meassurements to calculate delta AVG.
+ }
+
+ if(in)
+ {
+ boolean zero = (cm.receivedBytes - delta.total) == 0 ||
+ (timestamp - delta.totalLifetime) == 0;
+ value = zero ? 0.0f : (cm.receivedBytes - delta.total) /
+ (float)(timestamp - delta.totalLifetime);
+ delta.total = cm.receivedBytes;
+ delta.totalLifetime = timestamp;
+ }
+ else
+ {
+ boolean zero = (cm.sentBytes - delta.total) == 0 ||
+ (timestamp - delta.totalLifetime) == 0;
+ value = zero ? 0.0f : (cm.sentBytes - delta.total) /
+ (float)(timestamp - delta.totalLifetime);
+ delta.total = cm.sentBytes;
+ delta.totalLifetime = timestamp;
+ }
+ addDelta(series, timestamp, value * _bandwidthUnitsFactors[getBandwidthUnitIndex()]);
+ }
+ }
+ }
+ }
+ }
+
+ private void addDelta(final XYChart.Series<Number, Number> series, final long timestamp, final float value)
+ {
+ //
+ // Update the graph series in JavaFX thread.
+ //
+ Platform.runLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ series.getData().add(new XYChart.Data<Number, Number>(timestamp, value));
+ while(series.getData().size() > getHorizontalSymbolsCount())
+ {
+ series.getData().remove(0);
+ }
+ }
+ });
+ }
+
+ public void addSeries(final MetricsViewInfo info, final IceMX.Metrics[] data)
+ {
+ //
+ // Need to run in JavaFX thread.
+ //
+ Platform.runLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ if(data != null)
+ {
+ Map<MetricsViewTargetInfo, XYChart.Series<Number, Number>> seriesSeq = _series.get(info);
+ if(seriesSeq == null)
+ {
+ seriesSeq = new HashMap<MetricsViewTargetInfo, XYChart.Series<Number, Number>>();
+ _series.put(info, seriesSeq);
+ }
+
+ if(_category != GraphCategory.BandwidthGraphCategory)
+ {
+ for(IceMX.Metrics m : data)
+ {
+ MetricsViewTargetInfo targetInfo = new MetricsViewTargetInfo(info, m.id);
+ XYChart.Series<Number, Number> series = new XYChart.Series<Number, Number>();
+ series.setName(targetInfo.toString());
+ seriesSeq.put(targetInfo, series);
+ _chart.getData().add(series);
+ }
+ }
+ else
+ {
+ for(IceMX.Metrics m : data)
+ {
+ for(boolean in : new boolean[]{true, false})
+ {
+ MetricsViewTargetInfo targetInfo = new BandwidhMetricsInfo(info, m.id, in);
+ XYChart.Series<Number, Number> series = new XYChart.Series<Number, Number>();
+ series.setName(targetInfo.toString());
+ seriesSeq.put(targetInfo, series);
+ _chart.getData().add(series);
+ }
+ }
+ }
+ }
+ }
+ });
+ }
+
+ //
+ // Remove all series associated to a Metrics View
+ //
+ public void removeSeries(final MetricsViewInfo info)
+ {
+ //
+ // Need to run in JavaFX thread.
+ //
+ Platform.runLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ Map<MetricsViewTargetInfo, XYChart.Series<Number, Number>> seriesSeq = _series.get(info);
+ if(seriesSeq != null)
+ {
+ for(Map.Entry<MetricsViewTargetInfo, XYChart.Series<Number, Number>> entry :
+ seriesSeq.entrySet())
+ {
+ _chart.getData().remove(entry.getValue());
+ }
+ _series.remove(info);
+ }
+ }
+ });
+ }
+
+ synchronized long getRefreshPeriod()
+ {
+ return _refreshPeriod;
+ }
+
+ synchronized void setRefreshPeriod(long refreshPeriod)
+ {
+ _refreshPeriod = refreshPeriod;
+ if(_refreshThread != null)
+ {
+ _refreshThread.setRefreshPeriod(_refreshPeriod);
+ }
+ }
+
+ synchronized String getDateFormat()
+ {
+ return _dateFormat;
+ }
+
+ synchronized void setDateFormat(String dateFormat)
+ {
+ _dateFormat = dateFormat;
+ _timeFormater.setDateFormat(dateFormat);
+ }
+
+ synchronized String getBandwithUnit()
+ {
+ return _bandwidthUnits[_bandwidthUnitIndex];
+ }
+
+ synchronized int getBandwidthUnitIndex()
+ {
+ return _bandwidthUnitIndex;
+ }
+
+ synchronized void setBandwidthUnitIndex(int index)
+ {
+ _bandwidthUnitIndex = index;
+ }
+
+ synchronized String getTimeUnit()
+ {
+ return _timeUnits[_timeUnitIndex];
+ }
+
+ synchronized int getTimeUnitIndex()
+ {
+ return _timeUnitIndex;
+ }
+
+ synchronized void setTimeUnitIndex(int index)
+ {
+ _timeUnitIndex = index;
+ }
+
+ synchronized float conversionFactor(int index)
+ {
+ return _type == GraphType.BandwidhGraphType ?
+ _bandwidthUnitsFactors[index] / _bandwidthUnitsFactors[_bandwidthUnitIndex] :
+ _timeUnitsFactors[index] / _timeUnitsFactors[_timeUnitIndex];
+ }
+
+ synchronized String yAxisLabel(int index)
+ {
+ if(_type == GraphType.BandwidhGraphType)
+ {
+ return _bandwidthUnits[index];
+ }
+ else if(_type == GraphType.TotalAverageGraphType)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Average ");
+ if(_category == GraphCategory.DispatchGraphCategory)
+ {
+ sb.append("dispatch ");
+ }
+ else
+ {
+ sb.append("invocation ");
+ }
+ sb.append("time (");
+ sb.append(_timeUnits[index]);
+ sb.append(")");
+ return sb.toString();
+ }
+ else if(_category == GraphCategory.ThreadsGraphCategory)
+ {
+ return "Threads";
+ }
+ else if(_category == GraphCategory.ConnectionsGraphCategory)
+ {
+ return "Connections";
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ synchronized int getUnitsSelectedIndex()
+ {
+ if(_type == GraphType.BandwidhGraphType)
+ {
+ return _bandwidthUnitIndex;
+ }
+ else if(_type == GraphType.TotalAverageGraphType)
+ {
+ return _timeUnitIndex;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ private final Coordinator _coordinator;
+ private RefreshThread _refreshThread;
+ private final List<MetricsViewInfo> _metrics = new ArrayList<MetricsViewInfo>();
+ private Map<MetricsViewInfo, Map<MetricsViewTargetInfo, XYChart.Series<Number, Number>>> _series =
+ new HashMap<MetricsViewInfo, Map<MetricsViewTargetInfo, XYChart.Series<Number, Number>>>();
+
+ private Map<MetricsViewTargetInfo, DeltaInfo> _deltas = new HashMap<MetricsViewTargetInfo, DeltaInfo>();
+
+ private LineChart<Number, Number> _chart;
+ private final GraphCategory _category;
+ private final GraphType _type;
+ private final String _key;
+ private int _horizontaSymbolsCount = 10;
+
+ private long _refreshPeriod = 5000;
+
+ private String[] _dateFormats = new String[]{"HH:mm:ss", "mm:ss"};
+ private String _dateFormat = _dateFormats[0];
+
+ private String[] _bandwidthUnits = new String[]{"Bytes/s", "KBytes/s", "Bytes/min", "KBytes/min"};
+ private float[] _bandwidthUnitsFactors = new float[]{1000.0f, 1.0f, 60000.0f, 60.0f};
+ private int _bandwidthUnitIndex = 0;
+
+ private String[] _timeUnits = new String[]{"\u00B5s", "ms", "s"};
+ private float [] _timeUnitsFactors = new float[]{1.0f, 0.001f, 0.000001f};
+ private int _timeUnitIndex = 1;
+
+ final TimeFormatter _timeFormater = new TimeFormatter();
+ final Object _monitor = new Object();
+
+ NumberAxis _xAxis;
+ NumberAxis _yAxis;
+
+ private final static String NodeMimeType =
+ "application/x-java-jvm-local-objectref; class=IceGridGUI.LiveDeployment.Node";
+ private final static String ServerMimeType =
+ "application/x-java-jvm-local-objectref; class=IceGridGUI.LiveDeployment.Server";
+ private final static String MetricsViewMimeType =
+ "application/x-java-jvm-local-objectref; class=IceGridGUI.LiveDeployment.MetricsView";
+}
diff --git a/java/src/IceGridGUI/LiveDeployment/MetricsViewEditor.java b/java/src/IceGridGUI/LiveDeployment/MetricsViewEditor.java
index 30fa62270c3..2b2591d5b1d 100644
--- a/java/src/IceGridGUI/LiveDeployment/MetricsViewEditor.java
+++ b/java/src/IceGridGUI/LiveDeployment/MetricsViewEditor.java
@@ -323,13 +323,14 @@ class MetricsViewEditor extends Editor
for(int i = 0; i < values.length; ++i)
{
IceMX.InvocationMetrics o = (IceMX.InvocationMetrics)values[i];
- Object[] row = new Object[6];
+ Object[] row = new Object[7];
row[0] = o.id;
row[1] = Integer.toString(o.current);
row[2] = Long.toString(o.total);
row[3] = Integer.toString(o.retry);
row[4] = metricAvg(o, 1000.0f);
- row[5] = failures(key, node, o);
+ row[5] = remotes(o);
+ row[6] = failures(key, node, o);
_invocations.addRow(row);
}
}
@@ -471,6 +472,62 @@ class MetricsViewEditor extends Editor
}
});
}
+ else
+ {
+ button.setEnabled(false);
+ }
+ return button;
+
+ }
+
+ private Object remotes(final IceMX.InvocationMetrics o)
+ {
+ JButton button = new JButton("Show Remotes (" + Integer.toString(o.remotes.length) + ")");
+ button.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ final DefaultTableModel model = new DefaultTableModel();
+ model.addColumn("Identity");
+ model.addColumn("Current");
+ model.addColumn("Total");
+ model.addColumn("Avg (ms)");
+
+ JTable table = new JTable(model);
+ table.setPreferredSize(new Dimension(550, 200));
+ table.setPreferredScrollableViewportSize(table.getPreferredSize());
+ table.setCellSelectionEnabled(false);
+ table.setOpaque(false);
+
+ for(int i = 0; i < o.remotes.length; ++i)
+ {
+ IceMX.Metrics ro = o.remotes[i];
+ Object[] row = new Object[5];
+ row[0] = ro.id;
+ row[1] = Integer.toString(ro.current);
+ row[2] = Long.toString(ro.total);
+ row[3] = metricAvg(ro, 1000.0f);
+ model.addRow(row);
+ }
+
+ DefaultTableCellRenderer cr = (DefaultTableCellRenderer)table.getDefaultRenderer(String.class);
+ cr.setOpaque(false);
+
+ DefaultTableCellRenderer rr = new DefaultTableCellRenderer();
+ for(int i = 1; i < model.getColumnCount(); ++i)
+ {
+ rr.setHorizontalAlignment(SwingConstants.RIGHT);
+ rr.setOpaque(false);
+ table.getColumnModel().getColumn(i).setCellRenderer(rr);
+ }
+ JScrollPane scrollPane = new JScrollPane(table);
+
+ JOptionPane.showMessageDialog(_node.getCoordinator().getMainFrame(),
+ scrollPane,
+ "Invocation Remotes",
+ JOptionPane.PLAIN_MESSAGE );
+ }
+ });
return button;
}
@@ -479,11 +536,11 @@ class MetricsViewEditor extends Editor
{
createScrollTable(builder, "Operation Dispatch", _dispatColumnNames, _dispatch);
- createScrollTable(builder, "Application Connections", _connectionsColumnNames, _connections);
+ createScrollTable(builder, "Connections", _connectionsColumnNames, _connections);
createScrollTable(builder, "Remote Invocations", _invocationsColumnNames, _invocations);
- createScrollTable(builder, "Application Threads", _threadsColumnNames, _threads);
+ createScrollTable(builder, "Threads", _threadsColumnNames, _threads);
createScrollTable(builder, "Connection Establishments", _connectionsEstablishmentsColumnNames,
_connectionsEstablishments);
@@ -523,16 +580,26 @@ class MetricsViewEditor extends Editor
DefaultTableCellRenderer cr = (DefaultTableCellRenderer)table.getDefaultRenderer(String.class);
cr.setOpaque(false);
+
+ DefaultTableCellRenderer br = new ButtonRenderer();
+ br.setOpaque(false);
+
DefaultTableCellRenderer rr = new DefaultTableCellRenderer();
rr.setHorizontalAlignment(SwingConstants.RIGHT);
rr.setOpaque(false);
- for(int i = 1; i < columnNames.length - 1; i++)
+
+ for(int i = 0; i < columnNames.length; ++i)
{
- table.getColumnModel().getColumn(i).setCellRenderer(rr);
+ String name = (String)columnNames[i];
+ if(name.equals("Remotes") || name.equals("Failures"))
+ {
+ table.getColumnModel().getColumn(i).setCellRenderer(br);
+ }
+ else if(!name.equals("Identity"))
+ {
+ table.getColumnModel().getColumn(i).setCellRenderer(rr);
+ }
}
- DefaultTableCellRenderer br = new ButtonRenderer();
- br.setOpaque(false);
- table.getColumnModel().getColumn(columnNames.length - 1).setCellRenderer(br);
}
protected void buildPropertiesPanel()
@@ -568,10 +635,11 @@ class MetricsViewEditor extends Editor
private DefaultTableModel _invocations = new TableModel();
private Object[] _invocationsColumnNames = new Object[]{"Identity", "Current", "Total", "Retries", "Avg (ms)",
- "Failures"};
+ "Remotes", "Failures"};
private DefaultTableModel _connectionsEstablishments = new TableModel();
private Object[] _connectionsEstablishmentsColumnNames = new Object[]{"Identity", "Current", "Total", "Avg (ms)",
"Failures"};
+
private MetricsView _node;
}
diff --git a/java/src/IceGridGUI/LiveDeployment/Node.java b/java/src/IceGridGUI/LiveDeployment/Node.java
index 41eda9e05d6..a7281332e6a 100644
--- a/java/src/IceGridGUI/LiveDeployment/Node.java
+++ b/java/src/IceGridGUI/LiveDeployment/Node.java
@@ -908,6 +908,17 @@ class Node extends ListTreeNode
Utils.Resolver resolver;
}
+ public java.util.List<Server>
+ getServers()
+ {
+ java.util.List<Server> servers = new java.util.ArrayList<Server>();
+ for(Object obj : _children)
+ {
+ servers.add((Server)obj);
+ }
+ return servers;
+ }
+
//
// Application name to ApplicationData
//
diff --git a/java/src/IceGridGUI/LiveDeployment/Root.java b/java/src/IceGridGUI/LiveDeployment/Root.java
index 09beac80bac..04cbdd43540 100644
--- a/java/src/IceGridGUI/LiveDeployment/Root.java
+++ b/java/src/IceGridGUI/LiveDeployment/Root.java
@@ -12,6 +12,10 @@ package IceGridGUI.LiveDeployment;
import java.awt.Component;
import java.awt.Cursor;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+
import javax.swing.Icon;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
@@ -21,6 +25,8 @@ import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
+import javax.swing.JComponent;
+
import java.util.Enumeration;
import java.util.prefs.Preferences;
@@ -153,6 +159,161 @@ public class Root extends ListArrayTreeNode
return _applicationNameFilter;
}
+ public class NodeTransferable implements Transferable
+ {
+ public NodeTransferable(IceGridGUI.LiveDeployment.Node node)
+ {
+ _node = node;
+ try
+ {
+ _flavors = new DataFlavor[]{new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType +
+ ";class=IceGridGUI.LiveDeployment.Node")};
+ }
+ catch(ClassNotFoundException ex)
+ {
+ }
+ }
+
+ public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException
+ {
+ if(!isDataFlavorSupported(flavor))
+ {
+ throw new UnsupportedFlavorException(flavor);
+ }
+ return _node;
+ }
+
+ public DataFlavor[] getTransferDataFlavors()
+ {
+ return _flavors;
+ }
+
+ public boolean isDataFlavorSupported(DataFlavor flavor)
+ {
+ return _flavors[0].equals(flavor);
+ }
+
+ private IceGridGUI.LiveDeployment.Node _node;
+ private DataFlavor[] _flavors;
+ }
+
+ public class ServerTransferable implements Transferable
+ {
+ public ServerTransferable(IceGridGUI.LiveDeployment.Server server)
+ {
+ _server = server;
+ try
+ {
+ _flavors = new DataFlavor[]{new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType +
+ ";class=IceGridGUI.LiveDeployment.Server")};
+ }
+ catch(ClassNotFoundException ex)
+ {
+ }
+ }
+
+ public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException
+ {
+ if(!isDataFlavorSupported(flavor))
+ {
+ throw new UnsupportedFlavorException(flavor);
+ }
+ return _server;
+ }
+
+ public DataFlavor[] getTransferDataFlavors()
+ {
+ return _flavors;
+ }
+
+ public boolean isDataFlavorSupported(DataFlavor flavor)
+ {
+ return _flavors[0].equals(flavor);
+ }
+
+ private IceGridGUI.LiveDeployment.Server _server;
+ private DataFlavor[] _flavors;
+ }
+
+ public class MetricsViewTransferable implements Transferable
+ {
+ public MetricsViewTransferable(IceGridGUI.LiveDeployment.MetricsView metricsView)
+ {
+ _metricsView = metricsView;
+ try
+ {
+ _flavors = new DataFlavor[]{new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType +
+ ";class=IceGridGUI.LiveDeployment.MetricsView")};
+ }
+ catch(ClassNotFoundException ex)
+ {
+ }
+ }
+
+ public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException
+ {
+ if(!isDataFlavorSupported(flavor))
+ {
+ throw new UnsupportedFlavorException(flavor);
+ }
+ return _metricsView;
+ }
+
+ public DataFlavor[] getTransferDataFlavors()
+ {
+ return _flavors;
+ }
+
+ public boolean isDataFlavorSupported(DataFlavor flavor)
+ {
+ return _flavors[0].equals(flavor);
+ }
+
+ private IceGridGUI.LiveDeployment.MetricsView _metricsView;
+ private DataFlavor[] _flavors;
+ }
+
+ class TransferHandler extends javax.swing.TransferHandler
+ {
+ @Override
+ public int
+ getSourceActions(JComponent component)
+ {
+ return javax.swing.TransferHandler.COPY;
+ }
+
+ @Override
+ public Transferable
+ createTransferable(JComponent component)
+ {
+ JTree tree = (JTree)component;
+ TreePath[] paths = tree.getSelectionPaths();
+ if(paths != null)
+ {
+ TreeNode node = (TreeNode)paths[0].getLastPathComponent();
+ if(node instanceof IceGridGUI.LiveDeployment.MetricsView)
+ {
+ return new MetricsViewTransferable((IceGridGUI.LiveDeployment.MetricsView)node);
+ }
+ else if(node instanceof IceGridGUI.LiveDeployment.Server)
+ {
+ return new ServerTransferable((IceGridGUI.LiveDeployment.Server)node);
+ }
+ else if(node instanceof IceGridGUI.LiveDeployment.Node)
+ {
+ return new NodeTransferable((IceGridGUI.LiveDeployment.Node)node);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected void exportDone(JComponent source, Transferable data, int action)
+ {
+ // Does nothing as we don't support move action.
+ }
+ }
+
public Root(Coordinator coordinator)
{
super(null, "Root", 2);
@@ -164,6 +325,8 @@ public class Root extends ListArrayTreeNode
_treeModel = new FilteredTreeModel(this);
_tree = new JTree();
_tree.setModel(_treeModel);
+ _tree.setDragEnabled(true);
+ _tree.setTransferHandler(new TransferHandler());
_addObjectDialog = new ObjectDialog(this, false);
_showObjectDialog = new ObjectDialog(this, true);
diff --git a/java/src/IceGridGUI/LiveDeployment/Server.java b/java/src/IceGridGUI/LiveDeployment/Server.java
index 8aeb48eae38..c141f83fdc3 100644
--- a/java/src/IceGridGUI/LiveDeployment/Server.java
+++ b/java/src/IceGridGUI/LiveDeployment/Server.java
@@ -26,7 +26,7 @@ import java.util.Enumeration;
import IceGrid.*;
import IceGridGUI.*;
-class Server extends ListArrayTreeNode
+public class Server extends ListArrayTreeNode
{
//
// Actions
@@ -82,7 +82,6 @@ class Server extends ListArrayTreeNode
public void response()
{
amiSuccess(prefix);
- fetchMetricsViewNames();
}
public void exception(Ice.UserException e)
@@ -113,7 +112,6 @@ class Server extends ListArrayTreeNode
public void stop()
{
- _metrics.clear();
final String prefix = "Stopping server '" + _id + "'...";
getCoordinator().getStatusBar().setText(prefix);
@@ -399,8 +397,14 @@ class Server extends ListArrayTreeNode
}
}
- void fetchMetricsViewNames()
+ public void fetchMetricsViewNames()
{
+ if(_metricsRetrieved)
+ {
+ return; // Already loaded.
+ }
+ _metricsRetrieved = true;
+
Ice.ObjectPrx admin = getServerAdmin();
if(admin == null)
{
@@ -707,7 +711,6 @@ class Server extends ListArrayTreeNode
createAdapters();
createDbEnvs();
createServices();
- fetchMetricsViewNames();
}
ApplicationDescriptor getApplication()
@@ -883,6 +886,20 @@ class Server extends ListArrayTreeNode
{
_stateIconIndex = _state.ordinal() + 1;
}
+
+ if(_state == ServerState.Active && getRoot().getTree().isExpanded(getPath()))
+ {
+ fetchMetricsViewNames();
+ }
+ else
+ {
+ _metricsRetrieved = false;
+ if(_metrics.size() > 0)
+ {
+ _metrics.clear();
+ rebuild(this);
+ }
+ }
if(_serverDescriptor instanceof IceBoxDescriptor)
{
@@ -1207,6 +1224,10 @@ class Server extends ListArrayTreeNode
Ice.ObjectPrx getServerAdmin()
{
+ if(_state != ServerState.Active)
+ {
+ return null;
+ }
AdminPrx admin = getCoordinator().getAdmin();
if(admin == null)
{
@@ -1235,6 +1256,12 @@ class Server extends ListArrayTreeNode
return result;
}
+ public java.util.List<MetricsView>
+ getMetrics()
+ {
+ return new java.util.ArrayList<MetricsView>(_metrics);
+ }
+
private ServerInstanceDescriptor _instanceDescriptor;
private java.util.Map<String, PropertySetDescriptor> _servicePropertySets =
new java.util.HashMap<String, PropertySetDescriptor>(); // with substituted names!
@@ -1256,6 +1283,7 @@ class Server extends ListArrayTreeNode
private int _stateIconIndex;
private int _pid;
private String _toolTip;
+ private boolean _metricsRetrieved = false;
private IceBox.ServiceObserverPrx _serviceObserver;
diff --git a/java/src/IceGridGUI/LiveDeploymentPane.java b/java/src/IceGridGUI/LiveDeploymentPane.java
index 70244d70299..8aac66e7a9b 100644
--- a/java/src/IceGridGUI/LiveDeploymentPane.java
+++ b/java/src/IceGridGUI/LiveDeploymentPane.java
@@ -26,6 +26,8 @@ import javax.swing.plaf.basic.BasicSplitPaneUI;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.tree.TreePath;
+import javax.swing.event.TreeWillExpandListener;
+import javax.swing.event.TreeExpansionEvent;
import com.jgoodies.forms.factories.Borders;
@@ -33,6 +35,7 @@ import IceGrid.*;
import IceGridGUI.LiveDeployment.Editor;
import IceGridGUI.LiveDeployment.Root;
import IceGridGUI.LiveDeployment.TreeNode;
+import IceGridGUI.LiveDeployment.Server;
public class LiveDeploymentPane extends JSplitPane implements Tab
{
@@ -217,6 +220,26 @@ public class LiveDeploymentPane extends JSplitPane implements Tab
tree.addTreeSelectionListener(new SelectionListener());
+ //
+ // Fetch metrics when Server node is expanded.
+ //
+ tree.addTreeWillExpandListener(
+ new TreeWillExpandListener()
+ {
+ public void treeWillExpand(TreeExpansionEvent evt)
+ {
+ TreeNode node = (TreeNode)evt.getPath().getLastPathComponent();
+ if(node instanceof Server)
+ {
+ ((Server)node).fetchMetricsViewNames();
+ }
+ }
+
+ public void treeWillCollapse(TreeExpansionEvent evt)
+ {
+ }
+ });
+
tree.setRootVisible(false);
JScrollPane leftScroll =