mirror of
https://github.com/Rogiel/torrent4j
synced 2025-12-06 07:32:47 +00:00
Manager javadoc
Change-Id: I431ac866b1b55dbf570c231d90129d89e522d0b9
This commit is contained in:
@@ -58,6 +58,11 @@ import org.jboss.netty.handler.timeout.IdleStateEvent;
|
|||||||
/**
|
/**
|
||||||
* Standard handler responsible for forwarding calls to {@link TorrentAlgorithm}
|
* Standard handler responsible for forwarding calls to {@link TorrentAlgorithm}
|
||||||
* methods. This class handles low-level protocol specific behavior.
|
* methods. This class handles low-level protocol specific behavior.
|
||||||
|
* <p>
|
||||||
|
* The general guide line for this handler is to abstract <b>ALL</b> 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 <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -25,7 +25,14 @@ import net.torrent.torrent.context.TorrentContext;
|
|||||||
import org.jboss.netty.channel.Channel;
|
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.
|
||||||
|
* <p>
|
||||||
|
* Please note that the manager actually does not make any decision nor create
|
||||||
|
* or block an connection.
|
||||||
|
* <p>
|
||||||
|
* You can {@link Iterable iterate} over this manager to get <b>active</b>
|
||||||
|
* {@link Channel} instances.
|
||||||
*
|
*
|
||||||
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -28,19 +28,60 @@ import net.torrent.torrent.TorrentPiece;
|
|||||||
import net.torrent.torrent.context.TorrentContext;
|
import net.torrent.torrent.context.TorrentContext;
|
||||||
import net.torrent.torrent.context.TorrentPeer;
|
import net.torrent.torrent.context.TorrentPeer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The download manager keep an track over current parts being downloaded at the
|
||||||
|
* moment.
|
||||||
|
* <p>
|
||||||
|
* Please note that the manager actually does not make any decision nor block an
|
||||||
|
* requested piece.
|
||||||
|
* <p>
|
||||||
|
* You can {@link Iterable iterate} over this manager to get <b>current</b>
|
||||||
|
* downloading {@link TorrentPart parts}.
|
||||||
|
*
|
||||||
|
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||||
|
*/
|
||||||
|
// 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<TorrentPart> {
|
public class DownloadManager implements Iterable<TorrentPart> {
|
||||||
|
/**
|
||||||
|
* The torrent context
|
||||||
|
*/
|
||||||
private final TorrentContext context;
|
private final TorrentContext context;
|
||||||
|
/**
|
||||||
|
* The requested pieces not yet attended.
|
||||||
|
*/
|
||||||
private final Map<TorrentPart, TorrentPeer> activeParts = new HashMap<TorrentPart, TorrentPeer>();
|
private final Map<TorrentPart, TorrentPeer> activeParts = new HashMap<TorrentPart, TorrentPeer>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* the torrent context
|
||||||
|
*/
|
||||||
public DownloadManager(TorrentContext context) {
|
public DownloadManager(TorrentContext context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDownloading(TorrentPart torrentPart) {
|
/**
|
||||||
return activeParts.containsKey(torrentPart);
|
* Check if the given <tt>part</tt> 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 <tt>piece</tt> has been requested.
|
||||||
|
*
|
||||||
|
* @param piece
|
||||||
|
* the piece
|
||||||
|
* @return true if request message have been sent
|
||||||
|
*/
|
||||||
public boolean isDownloading(TorrentPiece piece) {
|
public boolean isDownloading(TorrentPiece piece) {
|
||||||
for (final TorrentPart part : activeParts.keySet()) {
|
for (final TorrentPart part : activeParts.keySet()) {
|
||||||
if (part.getPiece().equals(piece))
|
if (part.getPiece().equals(piece))
|
||||||
@@ -49,14 +90,35 @@ public class DownloadManager implements Iterable<TorrentPart> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given <tt>peer</tt> is uploading something.
|
||||||
|
*
|
||||||
|
* @param peer
|
||||||
|
* the peer
|
||||||
|
* @return true if downloading from this peer
|
||||||
|
*/
|
||||||
public boolean isDownloading(TorrentPeer peer) {
|
public boolean isDownloading(TorrentPeer peer) {
|
||||||
return activeParts.containsValue(peer);
|
return activeParts.containsValue(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TorrentPeer getPeer(TorrentPart torrentPart) {
|
/**
|
||||||
return activeParts.get(torrentPart);
|
* Get the peer uploading <tt>part</tt>
|
||||||
|
*
|
||||||
|
* @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 <tt>peer</tt>
|
||||||
|
*
|
||||||
|
* @param peer
|
||||||
|
* the peer
|
||||||
|
* @return a set of pieces
|
||||||
|
*/
|
||||||
public Set<TorrentPart> getTorrentParts(TorrentPeer peer) {
|
public Set<TorrentPart> getTorrentParts(TorrentPeer peer) {
|
||||||
final Set<TorrentPart> parts = new HashSet<TorrentPart>();
|
final Set<TorrentPart> parts = new HashSet<TorrentPart>();
|
||||||
for (final Entry<TorrentPart, TorrentPeer> entry : activeParts
|
for (final Entry<TorrentPart, TorrentPeer> entry : activeParts
|
||||||
@@ -67,18 +129,50 @@ public class DownloadManager implements Iterable<TorrentPart> {
|
|||||||
return parts;
|
return parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if there are no active pieces requests.
|
||||||
|
*
|
||||||
|
* @return true if no pending parts
|
||||||
|
*/
|
||||||
public boolean isInactive() {
|
public boolean isInactive() {
|
||||||
return activeParts.isEmpty();
|
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 <tt>peer</tt>.
|
||||||
|
* <p>
|
||||||
|
* 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<TorrentPart> remove(TorrentPeer peer) {
|
public Set<TorrentPart> remove(TorrentPeer peer) {
|
||||||
final Set<TorrentPart> parts = new HashSet<TorrentPart>();
|
final Set<TorrentPart> parts = new HashSet<TorrentPart>();
|
||||||
for (TorrentPart part : getTorrentParts(peer)) {
|
for (TorrentPart part : getTorrentParts(peer)) {
|
||||||
@@ -88,10 +182,20 @@ public class DownloadManager implements Iterable<TorrentPart> {
|
|||||||
return parts;
|
return parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current active requests
|
||||||
|
*
|
||||||
|
* @return the current active requests
|
||||||
|
*/
|
||||||
public int getActiveDownloadsCount() {
|
public int getActiveDownloadsCount() {
|
||||||
return activeParts.size();
|
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<TorrentPart, TorrentPeer> getActiveDownloads() {
|
public Map<TorrentPart, TorrentPeer> getActiveDownloads() {
|
||||||
return Collections.unmodifiableMap(activeParts);
|
return Collections.unmodifiableMap(activeParts);
|
||||||
}
|
}
|
||||||
@@ -101,6 +205,11 @@ public class DownloadManager implements Iterable<TorrentPart> {
|
|||||||
return activeParts.keySet().iterator();
|
return activeParts.keySet().iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the torrent context
|
||||||
|
*
|
||||||
|
* @return the torrent context
|
||||||
|
*/
|
||||||
public TorrentContext getContext() {
|
public TorrentContext getContext() {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,19 +29,56 @@ import net.torrent.util.PeerCallback;
|
|||||||
|
|
||||||
import org.jboss.netty.channel.Channel;
|
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.
|
||||||
|
* <p>
|
||||||
|
* Please note that the manager actually does not make any decision nor block an
|
||||||
|
* requested piece.
|
||||||
|
* <p>
|
||||||
|
* You can {@link Iterable iterate} over this manager to get <b>active</b>
|
||||||
|
* {@link PeerWirePeer peers}.
|
||||||
|
*/
|
||||||
public class PeerManager implements Iterable<PeerWirePeer> {
|
public class PeerManager implements Iterable<PeerWirePeer> {
|
||||||
|
/**
|
||||||
|
* The torrent context
|
||||||
|
*/
|
||||||
private final TorrentContext context;
|
private final TorrentContext context;
|
||||||
|
/**
|
||||||
|
* The {@link ConnectionManager} instance
|
||||||
|
*/
|
||||||
private final ConnectionManager connectionManager;
|
private final ConnectionManager connectionManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The map of active channel-peer mapping
|
||||||
|
*/
|
||||||
private final Map<Channel, PeerWirePeer> activePeers = new HashMap<Channel, PeerWirePeer>();
|
private final Map<Channel, PeerWirePeer> activePeers = new HashMap<Channel, PeerWirePeer>();
|
||||||
|
/**
|
||||||
|
* The map of inactive channel-peer mapping
|
||||||
|
*/
|
||||||
private final Map<Channel, PeerWirePeer> inactivePeers = new HashMap<Channel, PeerWirePeer>();
|
private final Map<Channel, PeerWirePeer> inactivePeers = new HashMap<Channel, PeerWirePeer>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* the torrent context
|
||||||
|
* @param connectionManager
|
||||||
|
* the connection manager instance
|
||||||
|
*/
|
||||||
public PeerManager(TorrentContext context,
|
public PeerManager(TorrentContext context,
|
||||||
ConnectionManager connectionManager) {
|
ConnectionManager connectionManager) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.connectionManager = connectionManager;
|
this.connectionManager = connectionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if the given <tt>channel</tt> has an peer attached to it.
|
||||||
|
*
|
||||||
|
* @param channel
|
||||||
|
* the channel
|
||||||
|
* @return true if an peer is attached
|
||||||
|
*/
|
||||||
public boolean contains(Channel channel) {
|
public boolean contains(Channel channel) {
|
||||||
if (activePeers.containsKey(channel))
|
if (activePeers.containsKey(channel))
|
||||||
return true;
|
return true;
|
||||||
@@ -50,6 +87,15 @@ public class PeerManager implements Iterable<PeerWirePeer> {
|
|||||||
return false;
|
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 <tt>peer</tt> is registered in this manager
|
||||||
|
*/
|
||||||
public boolean contains(PeerWirePeer peer) {
|
public boolean contains(PeerWirePeer peer) {
|
||||||
if (activePeers.containsValue(peer))
|
if (activePeers.containsValue(peer))
|
||||||
return true;
|
return true;
|
||||||
@@ -58,6 +104,13 @@ public class PeerManager implements Iterable<PeerWirePeer> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@link PeerWirePeer} registered in the given <tt>channel</tt>.
|
||||||
|
*
|
||||||
|
* @param channel
|
||||||
|
* the channel
|
||||||
|
* @return the peer instance.
|
||||||
|
*/
|
||||||
public PeerWirePeer getPeer(Channel channel) {
|
public PeerWirePeer getPeer(Channel channel) {
|
||||||
PeerWirePeer peer = activePeers.get(channel);
|
PeerWirePeer peer = activePeers.get(channel);
|
||||||
if (peer == null)
|
if (peer == null)
|
||||||
@@ -65,6 +118,13 @@ public class PeerManager implements Iterable<PeerWirePeer> {
|
|||||||
return peer;
|
return peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup for the {@link Channel} in which the <tt>peer</tt> is attached to.
|
||||||
|
*
|
||||||
|
* @param peer
|
||||||
|
* the peer
|
||||||
|
* @return the {@link Channel} for the given <tt>peer</tt>
|
||||||
|
*/
|
||||||
public Channel getChannel(PeerWirePeer peer) {
|
public Channel getChannel(PeerWirePeer peer) {
|
||||||
for (final Entry<Channel, PeerWirePeer> entry : activePeers.entrySet()) {
|
for (final Entry<Channel, PeerWirePeer> entry : activePeers.entrySet()) {
|
||||||
if (entry.getValue().equals(peer))
|
if (entry.getValue().equals(peer))
|
||||||
@@ -78,10 +138,24 @@ public class PeerManager implements Iterable<PeerWirePeer> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if there are no active peers in this manager.
|
||||||
|
*
|
||||||
|
* @return true if no active peers
|
||||||
|
*/
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return activePeers.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) {
|
public PeerWirePeer add(Channel channel, TorrentPeer peer) {
|
||||||
if (channel.isConnected()) {
|
if (channel.isConnected()) {
|
||||||
return activePeers.put(channel, new PeerWirePeer(channel, peer));
|
return activePeers.put(channel, new PeerWirePeer(channel, peer));
|
||||||
@@ -90,6 +164,13 @@ public class PeerManager implements Iterable<PeerWirePeer> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
public PeerWirePeer remove(Channel channel) {
|
||||||
PeerWirePeer peer;
|
PeerWirePeer peer;
|
||||||
if ((peer = activePeers.remove(channel)) != null)
|
if ((peer = activePeers.remove(channel)) != null)
|
||||||
@@ -99,6 +180,13 @@ public class PeerManager implements Iterable<PeerWirePeer> {
|
|||||||
return null;
|
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) {
|
public PeerWirePeer remove(PeerWirePeer peer) {
|
||||||
final Channel channel = getChannel(peer);
|
final Channel channel = getChannel(peer);
|
||||||
PeerWirePeer peerRemoved;
|
PeerWirePeer peerRemoved;
|
||||||
@@ -109,6 +197,13 @@ public class PeerManager implements Iterable<PeerWirePeer> {
|
|||||||
return null;
|
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) {
|
public PeerWirePeer update(Channel channel) {
|
||||||
PeerWirePeer peer;
|
PeerWirePeer peer;
|
||||||
if ((peer = remove(channel)) == null)
|
if ((peer = remove(channel)) == null)
|
||||||
@@ -116,30 +211,66 @@ public class PeerManager implements Iterable<PeerWirePeer> {
|
|||||||
return add(channel, peer.getTorrentPeer());
|
return add(channel, peer.getTorrentPeer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the total active peers
|
||||||
|
*
|
||||||
|
* @return the active peers count
|
||||||
|
*/
|
||||||
public int getActivePeersCount() {
|
public int getActivePeersCount() {
|
||||||
return activePeers.size();
|
return activePeers.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the total inactive peers
|
||||||
|
*
|
||||||
|
* @return the inactive peers count
|
||||||
|
*/
|
||||||
public int getImactivePeersCount() {
|
public int getImactivePeersCount() {
|
||||||
return activePeers.size();
|
return activePeers.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an {@link Map} of all active peers
|
||||||
|
*
|
||||||
|
* @return the {@link Map} of all active peers
|
||||||
|
*/
|
||||||
public Map<Channel, PeerWirePeer> getActivePeers() {
|
public Map<Channel, PeerWirePeer> getActivePeers() {
|
||||||
return Collections.unmodifiableMap(activePeers);
|
return Collections.unmodifiableMap(activePeers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an {@link Map} of all inactive peers
|
||||||
|
*
|
||||||
|
* @return the {@link Map} of all inactive peers
|
||||||
|
*/
|
||||||
public Map<Channel, PeerWirePeer> getInactivePeers() {
|
public Map<Channel, PeerWirePeer> getInactivePeers() {
|
||||||
return Collections.unmodifiableMap(inactivePeers);
|
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<Channel> getActiveChannels() {
|
public Set<Channel> getActiveChannels() {
|
||||||
return Collections.unmodifiableSet(activePeers.keySet());
|
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<Channel> getInactiveChannels() {
|
public Set<Channel> getInactiveChannels() {
|
||||||
return Collections.unmodifiableSet(inactivePeers.keySet());
|
return Collections.unmodifiableSet(inactivePeers.keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the <tt>callback</tt> for each active peer in this manager.
|
||||||
|
*
|
||||||
|
* @param callback
|
||||||
|
* the callback
|
||||||
|
*/
|
||||||
public void executeActive(PeerCallback callback) {
|
public void executeActive(PeerCallback callback) {
|
||||||
for (final Entry<Channel, PeerWirePeer> entry : this.activePeers
|
for (final Entry<Channel, PeerWirePeer> entry : this.activePeers
|
||||||
.entrySet()) {
|
.entrySet()) {
|
||||||
@@ -147,6 +278,12 @@ public class PeerManager implements Iterable<PeerWirePeer> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the <tt>callback</tt> for each inactive peer in this manager.
|
||||||
|
*
|
||||||
|
* @param callback
|
||||||
|
* the callback
|
||||||
|
*/
|
||||||
public void executeInactive(PeerCallback callback) {
|
public void executeInactive(PeerCallback callback) {
|
||||||
for (final Entry<Channel, PeerWirePeer> entry : this.inactivePeers
|
for (final Entry<Channel, PeerWirePeer> entry : this.inactivePeers
|
||||||
.entrySet()) {
|
.entrySet()) {
|
||||||
@@ -154,6 +291,14 @@ public class PeerManager implements Iterable<PeerWirePeer> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the <tt>callback</tt> 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) {
|
public void execute(PeerCallback callback) {
|
||||||
executeActive(callback);
|
executeActive(callback);
|
||||||
executeInactive(callback);
|
executeInactive(callback);
|
||||||
@@ -164,10 +309,20 @@ public class PeerManager implements Iterable<PeerWirePeer> {
|
|||||||
return activePeers.values().iterator();
|
return activePeers.values().iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the torrent context
|
||||||
|
*
|
||||||
|
* @return the torrent context
|
||||||
|
*/
|
||||||
public TorrentContext getContext() {
|
public TorrentContext getContext() {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the connection manager
|
||||||
|
*
|
||||||
|
* @return the connection manager
|
||||||
|
*/
|
||||||
public ConnectionManager getConnectionManager() {
|
public ConnectionManager getConnectionManager() {
|
||||||
return connectionManager;
|
return connectionManager;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,13 @@ import net.torrent.protocol.datastore.TorrentDatastore;
|
|||||||
import net.torrent.torrent.Torrent;
|
import net.torrent.torrent.Torrent;
|
||||||
import net.torrent.torrent.context.TorrentContext;
|
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 <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||||
|
*/
|
||||||
public class TorrentManager {
|
public class TorrentManager {
|
||||||
private final TorrentContext context;
|
private final TorrentContext context;
|
||||||
|
|
||||||
|
|||||||
@@ -27,27 +27,99 @@ import net.torrent.torrent.TorrentPart;
|
|||||||
import net.torrent.torrent.context.TorrentContext;
|
import net.torrent.torrent.context.TorrentContext;
|
||||||
import net.torrent.torrent.context.TorrentPeer;
|
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.
|
||||||
|
* <p>
|
||||||
|
* Please note that the manager actually does not make any decision nor declines
|
||||||
|
* an requested piece.
|
||||||
|
* <p>
|
||||||
|
* You can {@link Iterable iterate} over this manager to get <b>current</b>
|
||||||
|
* uploading {@link TorrentPart parts}.
|
||||||
|
* <p>
|
||||||
|
* FIXME <b>BUG NOTICE</b>: 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 <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||||
|
*/
|
||||||
|
// 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<TorrentPart> {
|
public class UploadManager implements Iterable<TorrentPart> {
|
||||||
|
/**
|
||||||
|
* The torrent context
|
||||||
|
*/
|
||||||
private final TorrentContext context;
|
private final TorrentContext context;
|
||||||
|
/**
|
||||||
|
* An map of requested pieces. Only accepted pieces are registered.
|
||||||
|
*/
|
||||||
private final Map<TorrentPart, TorrentPeer> activeParts = new HashMap<TorrentPart, TorrentPeer>();
|
private final Map<TorrentPart, TorrentPeer> activeParts = new HashMap<TorrentPart, TorrentPeer>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* the torrent context
|
||||||
|
*/
|
||||||
public UploadManager(TorrentContext context) {
|
public UploadManager(TorrentContext context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUploading(TorrentPart torrentPart) {
|
/**
|
||||||
return activeParts.containsKey(torrentPart);
|
* Test if the given <tt>part</tt> is being uploaded.
|
||||||
|
*
|
||||||
|
* @param part
|
||||||
|
* the part
|
||||||
|
* @return true if piece has been requested <b>AND</b> accepted.
|
||||||
|
*/
|
||||||
|
public boolean isUploading(TorrentPart part) {
|
||||||
|
return activeParts.containsKey(part);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if uploads are being made to the given <tt>peer</tt>
|
||||||
|
*
|
||||||
|
* @param peer
|
||||||
|
* the peer
|
||||||
|
* @return true if at least one piece has been requested an piece <b>AND</b>
|
||||||
|
* the request was accepted
|
||||||
|
*/
|
||||||
public boolean isUploading(TorrentPeer peer) {
|
public boolean isUploading(TorrentPeer peer) {
|
||||||
return activeParts.containsValue(peer);
|
return activeParts.containsValue(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TorrentPeer getPeer(TorrentPart torrentPart) {
|
/**
|
||||||
return activeParts.get(torrentPart);
|
* This method retrieve the peer which has requested the given
|
||||||
|
* <tt>piece</tt>.
|
||||||
|
* <p>
|
||||||
|
* 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 <tt>peer</tt>
|
||||||
|
*
|
||||||
|
* @param peer
|
||||||
|
* the peer
|
||||||
|
* @return an {@link Set} of all parts being uploaded to this peer.
|
||||||
|
*/
|
||||||
public Set<TorrentPart> getTorrentParts(TorrentPeer peer) {
|
public Set<TorrentPart> getTorrentParts(TorrentPeer peer) {
|
||||||
final Set<TorrentPart> parts = new HashSet<TorrentPart>();
|
final Set<TorrentPart> parts = new HashSet<TorrentPart>();
|
||||||
for (final Entry<TorrentPart, TorrentPeer> entry : activeParts
|
for (final Entry<TorrentPart, TorrentPeer> entry : activeParts
|
||||||
@@ -58,18 +130,51 @@ public class UploadManager implements Iterable<TorrentPart> {
|
|||||||
return parts;
|
return parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if this manager has no active uploads.
|
||||||
|
*
|
||||||
|
* @return true if no uploads are being done
|
||||||
|
*/
|
||||||
public boolean isInactive() {
|
public boolean isInactive() {
|
||||||
return activeParts.isEmpty();
|
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 <tt>part</tt> from this manager
|
||||||
|
* <p>
|
||||||
|
* 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 <tt>part</tt>
|
||||||
|
*/
|
||||||
|
public TorrentPeer remove(TorrentPart part) {
|
||||||
|
return activeParts.remove(part);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all uploads for the given <tt>peer</tt>
|
||||||
|
*
|
||||||
|
* @param peer
|
||||||
|
* the peer
|
||||||
|
* @return the set of {@link TorrentPart parts} being uploaded to that peer
|
||||||
|
*/
|
||||||
public Set<TorrentPart> remove(TorrentPeer peer) {
|
public Set<TorrentPart> remove(TorrentPeer peer) {
|
||||||
final Set<TorrentPart> parts = new HashSet<TorrentPart>();
|
final Set<TorrentPart> parts = new HashSet<TorrentPart>();
|
||||||
for (TorrentPart part : getTorrentParts(peer)) {
|
for (TorrentPart part : getTorrentParts(peer)) {
|
||||||
@@ -79,10 +184,25 @@ public class UploadManager implements Iterable<TorrentPart> {
|
|||||||
return parts;
|
return parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the amount of active uploads
|
||||||
|
*
|
||||||
|
* @return the count of active uploads
|
||||||
|
*/
|
||||||
public int getActiveUploadsCount() {
|
public int getActiveUploadsCount() {
|
||||||
return activeParts.size();
|
return activeParts.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an {@link Map} of active uploads
|
||||||
|
* <p>
|
||||||
|
* 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<TorrentPart, TorrentPeer> getActiveUploads() {
|
public Map<TorrentPart, TorrentPeer> getActiveUploads() {
|
||||||
return Collections.unmodifiableMap(activeParts);
|
return Collections.unmodifiableMap(activeParts);
|
||||||
}
|
}
|
||||||
@@ -92,6 +212,11 @@ public class UploadManager implements Iterable<TorrentPart> {
|
|||||||
return activeParts.keySet().iterator();
|
return activeParts.keySet().iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the torrent context
|
||||||
|
*
|
||||||
|
* @return the torrent context
|
||||||
|
*/
|
||||||
public TorrentContext getContext() {
|
public TorrentContext getContext() {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user