diff options
Diffstat (limited to 'java/src')
-rw-r--r-- | java/src/IceGridGUI/Coordinator.java | 114 | ||||
-rw-r--r-- | java/src/IceGridGUI/LiveDeployment/GraphView.java | 1252 | ||||
-rw-r--r-- | java/src/IceGridGUI/LiveDeployment/MetricsViewEditor.java | 88 | ||||
-rw-r--r-- | java/src/IceGridGUI/LiveDeployment/Node.java | 11 | ||||
-rw-r--r-- | java/src/IceGridGUI/LiveDeployment/Root.java | 163 | ||||
-rw-r--r-- | java/src/IceGridGUI/LiveDeployment/Server.java | 38 | ||||
-rw-r--r-- | java/src/IceGridGUI/LiveDeploymentPane.java | 23 |
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 = |