diff --git a/src/main/java/net/torrent/protocol/peerwire/handler/PeerWireAlgorithmHandler.java b/src/main/java/net/torrent/protocol/peerwire/handler/PeerWireAlgorithmHandler.java
index 27e2e10..2713d82 100644
--- a/src/main/java/net/torrent/protocol/peerwire/handler/PeerWireAlgorithmHandler.java
+++ b/src/main/java/net/torrent/protocol/peerwire/handler/PeerWireAlgorithmHandler.java
@@ -58,6 +58,11 @@ import org.jboss.netty.handler.timeout.IdleStateEvent;
/**
* Standard handler responsible for forwarding calls to {@link TorrentAlgorithm}
* methods. This class handles low-level protocol specific behavior.
+ *
+ * The general guide line for this handler is to abstract ALL protocol
+ * specific models and use an abstracted algorithm for download. This will
+ * obviously limit the complexity of algorithm implementations. If that is the
+ * case, you are free to implement a new handler.
*
* @author Rogiel Josias Sulzbach
*/
diff --git a/src/main/java/net/torrent/protocol/peerwire/manager/ConnectionManager.java b/src/main/java/net/torrent/protocol/peerwire/manager/ConnectionManager.java
index 42ee6f7..a2c444c 100644
--- a/src/main/java/net/torrent/protocol/peerwire/manager/ConnectionManager.java
+++ b/src/main/java/net/torrent/protocol/peerwire/manager/ConnectionManager.java
@@ -25,7 +25,14 @@ import net.torrent.torrent.context.TorrentContext;
import org.jboss.netty.channel.Channel;
/**
- * Connection manager: manages active and inactive connections.
+ * Connection manager: keep control over active and inactive {@link Channel
+ * channel} connections.
+ *
+ * Please note that the manager actually does not make any decision nor create
+ * or block an connection.
+ *
+ * You can {@link Iterable iterate} over this manager to get active
+ * {@link Channel} instances.
*
* @author Rogiel Josias Sulzbach
*/
diff --git a/src/main/java/net/torrent/protocol/peerwire/manager/DownloadManager.java b/src/main/java/net/torrent/protocol/peerwire/manager/DownloadManager.java
index 9eecd4f..7ef9277 100644
--- a/src/main/java/net/torrent/protocol/peerwire/manager/DownloadManager.java
+++ b/src/main/java/net/torrent/protocol/peerwire/manager/DownloadManager.java
@@ -28,19 +28,60 @@ import net.torrent.torrent.TorrentPiece;
import net.torrent.torrent.context.TorrentContext;
import net.torrent.torrent.context.TorrentPeer;
+/**
+ * The download manager keep an track over current parts being downloaded at the
+ * moment.
+ *
+ * Please note that the manager actually does not make any decision nor block an
+ * requested piece.
+ *
+ * You can {@link Iterable iterate} over this manager to get current
+ * downloading {@link TorrentPart parts}.
+ *
+ * @author Rogiel Josias Sulzbach
+ */
+// TODO track pieces which have been requested for some time but never got an
+// REJECT (fast peer extensions) nor PIECE message (standard torrent
+// implementation does nothing when the peer is not uploading the piece)
+// TODO allow more then one peer per piece request
public class DownloadManager implements Iterable {
+ /**
+ * The torrent context
+ */
private final TorrentContext context;
-
+ /**
+ * The requested pieces not yet attended.
+ */
private final Map activeParts = new HashMap();
+ /**
+ * Creates a new instance
+ *
+ * @param context
+ * the torrent context
+ */
public DownloadManager(TorrentContext context) {
this.context = context;
}
- public boolean isDownloading(TorrentPart torrentPart) {
- return activeParts.containsKey(torrentPart);
+ /**
+ * Check if the given part has been requested.
+ *
+ * @param part
+ * the torrent part
+ * @return true if request message have been sent
+ */
+ public boolean isDownloading(TorrentPart part) {
+ return activeParts.containsKey(part);
}
+ /**
+ * Test if the given piece has been requested.
+ *
+ * @param piece
+ * the piece
+ * @return true if request message have been sent
+ */
public boolean isDownloading(TorrentPiece piece) {
for (final TorrentPart part : activeParts.keySet()) {
if (part.getPiece().equals(piece))
@@ -49,14 +90,35 @@ public class DownloadManager implements Iterable {
return false;
}
+ /**
+ * Check if the given peer is uploading something.
+ *
+ * @param peer
+ * the peer
+ * @return true if downloading from this peer
+ */
public boolean isDownloading(TorrentPeer peer) {
return activeParts.containsValue(peer);
}
- public TorrentPeer getPeer(TorrentPart torrentPart) {
- return activeParts.get(torrentPart);
+ /**
+ * Get the peer uploading part
+ *
+ * @param part
+ * the part
+ * @return the peer uploading the part
+ */
+ public TorrentPeer getPeer(TorrentPart part) {
+ return activeParts.get(part);
}
+ /**
+ * Get all parts being downloaded from the given peer
+ *
+ * @param peer
+ * the peer
+ * @return a set of pieces
+ */
public Set getTorrentParts(TorrentPeer peer) {
final Set parts = new HashSet();
for (final Entry entry : activeParts
@@ -67,18 +129,50 @@ public class DownloadManager implements Iterable {
return parts;
}
+ /**
+ * Test if there are no active pieces requests.
+ *
+ * @return true if no pending parts
+ */
public boolean isInactive() {
return activeParts.isEmpty();
}
- public TorrentPeer add(TorrentPart torrentPart, TorrentPeer peer) {
- return activeParts.put(torrentPart, peer);
+ /**
+ * Add a new part request
+ *
+ * @param part
+ * the part
+ * @param peer
+ * the remote peer
+ * @return the peer (java collections thing)
+ */
+ public TorrentPeer add(TorrentPart part, TorrentPeer peer) {
+ return activeParts.put(part, peer);
}
- public TorrentPeer remove(TorrentPart torrentPart) {
- return activeParts.remove(torrentPart);
+ /**
+ * Removes an part from this manager.
+ *
+ * @param part
+ * the part
+ * @return true if part was present before remove
+ */
+ public TorrentPeer remove(TorrentPart part) {
+ return activeParts.remove(part);
}
+ /**
+ * Remove all pieces request from the given peer.
+ *
+ * Note that since this implementation is decoupled from any protocol
+ * implementation, it will not cancel the request! This piece might arrive
+ * some time later.
+ *
+ * @param peer
+ * the peer
+ * @return a set containing pieces removed
+ */
public Set remove(TorrentPeer peer) {
final Set parts = new HashSet();
for (TorrentPart part : getTorrentParts(peer)) {
@@ -88,10 +182,20 @@ public class DownloadManager implements Iterable {
return parts;
}
+ /**
+ * Get the current active requests
+ *
+ * @return the current active requests
+ */
public int getActiveDownloadsCount() {
return activeParts.size();
}
+ /**
+ * Get an map containing each piece mapped to the peer uploading it.
+ *
+ * @return the map containing each piece mapped to the peer uploading it.
+ */
public Map getActiveDownloads() {
return Collections.unmodifiableMap(activeParts);
}
@@ -101,6 +205,11 @@ public class DownloadManager implements Iterable {
return activeParts.keySet().iterator();
}
+ /**
+ * Get the torrent context
+ *
+ * @return the torrent context
+ */
public TorrentContext getContext() {
return context;
}
diff --git a/src/main/java/net/torrent/protocol/peerwire/manager/PeerManager.java b/src/main/java/net/torrent/protocol/peerwire/manager/PeerManager.java
index bd621c5..5420dd3 100644
--- a/src/main/java/net/torrent/protocol/peerwire/manager/PeerManager.java
+++ b/src/main/java/net/torrent/protocol/peerwire/manager/PeerManager.java
@@ -29,19 +29,56 @@ import net.torrent.util.PeerCallback;
import org.jboss.netty.channel.Channel;
+/**
+ * The peer manager is used to keep control over active peers and they
+ * {@link Channel Netty Channel} used to write or read messages.
+ *
+ * Please note that the manager actually does not make any decision nor block an
+ * requested piece.
+ *
+ * You can {@link Iterable iterate} over this manager to get active
+ * {@link PeerWirePeer peers}.
+ */
public class PeerManager implements Iterable {
+ /**
+ * The torrent context
+ */
private final TorrentContext context;
+ /**
+ * The {@link ConnectionManager} instance
+ */
private final ConnectionManager connectionManager;
+ /**
+ * The map of active channel-peer mapping
+ */
private final Map activePeers = new HashMap();
+ /**
+ * The map of inactive channel-peer mapping
+ */
private final Map inactivePeers = new HashMap();
+ /**
+ * Creates a new instance
+ *
+ * @param context
+ * the torrent context
+ * @param connectionManager
+ * the connection manager instance
+ */
public PeerManager(TorrentContext context,
ConnectionManager connectionManager) {
this.context = context;
this.connectionManager = connectionManager;
}
+ /**
+ * Tests if the given channel has an peer attached to it.
+ *
+ * @param channel
+ * the channel
+ * @return true if an peer is attached
+ */
public boolean contains(Channel channel) {
if (activePeers.containsKey(channel))
return true;
@@ -50,6 +87,15 @@ public class PeerManager implements Iterable {
return false;
}
+ /**
+ * Tests if the current {@link PeerWirePeer} is registered in this manager.
+ * You will normally not have access to {@link PeerWirePeer} object, thus
+ * whis method might not be very useful outside handlers.
+ *
+ * @param peer
+ * the {@link PeerWirePeer} peer
+ * @return true if this peer is registered in this manager
+ */
public boolean contains(PeerWirePeer peer) {
if (activePeers.containsValue(peer))
return true;
@@ -58,6 +104,13 @@ public class PeerManager implements Iterable {
return false;
}
+ /**
+ * Get the {@link PeerWirePeer} registered in the given channel.
+ *
+ * @param channel
+ * the channel
+ * @return the peer instance.
+ */
public PeerWirePeer getPeer(Channel channel) {
PeerWirePeer peer = activePeers.get(channel);
if (peer == null)
@@ -65,6 +118,13 @@ public class PeerManager implements Iterable {
return peer;
}
+ /**
+ * Lookup for the {@link Channel} in which the peer is attached to.
+ *
+ * @param peer
+ * the peer
+ * @return the {@link Channel} for the given peer
+ */
public Channel getChannel(PeerWirePeer peer) {
for (final Entry entry : activePeers.entrySet()) {
if (entry.getValue().equals(peer))
@@ -78,10 +138,24 @@ public class PeerManager implements Iterable {
return null;
}
+ /**
+ * Test if there are no active peers in this manager.
+ *
+ * @return true if no active peers
+ */
public boolean isEmpty() {
return activePeers.isEmpty();
}
+ /**
+ * Adds a new peer to this manager.
+ *
+ * @param channel
+ * the channel
+ * @param peer
+ * the peer
+ * @return the {@link PeerWirePeer} created instance.
+ */
public PeerWirePeer add(Channel channel, TorrentPeer peer) {
if (channel.isConnected()) {
return activePeers.put(channel, new PeerWirePeer(channel, peer));
@@ -90,6 +164,13 @@ public class PeerManager implements Iterable {
}
}
+ /**
+ * Removes an {@link Channel} and its {@link TorrentPeer} from this manager.
+ *
+ * @param channel
+ * the channel
+ * @return the, now removed, {@link PeerWirePeer} instance
+ */
public PeerWirePeer remove(Channel channel) {
PeerWirePeer peer;
if ((peer = activePeers.remove(channel)) != null)
@@ -99,6 +180,13 @@ public class PeerManager implements Iterable {
return null;
}
+ /**
+ * Removes an {@link PeerWirePeer} from this manager.
+ *
+ * @param peer
+ * the peer
+ * @return the, now removed, {@link PeerWirePeer} instance
+ */
public PeerWirePeer remove(PeerWirePeer peer) {
final Channel channel = getChannel(peer);
PeerWirePeer peerRemoved;
@@ -109,6 +197,13 @@ public class PeerManager implements Iterable {
return null;
}
+ /**
+ * Updates this {@link Channel} peer state (i.e. active or inactive)
+ *
+ * @param channel
+ * the channel
+ * @return the {@link PeerWirePeer} instance updated
+ */
public PeerWirePeer update(Channel channel) {
PeerWirePeer peer;
if ((peer = remove(channel)) == null)
@@ -116,30 +211,66 @@ public class PeerManager implements Iterable {
return add(channel, peer.getTorrentPeer());
}
+ /**
+ * Get the total active peers
+ *
+ * @return the active peers count
+ */
public int getActivePeersCount() {
return activePeers.size();
}
+ /**
+ * Get the total inactive peers
+ *
+ * @return the inactive peers count
+ */
public int getImactivePeersCount() {
return activePeers.size();
}
+ /**
+ * Get an {@link Map} of all active peers
+ *
+ * @return the {@link Map} of all active peers
+ */
public Map getActivePeers() {
return Collections.unmodifiableMap(activePeers);
}
+ /**
+ * Get an {@link Map} of all inactive peers
+ *
+ * @return the {@link Map} of all inactive peers
+ */
public Map getInactivePeers() {
return Collections.unmodifiableMap(inactivePeers);
}
+ /**
+ * Get an {@link Set} of all active {@link Channel channels}
+ *
+ * @return the {@link Set} of all active {@link Channel channels}
+ */
public Set getActiveChannels() {
return Collections.unmodifiableSet(activePeers.keySet());
}
+ /**
+ * Get an {@link Set} of all inactive {@link Channel channels}
+ *
+ * @return the {@link Set} of all inactive {@link Channel channels}
+ */
public Set getInactiveChannels() {
return Collections.unmodifiableSet(inactivePeers.keySet());
}
+ /**
+ * Executes the callback for each active peer in this manager.
+ *
+ * @param callback
+ * the callback
+ */
public void executeActive(PeerCallback callback) {
for (final Entry entry : this.activePeers
.entrySet()) {
@@ -147,6 +278,12 @@ public class PeerManager implements Iterable {
}
}
+ /**
+ * Executes the callback for each inactive peer in this manager.
+ *
+ * @param callback
+ * the callback
+ */
public void executeInactive(PeerCallback callback) {
for (final Entry entry : this.inactivePeers
.entrySet()) {
@@ -154,6 +291,14 @@ public class PeerManager implements Iterable {
}
}
+ /**
+ * Executes the callback for each active and inactive peer in this
+ * manager. This method call firstly {@link #executeActive(PeerCallback)}
+ * and later {@link #executeInactive(PeerCallback)}.
+ *
+ * @param callback
+ * the callback
+ */
public void execute(PeerCallback callback) {
executeActive(callback);
executeInactive(callback);
@@ -164,10 +309,20 @@ public class PeerManager implements Iterable {
return activePeers.values().iterator();
}
+ /**
+ * Get the torrent context
+ *
+ * @return the torrent context
+ */
public TorrentContext getContext() {
return context;
}
+ /**
+ * Get the connection manager
+ *
+ * @return the connection manager
+ */
public ConnectionManager getConnectionManager() {
return connectionManager;
}
diff --git a/src/main/java/net/torrent/protocol/peerwire/manager/TorrentManager.java b/src/main/java/net/torrent/protocol/peerwire/manager/TorrentManager.java
index 7adb839..afc13cc 100644
--- a/src/main/java/net/torrent/protocol/peerwire/manager/TorrentManager.java
+++ b/src/main/java/net/torrent/protocol/peerwire/manager/TorrentManager.java
@@ -19,6 +19,13 @@ import net.torrent.protocol.datastore.TorrentDatastore;
import net.torrent.torrent.Torrent;
import net.torrent.torrent.context.TorrentContext;
+/**
+ * This is an simple class used to group up all managers for a single torrent.
+ * It does not do nothing special is just used to avoid incompatibility with
+ * handlers once a new manager is created.
+ *
+ * @author Rogiel Josias Sulzbach
+ */
public class TorrentManager {
private final TorrentContext context;
diff --git a/src/main/java/net/torrent/protocol/peerwire/manager/UploadManager.java b/src/main/java/net/torrent/protocol/peerwire/manager/UploadManager.java
index a0863ad..bfc239b 100644
--- a/src/main/java/net/torrent/protocol/peerwire/manager/UploadManager.java
+++ b/src/main/java/net/torrent/protocol/peerwire/manager/UploadManager.java
@@ -27,27 +27,99 @@ import net.torrent.torrent.TorrentPart;
import net.torrent.torrent.context.TorrentContext;
import net.torrent.torrent.context.TorrentPeer;
+/**
+ * The upload manager keep an track over current parts being uploaded at the
+ * moment. Notice that the part is remove right after the last byte is written,
+ * this is not a guarantee that the peer has received data nor that it is still
+ * alive.
+ *
+ * Please note that the manager actually does not make any decision nor declines
+ * an requested piece.
+ *
+ * You can {@link Iterable iterate} over this manager to get current
+ * uploading {@link TorrentPart parts}.
+ *
+ * FIXME BUG NOTICE: Note that this manager has an huge issue. When two
+ * or more peers request the very same part, only the latter will be maintained
+ * under control by this manager. This should be fixed soon and changes to the
+ * manager signature can occur. The affected methods are:
+ * {@link UploadManager#getPeer(TorrentPart)},
+ * {@link UploadManager#remove(TorrentPart)} and
+ * {@link UploadManager#getActiveUploads()}.
+ *
+ * @author Rogiel Josias Sulzbach
+ */
+// TODO track pieces which have been requested but the upload is not interesting
+// right now, but might be later.
+// FIXME this manager has an issue: if two peers request the same piece, only
+// the latter one will be managed! UploadManager#getPeer(TorrentPart part) needs
+// a fix.
public class UploadManager implements Iterable {
+ /**
+ * The torrent context
+ */
private final TorrentContext context;
-
+ /**
+ * An map of requested pieces. Only accepted pieces are registered.
+ */
private final Map activeParts = new HashMap();
+ /**
+ * Creates a new instance
+ *
+ * @param context
+ * the torrent context
+ */
public UploadManager(TorrentContext context) {
this.context = context;
}
- public boolean isUploading(TorrentPart torrentPart) {
- return activeParts.containsKey(torrentPart);
+ /**
+ * Test if the given part is being uploaded.
+ *
+ * @param part
+ * the part
+ * @return true if piece has been requested AND accepted.
+ */
+ public boolean isUploading(TorrentPart part) {
+ return activeParts.containsKey(part);
}
+ /**
+ * Test if uploads are being made to the given peer
+ *
+ * @param peer
+ * the peer
+ * @return true if at least one piece has been requested an piece AND
+ * the request was accepted
+ */
public boolean isUploading(TorrentPeer peer) {
return activeParts.containsValue(peer);
}
- public TorrentPeer getPeer(TorrentPart torrentPart) {
- return activeParts.get(torrentPart);
+ /**
+ * This method retrieve the peer which has requested the given
+ * piece.
+ *
+ * Note that this method has an huge issue: when two or more peers request
+ * the very same part (whichever piece), only the latter will be maintained
+ * under control by this manager. This need to be fixed soon and this method
+ * deprecated. You should avoid relying on it!
+ *
+ * @param part
+ * @return
+ */
+ public TorrentPeer getPeer(TorrentPart part) {
+ return activeParts.get(part);
}
+ /**
+ * Get the pieces being uploaded to the given peer
+ *
+ * @param peer
+ * the peer
+ * @return an {@link Set} of all parts being uploaded to this peer.
+ */
public Set getTorrentParts(TorrentPeer peer) {
final Set parts = new HashSet();
for (final Entry entry : activeParts
@@ -58,18 +130,51 @@ public class UploadManager implements Iterable {
return parts;
}
+ /**
+ * Tests if this manager has no active uploads.
+ *
+ * @return true if no uploads are being done
+ */
public boolean isInactive() {
return activeParts.isEmpty();
}
- public TorrentPeer add(TorrentPart torrentPart, TorrentPeer peer) {
- return activeParts.put(torrentPart, peer);
+ /**
+ * Adds a new part to this manager
+ *
+ * @param part
+ * the uploaded part
+ * @param peer
+ * the downloading peer
+ * @return the downloding {@link TorrentPeer}
+ */
+ public TorrentPeer add(TorrentPart part, TorrentPeer peer) {
+ return activeParts.put(part, peer);
}
- public TorrentPeer remove(TorrentPart torrentPart) {
- return activeParts.remove(torrentPart);
+ /**
+ * Removes the given part from this manager
+ *
+ * Note that this method has an huge issue: when two or more peers request
+ * the very same part (whichever piece), only the latter will be maintained
+ * under control by this manager. This need to be fixed soon and this method
+ * deprecated. You should avoid relying on it!
+ *
+ * @param part
+ * the part
+ * @return the downloading peer for the part
+ */
+ public TorrentPeer remove(TorrentPart part) {
+ return activeParts.remove(part);
}
+ /**
+ * Removes all uploads for the given peer
+ *
+ * @param peer
+ * the peer
+ * @return the set of {@link TorrentPart parts} being uploaded to that peer
+ */
public Set remove(TorrentPeer peer) {
final Set parts = new HashSet();
for (TorrentPart part : getTorrentParts(peer)) {
@@ -79,10 +184,25 @@ public class UploadManager implements Iterable {
return parts;
}
+ /**
+ * Get the amount of active uploads
+ *
+ * @return the count of active uploads
+ */
public int getActiveUploadsCount() {
return activeParts.size();
}
+ /**
+ * Get an {@link Map} of active uploads
+ *
+ * Note that this method has an huge issue: when two or more peers request
+ * the very same part (whichever piece), only the latter will be maintained
+ * under control by this manager. This need to be fixed soon and this method
+ * deprecated. You should avoid relying on it!
+ *
+ * @return an {@link Map} of active uploads
+ */
public Map getActiveUploads() {
return Collections.unmodifiableMap(activeParts);
}
@@ -92,6 +212,11 @@ public class UploadManager implements Iterable {
return activeParts.keySet().iterator();
}
+ /**
+ * Get the torrent context
+ *
+ * @return the torrent context
+ */
public TorrentContext getContext() {
return context;
}