Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 package org.ros.node;
00018
00019 import com.google.common.base.Preconditions;
00020 import com.google.common.collect.BiMap;
00021 import com.google.common.collect.HashBiMap;
00022 import com.google.common.collect.HashMultimap;
00023 import com.google.common.collect.Lists;
00024 import com.google.common.collect.Maps;
00025 import com.google.common.collect.Multimap;
00026 import com.google.common.collect.Multimaps;
00027
00028 import org.apache.commons.logging.Log;
00029 import org.apache.commons.logging.LogFactory;
00030 import org.ros.concurrent.DefaultScheduledExecutorService;
00031 import org.ros.namespace.GraphName;
00032
00033 import java.util.Collection;
00034 import java.util.concurrent.ExecutorService;
00035 import java.util.concurrent.ScheduledExecutorService;
00036
00042 public class DefaultNodeMainExecutor implements NodeMainExecutor {
00043
00044 private static final boolean DEBUG = false;
00045 private static final Log log = LogFactory.getLog(DefaultNodeMainExecutor.class);
00046
00047 private final NodeFactory nodeFactory;
00048 private final ScheduledExecutorService scheduledExecutorService;
00049 private final Multimap<GraphName, ConnectedNode> connectedNodes;
00050 private final BiMap<Node, NodeMain> nodeMains;
00051
00052 private class RegistrationListener implements NodeListener {
00053 @Override
00054 public void onStart(ConnectedNode connectedNode) {
00055 registerNode(connectedNode);
00056 }
00057
00058 @Override
00059 public void onShutdown(Node node) {
00060 }
00061
00062 @Override
00063 public void onShutdownComplete(Node node) {
00064 unregisterNode(node);
00065 }
00066
00067 @Override
00068 public void onError(Node node, Throwable throwable) {
00069 log.error("Node error.", throwable);
00070 unregisterNode(node);
00071 }
00072 }
00073
00080 public static NodeMainExecutor newDefault() {
00081 return newDefault(new DefaultScheduledExecutorService());
00082 }
00083
00088 public static NodeMainExecutor newDefault(ScheduledExecutorService executorService) {
00089 return new DefaultNodeMainExecutor(new DefaultNodeFactory(executorService), executorService);
00090 }
00091
00098 private DefaultNodeMainExecutor(NodeFactory nodeFactory,
00099 ScheduledExecutorService scheduledExecutorService) {
00100 this.nodeFactory = nodeFactory;
00101 this.scheduledExecutorService = scheduledExecutorService;
00102 connectedNodes =
00103 Multimaps.synchronizedMultimap(HashMultimap.<GraphName, ConnectedNode>create());
00104 nodeMains = Maps.synchronizedBiMap(HashBiMap.<Node, NodeMain>create());
00105 Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
00106 @Override
00107 public void run() {
00108 DefaultNodeMainExecutor.this.shutdown();
00109 }
00110 }));
00111 }
00112
00113 @Override
00114 public ScheduledExecutorService getScheduledExecutorService() {
00115 return scheduledExecutorService;
00116 }
00117
00118 @Override
00119 public void execute(final NodeMain nodeMain, final NodeConfiguration nodeConfiguration,
00120 final Collection<NodeListener> nodeListeners) {
00121
00122
00123 final NodeConfiguration nodeConfigurationCopy = NodeConfiguration.copyOf(nodeConfiguration);
00124 nodeConfigurationCopy.setDefaultNodeName(nodeMain.getDefaultNodeName());
00125 Preconditions.checkNotNull(nodeConfigurationCopy.getNodeName(), "Node name not specified.");
00126 if (DEBUG) {
00127 log.info("Starting node: " + nodeConfigurationCopy.getNodeName());
00128 }
00129 scheduledExecutorService.execute(new Runnable() {
00130 @Override
00131 public void run() {
00132 Collection<NodeListener> nodeListenersCopy = Lists.newArrayList();
00133 nodeListenersCopy.add(new RegistrationListener());
00134 nodeListenersCopy.add(nodeMain);
00135 if (nodeListeners != null) {
00136 nodeListenersCopy.addAll(nodeListeners);
00137 }
00138
00139 Node node = nodeFactory.newNode(nodeConfigurationCopy, nodeListenersCopy);
00140 nodeMains.put(node, nodeMain);
00141 }
00142 });
00143 }
00144
00145 @Override
00146 public void execute(NodeMain nodeMain, NodeConfiguration nodeConfiguration) {
00147 execute(nodeMain, nodeConfiguration, null);
00148 }
00149
00150 @Override
00151 public void shutdownNodeMain(NodeMain nodeMain) {
00152 Node node = nodeMains.inverse().get(nodeMain);
00153 if (node != null) {
00154 safelyShutdownNode(node);
00155 }
00156 }
00157
00158 @Override
00159 public void shutdown() {
00160 synchronized (connectedNodes) {
00161 for (ConnectedNode connectedNode : connectedNodes.values()) {
00162 safelyShutdownNode(connectedNode);
00163 }
00164 }
00165 }
00166
00173 private void safelyShutdownNode(Node node) {
00174 boolean success = true;
00175 try {
00176 node.shutdown();
00177 } catch (Exception e) {
00178
00179 log.error("Exception thrown while shutting down node.", e);
00180
00181
00182 unregisterNode(node);
00183 success = false;
00184 }
00185 if (success) {
00186 log.info("Shutdown successful.");
00187 }
00188 }
00189
00196 private void registerNode(ConnectedNode connectedNode) {
00197 GraphName nodeName = connectedNode.getName();
00198 synchronized (connectedNodes) {
00199 for (ConnectedNode illegalConnectedNode : connectedNodes.get(nodeName)) {
00200 System.err.println(String.format(
00201 "Node name collision. Existing node %s (%s) will be shutdown.", nodeName,
00202 illegalConnectedNode.getUri()));
00203 illegalConnectedNode.shutdown();
00204 }
00205 connectedNodes.put(nodeName, connectedNode);
00206 }
00207 }
00208
00215 private void unregisterNode(Node node) {
00216 connectedNodes.get(node.getName()).remove(node);
00217 nodeMains.remove(node);
00218 }
00219 }