From: David ‘Bombe’ Roden Date: Sat, 3 May 2008 16:17:06 +0000 (+0000) Subject: add fcp connection collector X-Git-Url: https://git.pterodactylus.net/?a=commitdiff_plain;h=7c75325e43196a5e07f2de49d67c0c4a171ccf97;p=jSite2.git add fcp connection collector git-svn-id: http://trooper/svn/projects/jSite/trunk@780 c3eda9e8-030b-0410-8277-bc7414b0a119 --- diff --git a/src/net/pterodactylus/jsite/freenet/FcpCollector.java b/src/net/pterodactylus/jsite/freenet/FcpCollector.java new file mode 100644 index 0000000..85bb9a9 --- /dev/null +++ b/src/net/pterodactylus/jsite/freenet/FcpCollector.java @@ -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 <bombe@freenetproject.org> + * @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 connections = Collections.synchronizedSet(new HashSet()); + + /** Keeps track of which connection is in use right now. */ + private Set usedConnections = Collections.synchronizedSet(new HashSet()); + + /** Maps nodes to high-level clients. */ + private Map clientNodes = Collections.synchronizedMap(new HashMap()); + + /** + * 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 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 { + 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. */ + } + } + 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 getNodes() { + return new ArrayList(clientNodes.values()); + } + + // + // PRIVATE METHODS + // + + /** + * Finds a currently unused high-level client, optionally waiting until a + * client is free and marking it used. + * + * @param wait + * true to wait for a free connection, + * false to return null + * @param markAsUsed + * true to mark the connection as used before + * returning it, false not to mark it + * @return An unused FCP connection, or null 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; + } + } + +}