X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fnet%2Fpterodactylus%2Fjsite%2Fcore%2FNodeManager.java;h=40e4190f3067e7927f283051f23566456c27bff8;hb=3ac91e8b526e04d6be1fc1bb16154633a0ad957e;hp=f772dc2592bf440791db738fb054a22423d92251;hpb=78dd8a015cbfdedca1a962d03d16b89ee8187b8f;p=jSite2.git diff --git a/src/net/pterodactylus/jsite/core/NodeManager.java b/src/net/pterodactylus/jsite/core/NodeManager.java index f772dc2..40e4190 100644 --- a/src/net/pterodactylus/jsite/core/NodeManager.java +++ b/src/net/pterodactylus/jsite/core/NodeManager.java @@ -40,15 +40,17 @@ import java.util.logging.Logger; import net.pterodactylus.fcp.highlevel.HighLevelClient; import net.pterodactylus.fcp.highlevel.HighLevelClientListener; +import net.pterodactylus.fcp.highlevel.HighLevelException; import net.pterodactylus.fcp.highlevel.KeyGenerationResult; +import net.pterodactylus.jsite.util.IdGenerator; import net.pterodactylus.util.io.Closer; import net.pterodactylus.util.logging.Logging; +import net.pterodactylus.util.number.Hex; /** * TODO - * + * * @author David ‘Bombe’ Roden <bombe@freenetproject.org> - * @version $Id$ */ public class NodeManager implements Iterable, PropertyChangeListener, HighLevelClientListener { @@ -70,6 +72,9 @@ public class NodeManager implements Iterable, PropertyChangeListener, High /** All nodes. */ private List nodes = Collections.synchronizedList(new ArrayList()); + /** Map from node ID to node. */ + private Map idNodes = Collections.synchronizedMap(new HashMap()); + /** All FCP connections. */ private Map nodeClients = Collections.synchronizedMap(new HashMap()); @@ -78,7 +83,7 @@ public class NodeManager implements Iterable, PropertyChangeListener, High /** * Creates a new FCP collector. - * + * * @param clientName * The name of the FCP client * @param directory @@ -95,7 +100,7 @@ public class NodeManager implements Iterable, PropertyChangeListener, High /** * Adds the given listener to the list of listeners. - * + * * @param nodeListener * The listener to add */ @@ -105,7 +110,7 @@ public class NodeManager implements Iterable, PropertyChangeListener, High /** * Removes the given listener from the list of listeners. - * + * * @param nodeListener * The listener to remove */ @@ -115,57 +120,61 @@ public class NodeManager implements Iterable, PropertyChangeListener, High /** * Notifies all listeners that a node was added. - * + * * @param node * The node that was added. */ private void fireNodeAdded(Node node) { - for (NodeListener nodeListener: nodeListeners) { + logger.log(Level.FINEST, "firing nodeAdded event with [node=" + node + "]"); + for (NodeListener nodeListener : nodeListeners) { nodeListener.nodeAdded(node); } } /** * Notifies all listeners that a node was removed. - * + * * @param node * The node that was removed */ private void fireNodeRemoved(Node node) { - for (NodeListener nodeListener: nodeListeners) { + logger.log(Level.FINEST, "firing nodeRemoved event with [node=" + node + "]"); + for (NodeListener nodeListener : nodeListeners) { nodeListener.nodeRemoved(node); } } /** * 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) { + logger.log(Level.FINEST, "firing nodeConnected event with [node=" + node + "]"); + for (NodeListener nodeListener : nodeListeners) { nodeListener.nodeConnected(node); } } /** * Notifies all listeners that a connection to a node has failed. - * + * * @param node * The node that could not be connected * @param cause * The cause of the failure */ private void fireNodeConnectionFailed(Node node, Throwable cause) { - for (NodeListener nodeListener: nodeListeners) { + logger.log(Level.FINEST, "firing nodeConnectionFailed event with [node=" + node + ",cause=" + cause + "]"); + for (NodeListener nodeListener : nodeListeners) { nodeListener.nodeConnectionFailed(node, cause); } } /** * Notifies all listeners that the given node was disconnected. - * + * * @param node * The node that is now disconnected * @param throwable @@ -173,7 +182,8 @@ public class NodeManager implements Iterable, PropertyChangeListener, High * if there was no exception */ private void fireNodeDisconnected(Node node, Throwable throwable) { - for (NodeListener nodeListener: nodeListeners) { + logger.log(Level.FINEST, "firing nodeDisconnected event with [node=" + node + ",throwable=" + throwable + "]"); + for (NodeListener nodeListener : nodeListeners) { nodeListener.nodeDisconnected(node, throwable); } } @@ -184,7 +194,7 @@ public class NodeManager implements Iterable, PropertyChangeListener, High /** * Returns the directory in which the nodes are stored. - * + * * @return The directory the nodes are stored in */ public String getDirectory() { @@ -193,7 +203,7 @@ public class NodeManager implements Iterable, PropertyChangeListener, High /** * Checks whether the given node is already connected. - * + * * @param node * The node to check * @return true if the node is already connected, @@ -216,11 +226,12 @@ public class NodeManager implements Iterable, PropertyChangeListener, High /** * Loads nodes. - * + * * @throws IOException * if an I/O error occurs loading the nodes */ public void load() throws IOException { + logger.log(Level.FINEST, "load()"); File directoryFile = new File(directory); File nodeFile = new File(directoryFile, "nodes.properties"); if (!nodeFile.exists() || !nodeFile.isFile() || !nodeFile.canRead()) { @@ -238,6 +249,10 @@ public class NodeManager implements Iterable, PropertyChangeListener, High List loadedNodes = new ArrayList(); while (nodeProperties.containsKey("nodes." + ++nodeIndex + ".name")) { String nodePrefix = "nodes." + nodeIndex; + String nodeId = nodeProperties.getProperty(nodePrefix + ".id"); + if (nodeId == null) { + nodeId = Hex.toHex(IdGenerator.generateId()); + } String nodeName = nodeProperties.getProperty(nodePrefix + ".name"); if (!Verifier.verifyNodeName(nodeName)) { logger.log(Level.WARNING, "invalid node name “" + nodeName + "”, skipping…"); @@ -262,15 +277,16 @@ public class NodeManager implements Iterable, PropertyChangeListener, High continue; } Node newNode = new Node(); + newNode.setId(nodeId); newNode.setName(nodeName); newNode.setHostname(nodeHostname); newNode.setPort(nodePort); loadedNodes.add(newNode); } - logger.fine("loaded " + loadedNodes.size() + " nodes from config"); + logger.log(Level.FINE, "loaded " + loadedNodes.size() + " nodes from config"); synchronized (syncObject) { nodes.clear(); - for (Node node: loadedNodes) { + for (Node node : loadedNodes) { addNode(node); } } @@ -278,11 +294,12 @@ public class NodeManager implements Iterable, PropertyChangeListener, High /** * Saves all configured nodes. - * + * * @throws IOException * if an I/O error occurs saving the nodes */ public void save() throws IOException { + logger.log(Level.FINEST, "save()"); File directoryFile = new File(directory); if (!directoryFile.exists()) { if (!directoryFile.mkdirs()) { @@ -291,8 +308,9 @@ public class NodeManager implements Iterable, PropertyChangeListener, High } Properties nodeProperties = new Properties(); int nodeIndex = -1; - for (Node node: nodes) { + for (Node node : nodes) { String nodePrefix = "nodes." + ++nodeIndex; + nodeProperties.setProperty(nodePrefix + ".id", node.getId()); nodeProperties.setProperty(nodePrefix + ".name", node.getName()); nodeProperties.setProperty(nodePrefix + ".hostname", node.getHostname()); nodeProperties.setProperty(nodePrefix + ".port", String.valueOf(node.getPort())); @@ -309,21 +327,23 @@ public class NodeManager implements Iterable, PropertyChangeListener, High /** * Adds the given node to this manager. - * + * * @see #connect(Node) * @param node * The node to connect to - * @return true if the node was added, false - * if the node was not added because it was already known + * @return true if the node was added, false if + * the node was not added because it was already known */ public boolean addNode(Node node) { + logger.log(Level.FINEST, "addNode(node=" + node + ")"); if (nodes.contains(node)) { - logger.warning("was told to add already known node: " + node); + logger.log(Level.WARNING, "was told to add already known node: " + node); return false; } node.addPropertyChangeListener(this); HighLevelClient highLevelClient = new HighLevelClient(clientName); nodes.add(node); + idNodes.put(node.getId(), node); clientNodes.put(highLevelClient, node); nodeClients.put(node, highLevelClient); highLevelClient.addHighLevelClientListener(this); @@ -334,11 +354,12 @@ public class NodeManager implements Iterable, PropertyChangeListener, High /** * 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) { + logger.log(Level.FINEST, "removeNode(node=" + node + ")"); synchronized (syncObject) { if (!nodes.contains(node)) { return; @@ -346,6 +367,8 @@ public class NodeManager implements Iterable, PropertyChangeListener, High if (nodeClients.containsKey(node)) { disconnect(node); } + nodes.remove(node); + idNodes.remove(node.getId()); node.removePropertyChangeListener(this); fireNodeRemoved(node); } @@ -353,15 +376,16 @@ public class NodeManager implements Iterable, PropertyChangeListener, High /** * Tries to establish a connection with the given node. - * + * * @param node * The node to connect to */ public void connect(Node node) { + logger.log(Level.FINEST, "connect(node=" + node + ")"); HighLevelClient highLevelClient; highLevelClient = nodeClients.get(node); if (highLevelClient == null) { - logger.warning("was told to connect to unknown node: " + node); + logger.log(Level.WARNING, "was told to connect to unknown node: " + node); return; } try { @@ -375,11 +399,12 @@ public class NodeManager implements Iterable, PropertyChangeListener, High /** * Disconnects the given node without removing it. - * + * * @param node * The node to disconnect */ public void disconnect(Node node) { + logger.log(Level.FINEST, "disconnect(node=" + node + ")"); synchronized (syncObject) { if (!nodes.contains(node)) { return; @@ -391,7 +416,7 @@ public class NodeManager implements Iterable, PropertyChangeListener, High /** * Returns a list of all nodes. - * + * * @return A list of all nodes */ public List getNodes() { @@ -400,7 +425,7 @@ public class NodeManager implements Iterable, PropertyChangeListener, High /** * Returns the high-level client for a given node. - * + * * @param node * The node to get a high-level client for * @return The high-level client for a node, or null if the @@ -412,7 +437,7 @@ public class NodeManager implements Iterable, PropertyChangeListener, High /** * Returns the node for a high-level client. - * + * * @param highLevelClient * The high-level client to get the node for * @return The node for the high-level client, or null if the @@ -423,23 +448,41 @@ public class NodeManager implements Iterable, PropertyChangeListener, High } /** + * Returns the node identified by the given ID. + * + * @param id + * The ID of the node + * @return The node with the given ID, or null if no such node + * was found + */ + Node getNode(String id) { + return idNodes.get(id); + } + + /** * Generates a new SSK key pair. - * + * * @return An array with the private key at index 0 and the * public key at index 1 * @throws IOException * if an I/O error occurs communicating with the node + * @throws JSiteException + * if there is a problem with the node */ - public String[] generateKeyPair() throws IOException { - if (!nodes.isEmpty()) { - Node node = nodes.get(0); - HighLevelClient highLevelClient = nodeClients.get(node); - try { - KeyGenerationResult keyGenerationResult = highLevelClient.generateKey().getResult(); - return new String[] { keyGenerationResult.getInsertURI(), keyGenerationResult.getRequestURI() }; - } catch (InterruptedException e) { - /* ignore. */ - } + public String[] generateKeyPair() throws IOException, JSiteException { + logger.log(Level.FINEST, "generateKeyPair()"); + if (nodes.isEmpty()) { + throw new NoNodeException("no node configured"); + } + Node node = nodes.get(0); + HighLevelClient highLevelClient = nodeClients.get(node); + try { + KeyGenerationResult keyGenerationResult = highLevelClient.generateKey().getResult(); + return new String[] { keyGenerationResult.getInsertURI(), keyGenerationResult.getRequestURI() }; + } catch (HighLevelException hle1) { + throw new BackendException(hle1); + } catch (InterruptedException e) { + /* ignore. */ } return null; } @@ -456,7 +499,7 @@ public class NodeManager implements Iterable, PropertyChangeListener, High * {@inheritDoc} */ public void clientConnected(HighLevelClient highLevelClient) { - logger.log(Level.FINER, "clientConnected(c=" + highLevelClient + ")"); + logger.log(Level.FINEST, "clientConnected(highLevelClient=" + highLevelClient + ")"); Node node = clientNodes.get(highLevelClient); if (node == null) { logger.log(Level.WARNING, "got event for unknown client"); @@ -469,7 +512,7 @@ public class NodeManager implements Iterable, PropertyChangeListener, High * {@inheritDoc} */ public void clientDisconnected(HighLevelClient highLevelClient, Throwable throwable) { - logger.log(Level.FINER, "clientDisconnected(c=" + highLevelClient + ",t=" + throwable + ")"); + logger.log(Level.FINEST, "clientDisconnected(highLevelClient=" + highLevelClient + ",throwable=" + throwable + ")"); synchronized (syncObject) { Node node = clientNodes.get(highLevelClient); if (node == null) {