diff options
Diffstat (limited to 'java/src/IceGridGUI/LiveDeployment/Node.java')
-rw-r--r-- | java/src/IceGridGUI/LiveDeployment/Node.java | 926 |
1 files changed, 926 insertions, 0 deletions
diff --git a/java/src/IceGridGUI/LiveDeployment/Node.java b/java/src/IceGridGUI/LiveDeployment/Node.java new file mode 100644 index 00000000000..e0518effc23 --- /dev/null +++ b/java/src/IceGridGUI/LiveDeployment/Node.java @@ -0,0 +1,926 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 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.awt.Component; +import java.awt.Cursor; + +import javax.swing.Icon; +import javax.swing.JOptionPane; +import javax.swing.JPopupMenu; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreePath; + +import java.text.NumberFormat; + +import java.util.Enumeration; + +import IceGrid.*; +import IceGridGUI.*; + +class Node extends ListTreeNode +{ + // + // Actions + // + public boolean[] getAvailableActions() + { + boolean[] actions = new boolean[ACTION_COUNT]; + actions[SHUTDOWN_NODE] = _up; + actions[RETRIEVE_STDOUT] = _up; + actions[RETRIEVE_STDERR] = _up; + return actions; + } + + public void retrieveOutput(final boolean stdout) + { + getRoot().openShowLogDialog(new ShowLogDialog.FileIteratorFactory() + { + public FileIteratorPrx open(int count) + throws FileNotAvailableException, NodeNotExistException, NodeUnreachableException + { + AdminSessionPrx session = getRoot().getCoordinator().getSession(); + FileIteratorPrx result; + if(stdout) + { + result = session.openNodeStdOut(_id, count); + } + else + { + result = session.openNodeStdErr(_id, count); + } + return result; + } + + public String getTitle() + { + return "Node " + _id + " " + (stdout ? "stdout" : "stderr"); + } + + public String getDefaultFilename() + { + return _id + (stdout ? ".out" : ".err"); + } + }); + } + + public void shutdownNode() + { + final String prefix = "Shutting down node '" + _id + "'..."; + getCoordinator().getStatusBar().setText(prefix); + + AMI_Admin_shutdownNode cb = new AMI_Admin_shutdownNode() + { + // + // Called by another thread! + // + public void ice_response() + { + amiSuccess(prefix); + } + + public void ice_exception(Ice.UserException e) + { + amiFailure(prefix, "Failed to shutdown " + _id, e); + } + + public void ice_exception(Ice.LocalException e) + { + amiFailure(prefix, "Failed to shutdown " + _id, + e.toString()); + } + }; + + try + { + getCoordinator().getMainFrame().setCursor( + Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + + getCoordinator().getAdmin().shutdownNode_async(cb, _id); + } + catch(Ice.LocalException e) + { + failure(prefix, "Failed to shutdown " + _id, e.toString()); + } + finally + { + getCoordinator().getMainFrame().setCursor( + Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + } + + public JPopupMenu getPopupMenu() + { + LiveActions la = getCoordinator().getLiveActionsForPopup(); + + if(_popup == null) + { + _popup = new JPopupMenu(); + _popup.add(la.get(RETRIEVE_STDOUT)); + _popup.add(la.get(RETRIEVE_STDERR)); + _popup.addSeparator(); + _popup.add(la.get(SHUTDOWN_NODE)); + } + + la.setTarget(this); + return _popup; + } + + public Editor getEditor() + { + if(_editor == null) + { + _editor = new NodeEditor(); + } + _editor.show(this); + return _editor; + } + + public Component getTreeCellRendererComponent( + JTree tree, + Object value, + boolean sel, + boolean expanded, + boolean leaf, + int row, + boolean hasFocus) + { + if(_cellRenderer == null) + { + // + // Initialization + // + _cellRenderer = new DefaultTreeCellRenderer(); + _nodeUp = Utils.getIcon("/icons/16x16/node_up.png"); + _nodeDown = Utils.getIcon("/icons/16x16/node_down.png"); + } + + if(_up) + { + _cellRenderer.setToolTipText("Up and running"); + if(expanded) + { + _cellRenderer.setOpenIcon(_nodeUp); + } + else + { + _cellRenderer.setClosedIcon(_nodeUp); + } + } + else + { + _cellRenderer.setToolTipText("Not running"); + if(expanded) + { + _cellRenderer.setOpenIcon(_nodeDown); + } + else + { + _cellRenderer.setClosedIcon(_nodeDown); + } + } + + return _cellRenderer.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + } + + Node(Root parent, NodeDynamicInfo info) + { + super(parent, info.info.name); + up(info, false); + } + + Node(Root parent, ApplicationDescriptor appDesc, + String nodeName, NodeDescriptor nodeDesc) + { + super(parent, nodeName); + add(appDesc, nodeDesc); + } + + Node(Root parent, ApplicationDescriptor appDesc, NodeUpdateDescriptor update) + { + super(parent, update.name); + + NodeDescriptor nodeDesc = new NodeDescriptor( + update.variables, + update.serverInstances, + update.servers, + update.loadFactor == null ? "" : update.loadFactor.value, + update.description == null ? "" : update.description.value, + update.propertySets); + + appDesc.nodes.put(_id, nodeDesc); + add(appDesc, nodeDesc); + } + + Utils.ExpandedPropertySet expand(PropertySetDescriptor descriptor, String applicationName, Utils.Resolver resolver) + { + Utils.ExpandedPropertySet result = new Utils.ExpandedPropertySet(); + result.references = new Utils.ExpandedPropertySet[descriptor.references.length]; + + int i = 0; + for(String ref : descriptor.references) + { + result.references[i++] = expand(findNamedPropertySet(resolver.substitute(ref), applicationName), + applicationName, resolver); + } + + result.properties = descriptor.properties; + return result; + } + + PropertySetDescriptor findNamedPropertySet(String name, String applicationName) + { + ApplicationData appData = _map.get(applicationName); + if(appData != null) + { + NodeDescriptor descriptor = appData.descriptor; + PropertySetDescriptor result = (PropertySetDescriptor)descriptor.propertySets.get(name); + if(result != null) + { + return result; + } + } + return getRoot().findNamedPropertySet(name, applicationName); + } + + boolean hasServersFromApplication(String name) + { + return _map.containsKey(name); + } + + void add(ApplicationDescriptor appDesc, NodeDescriptor nodeDesc) + { + ApplicationData data = new ApplicationData(); + data.descriptor = nodeDesc; + @SuppressWarnings("unchecked") + Utils.Resolver resolver = new Utils.Resolver(new java.util.Map[]{appDesc.variables, nodeDesc.variables}); + data.resolver = resolver; + data.resolver.put("application", appDesc.name); + data.resolver.put("node", _id); + putInfoVariables(data.resolver); + + _map.put(appDesc.name, data); + + for(ServerInstanceDescriptor p : nodeDesc.serverInstances) + { + insertServer(createServer(appDesc, data.resolver, p)); + } + + for(ServerDescriptor p : nodeDesc.servers) + { + insertServer(createServer(appDesc, data.resolver, p)); + } + } + + boolean remove(String appName) + { + _map.remove(appName); + if(_map.isEmpty() && !_up) + { + return true; + } + + java.util.List<Server> toRemove = new java.util.LinkedList<Server>(); + int[] toRemoveIndices = new int[_children.size()]; + int i = 0; + + for(int index = 0; index < _children.size(); ++index) + { + Server server = (Server)_children.get(index); + if(server.getApplication().name.equals(appName)) + { + toRemove.add(server); + toRemoveIndices[i++] = index; + } + } + toRemoveIndices = resize(toRemoveIndices, toRemove.size()); + _children.removeAll(toRemove); + getRoot().getTreeModel().nodesWereRemoved(this, toRemoveIndices, toRemove.toArray()); + + return false; + } + + void update(ApplicationDescriptor appDesc, NodeUpdateDescriptor update, boolean variablesChanged, + java.util.Set<String> serviceTemplates, java.util.Set<String> serverTemplates) + { + ApplicationData data = (ApplicationData)_map.get(appDesc.name); + + if(data == null) + { + if(update != null) + { + NodeDescriptor nodeDesc = new NodeDescriptor( + update.variables, + update.serverInstances, + update.servers, + update.loadFactor == null ? "" : update.loadFactor.value, + update.description == null ? "" : update.description.value, + update.propertySets); + + appDesc.nodes.put(_id, nodeDesc); + add(appDesc, nodeDesc); + } + // + // Else, nothing to do. + // + + return; + } + + NodeDescriptor nodeDesc = data.descriptor; + java.util.Set<Server> freshServers = new java.util.HashSet<Server>(); + + if(update != null) + { + // + // Update various fields of nodeDesc + // + if(update.description != null) + { + nodeDesc.description = update.description.value; + } + if(update.loadFactor != null) + { + nodeDesc.loadFactor = update.loadFactor.value; + } + + nodeDesc.variables.keySet().removeAll(java.util.Arrays.asList(update.removeVariables)); + nodeDesc.variables.putAll(update.variables); + + if(!variablesChanged) + { + variablesChanged = update.removeVariables.length > 0 || !update.variables.isEmpty(); + } + + nodeDesc.propertySets.keySet().removeAll(java.util.Arrays.asList(update.removePropertySets)); + nodeDesc.propertySets.putAll(update.propertySets); + + // + // Remove servers + // + for(String id : update.removeServers) + { + Server server = findServer(id); + if(server == null) + { + // + // This should never happen + // + String errorMsg = "LiveDeployment/Node: unable to remove server '" + id + + "'; please report this bug."; + + getCoordinator().getCommunicator().getLogger().error(errorMsg); + } + else + { + server.removeCallbacks(); + removeDescriptor(nodeDesc, server); + int index = getIndex(server); + _children.remove(server); + getRoot().getTreeModel().nodesWereRemoved(this, new int[]{index}, new Object[]{server}); + } + } + + // + // Add/update servers + // + for(ServerInstanceDescriptor desc : update.serverInstances) + { + Server server = createServer(appDesc, data.resolver, desc); + + Server oldServer = findServer(server.getId()); + if(oldServer == null) + { + insertServer(server); + freshServers.add(server); + nodeDesc.serverInstances.add(desc); + } + else + { + removeDescriptor(nodeDesc, oldServer); + oldServer.rebuild(server); + freshServers.add(oldServer); + nodeDesc.serverInstances.add(desc); + } + } + + for(ServerDescriptor desc : update.servers) + { + Server server = createServer(appDesc, data.resolver, desc); + + Server oldServer = findServer(server.getId()); + if(oldServer == null) + { + insertServer(server); + freshServers.add(server); + nodeDesc.servers.add(desc); + } + else + { + removeDescriptor(nodeDesc, oldServer); + oldServer.rebuild(server); + freshServers.add(oldServer); + nodeDesc.servers.add(desc); + } + } + } + + if(variablesChanged || !serviceTemplates.isEmpty() || !serverTemplates.isEmpty()) + { + // + // Rebuild every other server in this application + // + for(javax.swing.tree.TreeNode p : _children) + { + Server server = (Server)p; + if(server.getApplication() == appDesc) + { + if(!freshServers.contains(server)) + { + server.rebuild(data.resolver, variablesChanged, serviceTemplates, serverTemplates); + } + } + } + } + } + + NodeInfo getStaticInfo() + { + if(_info == null) + { + return null; + } + else + { + return _info.info; + } + } + + boolean isRunningWindows() + { + return _windows; + } + + private boolean putInfoVariables(Utils.Resolver resolver) + { + if(_info == null) + { + return false; + } + else + { + boolean updated = resolver.put("node.os", _info.info.os); + updated = resolver.put("node.hostname", _info.info.hostname) || updated; + updated = resolver.put("node.release", _info.info.release) || updated; + updated = resolver.put("node.version", _info.info.version) || updated; + updated = resolver.put("node.machine", _info.info.machine) || updated; + updated = resolver.put("node.datadir", _info.info.dataDir) || updated; + return updated; + } + } + + void up(NodeDynamicInfo info, boolean fireEvent) + { + _up = true; + _info = info; + _windows = info.info.os.toLowerCase().startsWith("windows"); + + // + // Update variables and rebuild all affected servers + // + for(ApplicationData data : _map.values()) + { + if(putInfoVariables(data.resolver)) + { + String appName = data.resolver.find("application"); + + for(javax.swing.tree.TreeNode p : _children) + { + Server server = (Server)p; + if(server.getApplication().name.equals(appName)) + { + server.rebuild(data.resolver, true, null, null); + } + } + } + } + + // + // Tell every server on this node + // + java.util.Set<Server> updatedServers = new java.util.HashSet<Server>(); + for(ServerDynamicInfo sinfo : _info.servers) + { + Server server = findServer(sinfo.id); + if(server != null) + { + server.update(sinfo.state, sinfo.pid, sinfo.enabled, true); + updatedServers.add(server); + } + } + for(javax.swing.tree.TreeNode p : _children) + { + Server server = (Server)p; + if(!updatedServers.contains(server)) + { + server.update(ServerState.Inactive, 0, true, true); + } + } + + // + // Tell adapters + // + java.util.Iterator<javax.swing.tree.TreeNode> p = _children.iterator(); + int updateCount = 0; + while(p.hasNext() && updateCount < _info.adapters.size()) + { + Server server = (Server)p.next(); + updateCount += server.updateAdapters(_info.adapters); + } + + if(fireEvent) + { + getRoot().getTreeModel().nodeChanged(this); + } + } + + boolean down() + { + _up = false; + _info.servers.clear(); + _info.adapters.clear(); + + if(_children.isEmpty()) + { + return true; + } + else + { + for(javax.swing.tree.TreeNode p : _children) + { + Server server = (Server)p; + server.nodeDown(); + } + + getRoot().getTreeModel().nodeChanged(this); + return false; + } + } + + void updateServer(ServerDynamicInfo updatedInfo) + { + if(_info != null) + { + java.util.ListIterator<ServerDynamicInfo> p = _info.servers.listIterator(); + while(p.hasNext()) + { + ServerDynamicInfo sinfo = p.next(); + if(sinfo.id.equals(updatedInfo.id)) + { + p.set(updatedInfo); + break; + } + } + } + + Server server = findServer(updatedInfo.id); + if(server != null) + { + server.update(updatedInfo.state, updatedInfo.pid, updatedInfo.enabled, true); + } + } + + void updateAdapter(AdapterDynamicInfo updatedInfo) + { + if(_info != null) + { + java.util.ListIterator<AdapterDynamicInfo> p = _info.adapters.listIterator(); + while(p.hasNext()) + { + AdapterDynamicInfo ainfo = p.next(); + if(ainfo.id.equals(updatedInfo.id)) + { + p.set(updatedInfo); + break; + } + } + } + + for(javax.swing.tree.TreeNode p : _children) + { + Server server = (Server)p; + if(server.updateAdapter(updatedInfo)) + { + break; + } + } + } + + Ice.ObjectPrx getProxy(String adapterId) + { + if(_info != null) + { + java.util.ListIterator<AdapterDynamicInfo> p = _info.adapters.listIterator(); + while(p.hasNext()) + { + AdapterDynamicInfo ainfo = p.next(); + if(ainfo.id.equals(adapterId)) + { + return ainfo.proxy; + } + } + } + return null; + } + + java.util.SortedMap<String, String> getLoadFactors() + { + java.util.SortedMap<String, String> result = new java.util.TreeMap<String, String>(); + + for(java.util.Map.Entry<String, ApplicationData> p : _map.entrySet()) + { + ApplicationData ad = p.getValue(); + + String val = ad.resolver.substitute(ad.descriptor.loadFactor); + if(val.length() == 0) + { + val = "Default"; + } + + result.put(p.getKey(), val); + } + return result; + } + + void showLoad() + { + AMI_Admin_getNodeLoad cb = new AMI_Admin_getNodeLoad() + { + public void ice_response(LoadInfo loadInfo) + { + NumberFormat format; + if(_windows) + { + format = NumberFormat.getPercentInstance(); + format.setMaximumFractionDigits(1); + format.setMinimumFractionDigits(1); + } + else + { + format = NumberFormat.getNumberInstance(); + format.setMaximumFractionDigits(2); + format.setMinimumFractionDigits(2); + } + + final String load = + format.format(loadInfo.avg1) + " " + + format.format(loadInfo.avg5) + " " + + format.format(loadInfo.avg15); + + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + _editor.setLoad(load, Node.this); + } + }); + } + + public void ice_exception(final Ice.UserException e) + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + if(e instanceof IceGrid.NodeNotExistException) + { + _editor.setLoad( + "Error: this node is not known to this IceGrid Registry", + Node.this); + } + else if(e instanceof IceGrid.NodeUnreachableException) + { + _editor.setLoad("Error: cannot reach this node", Node.this); + } + else + { + _editor.setLoad("Error: " + e.toString(), Node.this); + } + } + }); + } + + public void ice_exception(final Ice.LocalException e) + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + _editor.setLoad("Error: " + e.toString(), Node.this); + } + }); + } + }; + + try + { + getCoordinator().getMainFrame().setCursor( + Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + + IceGrid.AdminPrx admin = getCoordinator().getAdmin(); + if(admin == null) + { + _editor.setLoad("Unknown", this); + } + else + { + admin.getNodeLoad_async(cb, _id); + } + } + catch(Ice.LocalException e) + { + _editor.setLoad("Error: " + e.toString(), this); + } + finally + { + getCoordinator().getMainFrame().setCursor( + Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + } + + private Server createServer(ApplicationDescriptor application, Utils.Resolver resolver, + ServerInstanceDescriptor instanceDescriptor) + { + // + // Find template + // + TemplateDescriptor templateDescriptor = + (TemplateDescriptor)application.serverTemplates.get(instanceDescriptor.template); + assert templateDescriptor != null; + + ServerDescriptor serverDescriptor = (ServerDescriptor)templateDescriptor.descriptor; + + assert serverDescriptor != null; + + // + // Build resolver + // + Utils.Resolver instanceResolver = + new Utils.Resolver(resolver, + instanceDescriptor.parameterValues, + templateDescriptor.parameterDefaults); + + String serverId = instanceResolver.substitute(serverDescriptor.id); + instanceResolver.put("server", serverId); + + // + // Lookup dynamic info + // + ServerState serverState = _up ? ServerState.Inactive : null; + int pid = 0; + boolean enabled = true; + if(_info != null) + { + for(ServerDynamicInfo info : _info.servers) + { + if(info.id.equals(serverId)) + { + serverState = info.state; + pid = info.pid; + enabled = info.enabled; + break; + } + } + } + + // + // Create server + // + return new Server(this, serverId, instanceResolver, instanceDescriptor, serverDescriptor, application, + serverState, pid, enabled); + } + + private Server createServer(ApplicationDescriptor application, Utils.Resolver resolver, + ServerDescriptor serverDescriptor) + { + // + // Build resolver + // + Utils.Resolver instanceResolver = new Utils.Resolver(resolver); + String serverId = instanceResolver.substitute(serverDescriptor.id); + instanceResolver.put("server", serverId); + + // + // Lookup dynamic info + // + ServerState serverState = _up ? ServerState.Inactive : null; + int pid = 0; + boolean enabled = true; + if(_info != null) + { + for(ServerDynamicInfo info : _info.servers) + { + if(info.id.equals(serverId)) + { + serverState = info.state; + pid = info.pid; + enabled = info.enabled; + break; + } + } + } + + // + // Create server + // + return new Server(this, serverId, instanceResolver, null, serverDescriptor, application, serverState, pid, + enabled); + } + + private void insertServer(Server server) + { + insertSortedChild(server, _children, getRoot().getTreeModel()); + } + + private Server findServer(String id) + { + return (Server)find(id, _children); + } + + private void removeDescriptor(NodeDescriptor nodeDesc, Server server) + { + ServerInstanceDescriptor instanceDescriptor = server.getInstanceDescriptor(); + if(instanceDescriptor != null) + { + removeDescriptor(nodeDesc, instanceDescriptor); + } + else + { + removeDescriptor(nodeDesc, server.getServerDescriptor()); + } + } + + private void removeDescriptor(NodeDescriptor nodeDesc, ServerDescriptor sd) + { + // + // A straight remove uses equals(), which is not the desired behavior + // + java.util.Iterator<ServerDescriptor> p = nodeDesc.servers.iterator(); + while(p.hasNext()) + { + if(sd == p.next()) + { + p.remove(); + break; + } + } + } + + private void removeDescriptor(NodeDescriptor nodeDesc, ServerInstanceDescriptor sd) + { + // + // A straight remove uses equals(), which is not the desired behavior + // + java.util.Iterator<ServerInstanceDescriptor> p = nodeDesc.serverInstances.iterator(); + while(p.hasNext()) + { + if(sd == p.next()) + { + p.remove(); + break; + } + } + } + + static class ApplicationData + { + NodeDescriptor descriptor; + Utils.Resolver resolver; + } + + // + // Application name to ApplicationData + // + private final java.util.SortedMap<String, ApplicationData> _map = new java.util.TreeMap<String, ApplicationData>(); + + private boolean _up = false; + private NodeDynamicInfo _info; + private boolean _windows = false; + + static private DefaultTreeCellRenderer _cellRenderer; + static private Icon _nodeUp; + static private Icon _nodeDown; + + static private NodeEditor _editor; + static private JPopupMenu _popup; +} |