X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fnet%2Fpterodactylus%2Fjsite%2Fcore%2FNodeManager.java;h=5ed51a719d680f7f0bd7a7f320dd6c03ac59bc67;hb=b9455984497cc0e9bc58d7b33eaf951e992eb141;hp=71bb95dcef39957dec5dae0de7001dc6f6a96a40;hpb=029548705a1fa60731ad7f492103333acdd48001;p=jSite2.git diff --git a/src/net/pterodactylus/jsite/core/NodeManager.java b/src/net/pterodactylus/jsite/core/NodeManager.java index 71bb95d..5ed51a7 100644 --- a/src/net/pterodactylus/jsite/core/NodeManager.java +++ b/src/net/pterodactylus/jsite/core/NodeManager.java @@ -25,7 +25,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -37,10 +36,10 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; -import net.pterodactylus.fcp.highlevel.ConnectResult; -import net.pterodactylus.fcp.highlevel.HighLevelCallback; import net.pterodactylus.fcp.highlevel.HighLevelClient; +import net.pterodactylus.fcp.highlevel.HighLevelClientListener; import net.pterodactylus.util.io.Closer; +import net.pterodactylus.util.logging.Logging; /** * TODO @@ -48,10 +47,10 @@ import net.pterodactylus.util.io.Closer; * @author David ‘Bombe’ Roden <bombe@freenetproject.org> * @version $Id$ */ -public class NodeManager { +public class NodeManager implements HighLevelClientListener { /** Logger. */ - private static final Logger logger = Logger.getLogger(NodeManager.class.getName()); + private static final Logger logger = Logging.getLogger(NodeManager.class.getName()); /** The FCP client name. */ private final String clientName; @@ -62,11 +61,14 @@ public class NodeManager { /** Object used for synchronization. */ private final Object syncObject = new Object(); + /** Node listeners. */ + private List nodeListeners = Collections.synchronizedList(new ArrayList()); + /** All nodes. */ private List nodes = Collections.synchronizedList(new ArrayList()); /** All FCP connections. */ - private Map nodeConnections = Collections.synchronizedMap(new HashMap()); + private Map nodeClients = Collections.synchronizedMap(new HashMap()); /** Keeps track of which connection is in use right now. */ private Set usedConnections = Collections.synchronizedSet(new HashSet()); @@ -88,6 +90,57 @@ public class NodeManager { } // + // EVENT MANAGEMENT + // + + /** + * Adds the given listener to the list of listeners. + * + * @param nodeListener + * The listener to add + */ + public void addNodeListener(NodeListener nodeListener) { + nodeListeners.add(nodeListener); + } + + /** + * Removes the given listener from the list of listeners. + * + * @param nodeListener + * The listener to remove + */ + public void removeNodeListener(NodeListener nodeListener) { + nodeListeners.remove(nodeListener); + } + + /** + * Notifies all listeners that the given node was connected. + * + * @param node + * The node that is now connected + */ + private void fireNodeConnected(Node node) { + for (NodeListener nodeListener: nodeListeners) { + nodeListener.nodeConnected(node); + } + } + + /** + * Notifies all listeners that the given node was disconnected. + * + * @param node + * The node that is now disconnected + * @param throwable + * The exception that caused the disconnect, or null + * if there was no exception + */ + private void fireNodeDisconnected(Node node, Throwable throwable) { + for (NodeListener nodeListener: nodeListeners) { + nodeListener.nodeDisconnected(node, throwable); + } + } + + // // ACCESSORS // @@ -207,41 +260,72 @@ public class NodeManager { } /** - * Adds a connection to the given node. The connection is made instantly so - * this method may block. If the node can not be connected, it will not be - * added to the list of nodes. + * Adds the given node to this manager. * + * @see #connect(Node) * @param node * The node to connect to - * @return true if the connection to the node could be - * established - * @throws UnknownHostException - * if the hostname of the node can not be resolved - * @throws IOException - * if an I/O error occurs connecting to the node */ - public boolean addNode(Node node) throws UnknownHostException, IOException { - if (nodes.contains(node)) { - return true; + public void addNode(Node node) { + synchronized (syncObject) { + if (!nodes.contains(node)) { + nodes.add(node); + } } - HighLevelClient highLevelClient = new HighLevelClient(clientName, node.getHostname(), node.getPort()); - HighLevelCallback connectCallback = highLevelClient.connect(); - ConnectResult connectResult = null; - while (connectResult == null) { - try { - connectResult = connectCallback.getResult(); - } catch (InterruptedException e) { - /* ignore. */ + } + + /** + * Removes the given node from the node manager, disconnecting it if it is + * currently connected. + * + * @param node + * The node to remove + */ + public void removeNode(Node node) { + synchronized (syncObject) { + if (!nodes.contains(node)) { + return; + } + if (nodeClients.containsKey(node)) { + disconnect(node); } } - if (connectResult.isConnected()) { + } + + /** + * Tries to establish a connection with the given node. + * + * @param node + * The node to connect to + */ + public void connect(Node node) { + try { + HighLevelClient highLevelClient = new HighLevelClient(clientName, node.getHostname(), node.getPort()); synchronized (syncObject) { - nodes.add(node); - nodeConnections.put(node, highLevelClient); clientNodes.put(highLevelClient, node); + nodeClients.put(node, highLevelClient); } + highLevelClient.addHighLevelClientListener(this); + highLevelClient.connect(); + } catch (IOException ioe1) { + fireNodeDisconnected(node, ioe1); + } + } + + /** + * Disconnects the given node without removing it. + * + * @param node + * The node to disconnect + */ + public void disconnect(Node node) { + synchronized (syncObject) { + if (!nodes.contains(node)) { + return; + } + HighLevelClient highLevelClient = nodeClients.get(node); + highLevelClient.disconnect(); } - return connectResult.isConnected(); } /** @@ -250,7 +334,7 @@ public class NodeManager { * @return A list of all nodes */ public List getNodes() { - return new ArrayList(clientNodes.values()); + return Collections.unmodifiableList(nodes); } // @@ -275,7 +359,7 @@ public class NodeManager { synchronized (syncObject) { HighLevelClient freeHighLevelClient = null; while (freeHighLevelClient == null) { - for (HighLevelClient highLevelClient: nodeConnections.values()) { + for (HighLevelClient highLevelClient: nodeClients.values()) { if (!usedConnections.contains(highLevelClient)) { freeHighLevelClient = highLevelClient; break; @@ -296,4 +380,37 @@ public class NodeManager { } } + // + // INTERFACE HighLevelClientListener + // + + /** + * {@inheritDoc} + */ + public void clientConnected(HighLevelClient highLevelClient) { + logger.log(Level.FINER, "clientConnected(c=" + highLevelClient + ")"); + Node node = clientNodes.get(highLevelClient); + if (node == null) { + logger.log(Level.WARNING, "got event for unknown client"); + return; + } + fireNodeConnected(node); + } + + /** + * {@inheritDoc} + */ + public void clientDisconnected(HighLevelClient highLevelClient, Throwable throwable) { + logger.log(Level.FINER, "clientDisconnected(c=" + highLevelClient + ",t=" + throwable +")"); + synchronized (syncObject) { + Node node = clientNodes.remove(highLevelClient); + if (node == null) { + logger.log(Level.WARNING, "got event for unknown client"); + return; + } + nodeClients.remove(node); + fireNodeDisconnected(node, throwable); + } + } + }