002cd17748ecbf4f5ac60d56054148786daf59d8
[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.Set;
29 import java.util.logging.Level;
30 import java.util.logging.Logger;
31
32 import net.pterodactylus.fcp.highlevel.HighLevelCallback;
33 import net.pterodactylus.fcp.highlevel.HighLevelCallbackListener;
34 import net.pterodactylus.fcp.highlevel.HighLevelClient;
35 import net.pterodactylus.fcp.highlevel.HighLevelProgress;
36 import net.pterodactylus.fcp.highlevel.HighLevelProgressListener;
37 import net.pterodactylus.fcp.highlevel.RequestListResult;
38 import net.pterodactylus.fcp.highlevel.RequestResult;
39 import net.pterodactylus.util.logging.Logging;
40
41 /**
42  * The request manager keeps track of all the request on all connected nodes.
43  * The request manager is added to the {@link NodeManager} as a
44  * {@link NodeListener} so that it can fire request-removed events in case a
45  * node is disconnected.
46  * 
47  * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
48  * @version $Id$
49  */
50 public class RequestManager implements NodeListener, HighLevelProgressListener {
51
52         /** Logger. */
53         private static final Logger logger = Logging.getLogger(RequestManager.class.getName());
54
55         /** Request listeners. */
56         private List<RequestListener> requestListeners = Collections.synchronizedList(new ArrayList<RequestListener>());
57
58         /** The node manager. */
59         private NodeManager nodeManager;
60
61         /** Request lists for all nodes. */
62         @SuppressWarnings("unused")
63         private Map<Node, Set<Request>> nodeRequests = Collections.synchronizedMap(new HashMap<Node, Set<Request>>());
64
65         //
66         // EVENT MANAGEMENT
67         //
68
69         /**
70          * Adds a request listener.
71          * 
72          * @param requestListener
73          *            The request listener to add
74          */
75         public void addRequestListener(RequestListener requestListener) {
76                 requestListeners.add(requestListener);
77         }
78
79         /**
80          * Removes a request listener.
81          * 
82          * @param requestListener
83          *            The request listener to remove
84          */
85         public void removeRequestListener(RequestListener requestListener) {
86                 requestListeners.remove(requestListener);
87         }
88
89         /**
90          * Notifies all listeners that a request was added.
91          * 
92          * @param node
93          *            The node that added the request
94          * @param request
95          *            The request that was added
96          */
97         private void fireRequestAdded(Node node, Request request) {
98                 for (RequestListener requestListener: requestListeners) {
99                         requestListener.requestAdded(node, request);
100                 }
101         }
102
103         /**
104          * Notifies all listeners that a request progressed.
105          * 
106          * @param node
107          *            The node that runs the request
108          * @param request
109          *            The request
110          * @param totalBlocks
111          *            The total number of blocks
112          * @param requiredBlocks
113          *            The number of required blocks
114          * @param successfulBlocks
115          *            The number of successful blocks
116          * @param failedBlocks
117          *            The number of failed blocks
118          * @param fatallyFailedBlocks
119          *            The number of fatally failed blocks
120          * @param finalizedTotal
121          *            <code>true</code> if the total number of blocks in final,
122          *            <code>false</code> otherwise
123          */
124         private void fireRequestProgressed(Node node, Request request, int totalBlocks, int requiredBlocks, int successfulBlocks, int failedBlocks, int fatallyFailedBlocks, boolean finalizedTotal) {
125                 for (RequestListener requestListener: requestListeners) {
126                         requestListener.requestProgressed(node, request, totalBlocks, requiredBlocks, successfulBlocks, failedBlocks, fatallyFailedBlocks, finalizedTotal);
127                 }
128         }
129
130         //
131         // ACCESSORS
132         //
133
134         /**
135          * Sets the node manager to use.
136          * 
137          * @param nodeManager
138          *            The node manager
139          */
140         public void setNodeManager(NodeManager nodeManager) {
141                 this.nodeManager = nodeManager;
142         }
143
144         //
145         // ACTIONS
146         //
147
148         //
149         // PRIVATE ACTIONS
150         //
151
152         /**
153          * Requests a list of all running requests from a node. This method will
154          * block until the request has been sent!
155          * 
156          * @param node
157          *            The node to get all requests for
158          * @throws IOException
159          *             if an I/O error occurs while communicating with the node
160          */
161         private void getRequests(final Node node) throws IOException {
162                 HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node);
163                 if (highLevelClient == null) {
164                         logger.log(Level.WARNING, "no client for node: " + node);
165                         return;
166                 }
167                 HighLevelCallback<RequestListResult> requestListCallback = highLevelClient.getRequests();
168                 requestListCallback.addHighLevelCallbackListener(new HighLevelCallbackListener<RequestListResult>() {
169
170                         @SuppressWarnings("synthetic-access")
171                         public void gotResult(HighLevelCallback<RequestListResult> highLevelCallback) {
172                                 RequestListResult requestListResult;
173                                 try {
174                                         requestListResult = highLevelCallback.getResult();
175                                 } catch (InterruptedException e) {
176                                         logger.log(Level.SEVERE, "getResult() blocked and was interrupted");
177                                         return;
178                                 }
179                                 for (RequestResult requestResult: requestListResult) {
180                                         Request request = new Request(requestResult.getIdentifier());
181                                         /* TODO - fill request */
182                                         fireRequestAdded(node, request);
183                                 }
184                         }
185                 });
186         }
187
188         //
189         // INTERFACE NodeListener
190         //
191
192         /**
193          * {@inheritDoc}
194          */
195         public void nodeAdded(Node node) {
196                 HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node);
197                 if (highLevelClient == null) {
198                         logger.warning("got nodeAdded but no high-level client: " + node);
199                         return;
200                 }
201                 highLevelClient.addHighLevelProgressListener(this);
202         }
203
204         /**
205          * {@inheritDoc}
206          */
207         public void nodeRemoved(Node node) {
208                 HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node);
209                 if (highLevelClient == null) {
210                         logger.warning("got nodeRemoved but no high-level client: " + node);
211                         return;
212                 }
213                 highLevelClient.removeHighLevelProgressListener(this);
214         }
215
216         /**
217          * {@inheritDoc}
218          */
219         public void nodeConnected(Node node) {
220                 HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node);
221                 if (highLevelClient == null) {
222                         logger.log(Level.WARNING, "got no high-level client for node " + node);
223                         return;
224                 }
225                 try {
226                         highLevelClient.setWatchGlobal(true);
227                         getRequests(node);
228                 } catch (IOException e) {
229                         /* ignore exception, disconnects are handled elsewhere. */
230                 }
231         }
232
233         /**
234          * {@inheritDoc}
235          */
236         public void nodeConnectionFailed(Node node, Throwable cause) {
237                 /* we don't care about this. */
238         }
239
240         /**
241          * {@inheritDoc}
242          */
243         public void nodeDisconnected(Node node, Throwable throwable) {
244                 HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node);
245                 if (highLevelClient == null) {
246                         logger.warning("got nodeDisconnected from node without high-level client: " + node);
247                         return;
248                 }
249         }
250
251         //
252         // INTERFACE HighLevelProgressListener
253         //
254
255         /**
256          * @see net.pterodactylus.fcp.highlevel.HighLevelProgressListener#progressReceived(java.lang.String,
257          *      net.pterodactylus.fcp.highlevel.HighLevelProgress)
258          */
259         public void progressReceived(String identifier, HighLevelProgress highLevelProgress) {
260                 fireRequestProgressed(null, new Request(identifier), highLevelProgress.getTotalBlocks(), highLevelProgress.getRequiredBlocks(), highLevelProgress.getSuccessfulBlocks(), highLevelProgress.getFailedBlocks(), highLevelProgress.getFatallyFailedBlocks(), highLevelProgress.isTotalFinalized());
261         }
262
263 }