X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fnet%2Fpterodactylus%2Fjsite%2Fcore%2FRequestManager.java;h=54ae5ac97ed5cba8e0ac9688692399321f9658e4;hb=eeea1af877d2a2e0f05d396718df58c2650ca2c3;hp=8f73b8d3a22cba89ee3cd13b808aa6f63e9b3744;hpb=d5afe3e2bde1f3a21cec6f3b3f1e57f7fdac3618;p=jSite2.git diff --git a/src/net/pterodactylus/jsite/core/RequestManager.java b/src/net/pterodactylus/jsite/core/RequestManager.java index 8f73b8d..54ae5ac 100644 --- a/src/net/pterodactylus/jsite/core/RequestManager.java +++ b/src/net/pterodactylus/jsite/core/RequestManager.java @@ -1,6 +1,6 @@ /* - * jSite2 - RequestManager.java - - * Copyright © 2008 David Roden + * jSite-next - RequestManager.java - + * Copyright © 2009 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 @@ -20,222 +20,176 @@ package net.pterodactylus.jsite.core; import java.io.IOException; -import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.List; +import java.util.HashSet; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; -import net.pterodactylus.fcp.highlevel.GetRequestResult; -import net.pterodactylus.fcp.highlevel.HighLevelCallback; -import net.pterodactylus.fcp.highlevel.HighLevelCallbackListener; -import net.pterodactylus.fcp.highlevel.HighLevelClient; -import net.pterodactylus.fcp.highlevel.HighLevelException; -import net.pterodactylus.fcp.highlevel.HighLevelProgress; -import net.pterodactylus.fcp.highlevel.HighLevelProgressListener; -import net.pterodactylus.fcp.highlevel.PutDirRequestResult; -import net.pterodactylus.fcp.highlevel.PutRequestResult; -import net.pterodactylus.fcp.highlevel.RequestListResult; -import net.pterodactylus.fcp.highlevel.RequestResult; -import net.pterodactylus.jsite.core.Request.Type; -import net.pterodactylus.util.logging.Logging; +import net.pterodactylus.fcp.highlevel.FcpClient; +import net.pterodactylus.fcp.highlevel.FcpException; +import net.pterodactylus.jsite.util.IdGenerator; +import net.pterodactylus.util.number.Hex; /** - * The request manager keeps track of all the request on all connected nodes. - * The request manager is added to the {@link NodeManager} as a - * {@link NodeListener} so that it can fire request-removed events in case a - * node is disconnected. - * - * @author David ‘Bombe’ Roden <bombe@freenetproject.org> - * @version $Id$ + * Manages requests. + * + * @author David ‘Bombe’ Roden */ -public class RequestManager implements NodeListener, HighLevelProgressListener { +public class RequestManager implements NodeListener { - /** Logger. */ - private static final Logger logger = Logging.getLogger(RequestManager.class.getName()); + /** The logger. */ + private static final Logger logger = Logger.getLogger(RequestManager.class.getName()); - /** Request listeners. */ - private List requestListeners = Collections.synchronizedList(new ArrayList()); + /** Request event manager. */ + private final RequestListenerManager requestListenerManager = new RequestListenerManager(); /** The node manager. */ - private NodeManager nodeManager; + private final NodeManager nodeManager; + + /** Maps request IDs to requests. */ + private final Map idRequests = Collections.synchronizedMap(new HashMap()); - /** Request lists for all nodes. */ - @SuppressWarnings("unused") - private Map> nodeRequests = Collections.synchronizedMap(new HashMap>()); + /** + * Creates a new request manager. + * + * @param nodeManager + * The node manager to utilize + */ + public RequestManager(NodeManager nodeManager) { + this.nodeManager = nodeManager; + } // - // EVENT MANAGEMENT + // LISTENER MANAGEMENT // /** - * Adds a request listener. - * + * Adds the given request listener to the list of registered listeners. + * + * @see RequestListenerManager#addListener(RequestListener) * @param requestListener * The request listener to add */ public void addRequestListener(RequestListener requestListener) { - requestListeners.add(requestListener); + requestListenerManager.addListener(requestListener); } /** - * Removes a request listener. - * + * Removes the given request listener from the list of registered listeners. + * + * @see RequestListenerManager#removeListener(RequestListener) * @param requestListener * The request listener to remove */ public void removeRequestListener(RequestListener requestListener) { - requestListeners.remove(requestListener); + requestListenerManager.removeListener(requestListener); } - /** - * Notifies all listeners that a request was added. - * - * @param request - * The request that was added - */ - private void fireRequestAdded(Request request) { - for (RequestListener requestListener: requestListeners) { - requestListener.requestAdded(request); - } - } + // + // ACTIONS + // - /** - * Notifies all listeners that a request progressed. - * - * @param request - * The request - */ - private void fireRequestProgressed(Request request) { - for (RequestListener requestListener: requestListeners) { - requestListener.requestProgressed(request); - } + public void load() throws IOException { } - /** - * Notifies all listeners that a request was removed. - * - * @param request - * The request that was removed - */ - private void fireRequestRemoved(Request request) { - for (RequestListener requestListener: requestListeners) { - requestListener.requestRemoved(request); - } + public void save() throws IOException { } /** - * Notifies all listeners that a request has finished. - * - * @see RequestListener#requestFinished(Request) - * @param request - * The request that has finished + * Starts inserting the given project. + * + * @param project + * The project to insert + * @throws JSiteException + * if the project’s node is not connected, or no node is + * connected at all */ - private void fireRequestFinished(Request request) { - for (RequestListener requestListener: requestListeners) { - requestListener.requestFinished(request); + public void insertProject(Project project) throws JSiteException { + Request request = new Request(); + request.setClientToken(generateClientToken(project)); + Node wantedNode = project.getNode(); + if (wantedNode == null) { + for (Node node : nodeManager.getNodes()) { + if (nodeManager.getFcpClient(node) != null) { + wantedNode = node; + break; + } + } } - } - - /** - * Notifies all listeners that a request has generated a URI. - * - * @see RequestListener#requestGeneratedURI(Request, String) - * @param request - * The request that has generated a URI - * @param uri - * The generated URI - */ - private void fireRequestGeneratedURI(Request request, String uri) { - for (RequestListener requestListener: requestListeners) { - requestListener.requestGeneratedURI(request, uri); + if (wantedNode == null) { + /* TODO use custom exception */ + throw new JSiteException("No node connected."); } + FcpClient fcpClient = nodeManager.getFcpClient(wantedNode); } // - // ACCESSORS + // PRIVATE METHODS // /** - * Sets the node manager to use. - * - * @param nodeManager - * The node manager + * Checks whether the given client token is a client token created by this + * request manager. + * + * @param clientToken + * The client token to check + * @return {@code true} if the client token was created by this request + * manager, {@code false} otherwise */ - public void setNodeManager(NodeManager nodeManager) { - this.nodeManager = nodeManager; + private boolean isKnownClientToken(String clientToken) { + String[] clientTokenParts = clientToken.split("\\."); + if (clientTokenParts.length != 3) { + return false; + } + String projectIdString = clientTokenParts[0]; + if (projectIdString.length() != (IdGenerator.DEFAULT_LENGTH * 2)) { + return false; + } + int clientTokenHashCode = -1; + try { + Hex.toByte(projectIdString); + Long.valueOf(clientTokenParts[1]); + clientTokenHashCode = Integer.valueOf(clientTokenParts[2]); + } catch (NumberFormatException nfe1) { + return false; + } + if ((clientTokenParts[0] + "." + clientTokenParts[1]).hashCode() != clientTokenHashCode) { + return false; + } + return true; } - // - // ACTIONS - // - - // - // PRIVATE ACTIONS - // - /** - * Requests a list of all running requests from a node. This method will - * block until the request has been sent! - * - * @param node - * The node to get all requests for - * @throws IOException - * if an I/O error occurs while communicating with the node - * @throws JSiteException - * if there is a problem with the node + * Generates a client token for the given project. + * + * @param project + * The project to generate a client token for + * @return The generated client token */ - private void getRequests(final Node node) throws IOException, JSiteException { - HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node); - if (highLevelClient == null) { - logger.log(Level.WARNING, "no client for node: " + node); - return; - } - final Map identifierRequests = Collections.synchronizedMap(new HashMap()); - nodeRequests.put(node, identifierRequests); - HighLevelCallback requestListCallback; - try { - requestListCallback = highLevelClient.getRequests(); - requestListCallback.addHighLevelCallbackListener(new HighLevelCallbackListener() { + public String generateClientToken(Project project) { + String clientToken = project.getId() + "." + System.currentTimeMillis(); + clientToken += "." + clientToken.hashCode(); + return clientToken; + } - @SuppressWarnings("synthetic-access") - public void gotResult(HighLevelCallback highLevelCallback) { - RequestListResult requestListResult; - try { - requestListResult = highLevelCallback.getResult(); - } catch (InterruptedException e) { - logger.log(Level.SEVERE, "getResult() blocked and was interrupted"); - return; - } - for (RequestResult requestResult: requestListResult) { - String identifier = requestResult.getIdentifier(); - logger.log(Level.FINER, "got identifier: " + identifier); - Request request = identifierRequests.get(identifier); - if (request == null) { - request = new Request(node, identifier); - } - if (request.getType() == null) { - if (requestResult instanceof GetRequestResult) { - request.setType(Type.get); - } else if (requestResult instanceof PutRequestResult) { - request.setType(Type.put); - } else if (requestResult instanceof PutDirRequestResult) { - request.setType(Type.putDir); - } - } - if (identifierRequests.containsKey(identifier)) { - continue; - } - identifierRequests.put(requestResult.getIdentifier(), request); - fireRequestAdded(request); - } - } - }); - } catch (HighLevelException hle1) { - throw new BackendException(hle1); - } + /** + * Wraps the requests of the FCP API into jSite requests. + * + * @param requests + * The requests to wrap + * @return The wrapped requests + */ + private Collection wrapRequests(Collection requests) { + Collection wrappedRequests = new HashSet(); + for (net.pterodactylus.fcp.highlevel.Request request : requests) { + Request wrappedRequest = new Request(request.getIdentifier()); + wrappedRequest.setClientToken(request.getClientToken()); + wrappedRequests.add(wrappedRequest); + } + return wrappedRequests; } // @@ -246,44 +200,34 @@ public class RequestManager implements NodeListener, HighLevelProgressListener { * {@inheritDoc} */ public void nodeAdded(Node node) { - HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node); - if (highLevelClient == null) { - logger.warning("got nodeAdded but no high-level client: " + node); - return; - } - highLevelClient.addHighLevelProgressListener(this); - } - - /** - * {@inheritDoc} - */ - public void nodeRemoved(Node node) { - HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node); - if (highLevelClient == null) { - logger.warning("got nodeRemoved but no high-level client: " + node); - return; - } - highLevelClient.removeHighLevelProgressListener(this); + /* ignore. */ } /** * {@inheritDoc} */ public void nodeConnected(Node node) { - HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node); - if (highLevelClient == null) { - logger.log(Level.WARNING, "got no high-level client for node " + node); + FcpClient fcpClient = nodeManager.getFcpClient(node); + if (fcpClient == null) { + logger.log(Level.WARNING, "Got no FCP client for node (" + node + ")!"); return; } try { - highLevelClient.setWatchGlobal(true); - getRequests(node); - } catch (HighLevelException hle1) { - logger.log(Level.WARNING, "error in backend", hle1); - } catch (JSiteException jse1) { - logger.log(Level.WARNING, "error in backend", jse1); - } catch (IOException e) { - /* ignore exception, disconnects are handled elsewhere. */ + Collection requests = wrapRequests(fcpClient.getRequests(true)); + for (Request request : requests) { + String clientToken = request.getClientToken(); + if ((clientToken == null) || (clientToken.trim().length() == 0)) { + continue; + } + if (!isKnownClientToken(clientToken)) { + continue; + } + /* TODO - process request. */ + } + } catch (IOException ioe1) { + logger.log(Level.WARNING, "Could not get requests from node (" + node + ")!", ioe1); + } catch (FcpException fe1) { + logger.log(Level.WARNING, "Could not get requests from node (" + node + ")!", fe1); } } @@ -291,69 +235,21 @@ public class RequestManager implements NodeListener, HighLevelProgressListener { * {@inheritDoc} */ public void nodeConnectionFailed(Node node, Throwable cause) { - /* we don't care about this. */ + /* ignore. */ } /** * {@inheritDoc} */ public void nodeDisconnected(Node node, Throwable throwable) { - Map identifierRequests = nodeRequests.get(node); - if (identifierRequests == null) { - logger.warning("got node without request map: " + node); - return; - } - for (Request request: identifierRequests.values()) { - fireRequestRemoved(request); - } - identifierRequests.clear(); + /* TODO */ } - // - // INTERFACE HighLevelProgressListener - // - /** - * @see net.pterodactylus.fcp.highlevel.HighLevelProgressListener#progressReceived(HighLevelClient, - * String, HighLevelProgress) + * {@inheritDoc} */ - public void progressReceived(HighLevelClient highLevelClient, String identifier, HighLevelProgress highLevelProgress) { - Node node = nodeManager.getNode(highLevelClient); - if (node == null) { - logger.warning("got high-level client without node: " + highLevelClient); - return; - } - Map identifierRequests = nodeRequests.get(node); - if (identifierRequests == null) { - logger.warning("got node without request map: " + node); - identifierRequests = Collections.synchronizedMap(new HashMap()); - nodeRequests.put(node, identifierRequests); - } - Request request = identifierRequests.get(identifier); - if (request == null) { - logger.warning("got progress for unknown request: " + identifier); - request = new Request(node, identifier); - identifierRequests.put(identifier, request); - fireRequestAdded(request); - } - if (highLevelProgress.isFinished()) { - request.setFinished(true); - request.setSuccessful(!highLevelProgress.isFailed()); - fireRequestFinished(request); - } else if (highLevelProgress.isFetchable()) { - /* TODO - ignore? */ - } else if (highLevelProgress.getURI() != null) { - request.setURI(highLevelProgress.getURI()); - fireRequestGeneratedURI(request, highLevelProgress.getURI()); - } else { - request.setTotalBlocks(highLevelProgress.getTotalBlocks()); - request.setRequiredBlocks(highLevelProgress.getRequiredBlocks()); - request.setSuccessfulBlocks(highLevelProgress.getSuccessfulBlocks()); - request.setFailedBlocks(highLevelProgress.getFailedBlocks()); - request.setFatallyFailedBlocks(highLevelProgress.getFatallyFailedBlocks()); - request.setTotalFinalized(highLevelProgress.isTotalFinalized()); - fireRequestProgressed(request); - } + public void nodeRemoved(Node node) { + /* ignore. */ } }