add fcp connection collector
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sat, 3 May 2008 16:17:06 +0000 (16:17 +0000)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sat, 3 May 2008 16:17:06 +0000 (16:17 +0000)
git-svn-id: http://trooper/svn/projects/jSite/trunk@780 c3eda9e8-030b-0410-8277-bc7414b0a119

src/net/pterodactylus/jsite/freenet/FcpCollector.java [new file with mode: 0644]

diff --git a/src/net/pterodactylus/jsite/freenet/FcpCollector.java b/src/net/pterodactylus/jsite/freenet/FcpCollector.java
new file mode 100644 (file)
index 0000000..85bb9a9
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * jSite2 - FcpCollector.java -
+ * Copyright © 2008 David Roden
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package net.pterodactylus.jsite.freenet;
+
+import java.io.IOException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import net.pterodactylus.fcp.highlevel.ConnectResult;
+import net.pterodactylus.fcp.highlevel.HighLevelCallback;
+import net.pterodactylus.fcp.highlevel.HighLevelClient;
+import net.pterodactylus.jsite.core.Node;
+
+/**
+ * TODO
+ *
+ * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
+ * @version $Id$
+ */
+public class FcpCollector {
+
+       /** The FCP client name. */
+       private final String clientName;
+
+       /** Object used for synchronization. */
+       private final Object syncObject = new Object();
+
+       /** All FCP connections. */
+       private Set<HighLevelClient> connections = Collections.synchronizedSet(new HashSet<HighLevelClient>());
+
+       /** Keeps track of which connection is in use right now. */
+       private Set<HighLevelClient> usedConnections = Collections.synchronizedSet(new HashSet<HighLevelClient>());
+
+       /** Maps nodes to high-level clients. */
+       private Map<HighLevelClient, Node> clientNodes = Collections.synchronizedMap(new HashMap<HighLevelClient, Node>());
+
+       /**
+        * Creates a new FCP collector.
+        *
+        * @param clientName
+        *            The name of the FCP client
+        */
+       public FcpCollector(String clientName) {
+               this.clientName = clientName;
+       }
+
+       //
+       // ACTIONS
+       //
+
+       /**
+        * Adds a connection to the given node. The connection is made instantly so
+        * this method may block.
+        *
+        * @param node
+        *            The node to connect to
+        * @return <code>true</code> 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 {
+               HighLevelClient highLevelClient = new HighLevelClient(clientName, node.getHostname(), node.getPort());
+               HighLevelCallback<ConnectResult> connectCallback = highLevelClient.connect();
+               ConnectResult connectResult = null;
+               while (connectResult == null) {
+                       try {
+                               connectResult = connectCallback.getResult();
+                       } catch (InterruptedException e) {
+                               /* ignore. */
+                       }
+               }
+               if (connectResult.isConnected()) {
+                       synchronized (syncObject) {
+                               connections.add(highLevelClient);
+                               clientNodes.put(highLevelClient, node);
+                       }
+               }
+               return connectResult.isConnected();
+       }
+
+       /**
+        * Returns a list of all nodes.
+        *
+        * @return A list of all nodes
+        */
+       public List<Node> getNodes() {
+               return new ArrayList<Node>(clientNodes.values());
+       }
+
+       //
+       // PRIVATE METHODS
+       //
+
+       /**
+        * Finds a currently unused high-level client, optionally waiting until a
+        * client is free and marking it used.
+        *
+        * @param wait
+        *            <code>true</code> to wait for a free connection,
+        *            <code>false</code> to return <code>null</code>
+        * @param markAsUsed
+        *            <code>true</code> to mark the connection as used before
+        *            returning it, <code>false</code> not to mark it
+        * @return An unused FCP connection, or <code>null</code> if no connection
+        *         could be found
+        */
+       @SuppressWarnings("unused")
+       private HighLevelClient findUnusedClient(boolean wait, boolean markAsUsed) {
+               synchronized (syncObject) {
+                       HighLevelClient freeHighLevelClient = null;
+                       while (freeHighLevelClient == null) {
+                               for (HighLevelClient highLevelClient: connections) {
+                                       if (!usedConnections.contains(highLevelClient)) {
+                                               freeHighLevelClient = highLevelClient;
+                                               break;
+                                       }
+                               }
+                               if (freeHighLevelClient != null) {
+                                       if (markAsUsed) {
+                                               usedConnections.add(freeHighLevelClient);
+                                       }
+                                       return freeHighLevelClient;
+                               }
+                               if (!wait) {
+                                       return null;
+                               }
+                       }
+                       /* we never get here, but the compiler doesn't realize. */
+                       return null;
+               }
+       }
+
+}