first version of request table
[jSite2.git] / src / net / pterodactylus / jsite / core / RequestManager.java
1 /*
2  * jSite2 - RequestManager.java -
3  * Copyright © 2008 David Roden
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 package net.pterodactylus.jsite.core;
21
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.logging.Level;
29 import java.util.logging.Logger;
30
31 import net.pterodactylus.fcp.highlevel.HighLevelCallback;
32 import net.pterodactylus.fcp.highlevel.HighLevelCallbackListener;
33 import net.pterodactylus.fcp.highlevel.HighLevelClient;
34 import net.pterodactylus.fcp.highlevel.HighLevelProgress;
35 import net.pterodactylus.fcp.highlevel.HighLevelProgressListener;
36 import net.pterodactylus.fcp.highlevel.RequestListResult;
37 import net.pterodactylus.fcp.highlevel.RequestResult;
38 import net.pterodactylus.util.logging.Logging;
39
40 /**
41  * The request manager keeps track of all the request on all connected nodes.
42  * The request manager is added to the {@link NodeManager} as a
43  * {@link NodeListener} so that it can fire request-removed events in case a
44  * node is disconnected.
45  * 
46  * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
47  * @version $Id$
48  */
49 public class RequestManager implements NodeListener, HighLevelProgressListener {
50
51         /** Logger. */
52         private static final Logger logger = Logging.getLogger(RequestManager.class.getName());
53
54         /** Request listeners. */
55         private List<RequestListener> requestListeners = Collections.synchronizedList(new ArrayList<RequestListener>());
56
57         /** The node manager. */
58         private NodeManager nodeManager;
59
60         /** Request lists for all nodes. */
61         @SuppressWarnings("unused")
62         private Map<Node, Map<String, Request>> nodeRequests = Collections.synchronizedMap(new HashMap<Node, Map<String, Request>>());
63
64         //
65         // EVENT MANAGEMENT
66         //
67
68         /**
69          * Adds a request listener.
70          * 
71          * @param requestListener
72          *            The request listener to add
73          */
74         public void addRequestListener(RequestListener requestListener) {
75                 requestListeners.add(requestListener);
76         }
77
78         /**
79          * Removes a request listener.
80          * 
81          * @param requestListener
82          *            The request listener to remove
83          */
84         public void removeRequestListener(RequestListener requestListener) {
85                 requestListeners.remove(requestListener);
86         }
87
88         /**
89          * Notifies all listeners that a request was added.
90          * 
91          * @param request
92          *            The request that was added
93          */
94         private void fireRequestAdded(Request request) {
95                 for (RequestListener requestListener: requestListeners) {
96                         requestListener.requestAdded(request);
97                 }
98         }
99
100         /**
101          * Notifies all listeners that a request progressed.
102          * 
103          * @param request
104          *            The request
105          */
106         private void fireRequestProgressed(Request request) {
107                 for (RequestListener requestListener: requestListeners) {
108                         requestListener.requestProgressed(request);
109                 }
110         }
111
112         // TODO - fireRequestRemoved
113
114         //
115         // ACCESSORS
116         //
117
118         /**
119          * Sets the node manager to use.
120          * 
121          * @param nodeManager
122          *            The node manager
123          */
124         public void setNodeManager(NodeManager nodeManager) {
125                 this.nodeManager = nodeManager;
126         }
127
128         //
129         // ACTIONS
130         //
131
132         //
133         // PRIVATE ACTIONS
134         //
135
136         /**
137          * Requests a list of all running requests from a node. This method will
138          * block until the request has been sent!
139          * 
140          * @param node
141          *            The node to get all requests for
142          * @throws IOException
143          *             if an I/O error occurs while communicating with the node
144          */
145         private void getRequests(final Node node) throws IOException {
146                 HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node);
147                 if (highLevelClient == null) {
148                         logger.log(Level.WARNING, "no client for node: " + node);
149                         return;
150                 }
151                 final Map<String, Request> identifierRequests = new HashMap<String, Request>();
152                 nodeRequests.put(node, identifierRequests);
153                 HighLevelCallback<RequestListResult> requestListCallback = highLevelClient.getRequests();
154                 requestListCallback.addHighLevelCallbackListener(new HighLevelCallbackListener<RequestListResult>() {
155
156                         @SuppressWarnings("synthetic-access")
157                         public void gotResult(HighLevelCallback<RequestListResult> highLevelCallback) {
158                                 RequestListResult requestListResult;
159                                 try {
160                                         requestListResult = highLevelCallback.getResult();
161                                 } catch (InterruptedException e) {
162                                         logger.log(Level.SEVERE, "getResult() blocked and was interrupted");
163                                         return;
164                                 }
165                                 for (RequestResult requestResult: requestListResult) {
166                                         Request request = new Request(node, requestResult.getIdentifier());
167                                         identifierRequests.put(requestResult.getIdentifier(), request);
168                                         /* TODO - fill request */
169                                         fireRequestAdded(request);
170                                 }
171                         }
172                 });
173         }
174
175         //
176         // INTERFACE NodeListener
177         //
178
179         /**
180          * {@inheritDoc}
181          */
182         public void nodeAdded(Node node) {
183                 HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node);
184                 if (highLevelClient == null) {
185                         logger.warning("got nodeAdded but no high-level client: " + node);
186                         return;
187                 }
188                 highLevelClient.addHighLevelProgressListener(this);
189         }
190
191         /**
192          * {@inheritDoc}
193          */
194         public void nodeRemoved(Node node) {
195                 HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node);
196                 if (highLevelClient == null) {
197                         logger.warning("got nodeRemoved but no high-level client: " + node);
198                         return;
199                 }
200                 highLevelClient.removeHighLevelProgressListener(this);
201         }
202
203         /**
204          * {@inheritDoc}
205          */
206         public void nodeConnected(Node node) {
207                 HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node);
208                 if (highLevelClient == null) {
209                         logger.log(Level.WARNING, "got no high-level client for node " + node);
210                         return;
211                 }
212                 try {
213                         highLevelClient.setWatchGlobal(true);
214                         getRequests(node);
215                 } catch (IOException e) {
216                         /* ignore exception, disconnects are handled elsewhere. */
217                 }
218         }
219
220         /**
221          * {@inheritDoc}
222          */
223         public void nodeConnectionFailed(Node node, Throwable cause) {
224                 /* we don't care about this. */
225         }
226
227         /**
228          * {@inheritDoc}
229          */
230         public void nodeDisconnected(Node node, Throwable throwable) {
231                 HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node);
232                 if (highLevelClient == null) {
233                         logger.warning("got nodeDisconnected from node without high-level client: " + node);
234                         return;
235                 }
236         }
237
238         //
239         // INTERFACE HighLevelProgressListener
240         //
241
242         /**
243          * @see net.pterodactylus.fcp.highlevel.HighLevelProgressListener#progressReceived(HighLevelClient,
244          *      String, HighLevelProgress)
245          */
246         public void progressReceived(HighLevelClient highLevelClient, String identifier, HighLevelProgress highLevelProgress) {
247                 Node node = nodeManager.getNode(highLevelClient);
248                 if (node == null) {
249                         logger.warning("got high-level client without node: " + highLevelClient);
250                         return;
251                 }
252                 Map<String, Request> identifierRequests = nodeRequests.get(node);
253                 if (identifierRequests == null) {
254                         logger.warning("got node without request map: " + node);
255                         return;
256                 }
257                 Request request = identifierRequests.get(identifier);
258                 if (request == null) {
259                         logger.warning("got progress for unknown request: " + identifier);
260                         return;
261                 }
262                 request.setTotalBlocks(highLevelProgress.getTotalBlocks());
263                 request.setRequiredBlocks(highLevelProgress.getRequiredBlocks());
264                 request.setSuccessfulBlocks(highLevelProgress.getSuccessfulBlocks());
265                 request.setFailedBlocks(highLevelProgress.getFailedBlocks());
266                 request.setFatallyFailedBlocks(highLevelProgress.getFatallyFailedBlocks());
267                 request.setTotalFinalized(highLevelProgress.isTotalFinalized());
268                 fireRequestProgressed(request);
269         }
270
271 }