mirror of
https://github.com/Rogiel/torrent4j
synced 2025-12-05 23:22:49 +00:00
Scoring algorithm
This commit is contained in:
30
pom.xml
30
pom.xml
@@ -5,7 +5,7 @@
|
|||||||
<artifactId>libtorrent</artifactId>
|
<artifactId>libtorrent</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>libtorrent</name>
|
<name>libtorrent</name>
|
||||||
<version>1.0</version>
|
<version>1.0.0-alpha2</version>
|
||||||
<description>Java library used for downloading and uploading torrent files</description>
|
<description>Java library used for downloading and uploading torrent files</description>
|
||||||
<url>http://code.google.com/p/libtorrent-java</url>
|
<url>http://code.google.com/p/libtorrent-java</url>
|
||||||
|
|
||||||
@@ -97,6 +97,34 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-pdf-plugin</artifactId>
|
||||||
|
<version>1.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>pdf</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>pdf</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-clean-plugin</artifactId>
|
||||||
|
<version>2.4.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>clean</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>clean</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
<repositories>
|
<repositories>
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import net.torrent.protocol.algorithm.TorrentPeerAlgorithm;
|
|||||||
import net.torrent.protocol.algorithm.TorrentPieceDownloadAlgorithm;
|
import net.torrent.protocol.algorithm.TorrentPieceDownloadAlgorithm;
|
||||||
import net.torrent.protocol.algorithm.TorrentPieceUploadAlgorithm;
|
import net.torrent.protocol.algorithm.TorrentPieceUploadAlgorithm;
|
||||||
import net.torrent.protocol.peerwire.manager.TorrentManager;
|
import net.torrent.protocol.peerwire.manager.TorrentManager;
|
||||||
|
import net.torrent.torrent.piece.PieceSelector;
|
||||||
|
import net.torrent.torrent.piece.ScoredPieceSelector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard torrent algorithm
|
* Standard torrent algorithm
|
||||||
@@ -28,15 +30,21 @@ import net.torrent.protocol.peerwire.manager.TorrentManager;
|
|||||||
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||||
*/
|
*/
|
||||||
public class TorrentStdAlgorithm implements TorrentAlgorithm {
|
public class TorrentStdAlgorithm implements TorrentAlgorithm {
|
||||||
|
private final PieceSelector pieceSelector;
|
||||||
|
|
||||||
private final TorrentPeerAlgorithm peerAlgorithm;
|
private final TorrentPeerAlgorithm peerAlgorithm;
|
||||||
private final TorrentInterestAlgorithm interestAlgorithm;
|
private final TorrentInterestAlgorithm interestAlgorithm;
|
||||||
private final TorrentPieceDownloadAlgorithm downloadAlgorithm;
|
private final TorrentPieceDownloadAlgorithm downloadAlgorithm;
|
||||||
private final TorrentPieceUploadAlgorithm uploadAlgorithm;
|
private final TorrentPieceUploadAlgorithm uploadAlgorithm;
|
||||||
|
|
||||||
public TorrentStdAlgorithm(final TorrentManager manager) {
|
public TorrentStdAlgorithm(final TorrentManager manager) {
|
||||||
|
pieceSelector = new ScoredPieceSelector(manager);
|
||||||
|
|
||||||
peerAlgorithm = new TorrentStdPeerAlgorithm(manager);
|
peerAlgorithm = new TorrentStdPeerAlgorithm(manager);
|
||||||
interestAlgorithm = new TorrentStdInterestAlgorithm(manager);
|
interestAlgorithm = new TorrentStdInterestAlgorithm(manager,
|
||||||
downloadAlgorithm = new TorrentStdPieceDownloadAlgorithm(manager);
|
pieceSelector);
|
||||||
|
downloadAlgorithm = new TorrentStdPieceDownloadAlgorithm(manager,
|
||||||
|
pieceSelector);
|
||||||
uploadAlgorithm = new TorrentStdPieceUploadAlgorithm(manager);
|
uploadAlgorithm = new TorrentStdPieceUploadAlgorithm(manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import net.torrent.protocol.peerwire.manager.TorrentManager;
|
|||||||
import net.torrent.torrent.context.TorrentPeer;
|
import net.torrent.torrent.context.TorrentPeer;
|
||||||
import net.torrent.torrent.context.TorrentPeer.ChokingState;
|
import net.torrent.torrent.context.TorrentPeer.ChokingState;
|
||||||
import net.torrent.torrent.context.TorrentPeer.InterestState;
|
import net.torrent.torrent.context.TorrentPeer.InterestState;
|
||||||
|
import net.torrent.torrent.piece.PieceSelector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard torrent interest algorithm
|
* Standard torrent interest algorithm
|
||||||
@@ -29,15 +30,29 @@ import net.torrent.torrent.context.TorrentPeer.InterestState;
|
|||||||
public class TorrentStdInterestAlgorithm implements TorrentInterestAlgorithm {
|
public class TorrentStdInterestAlgorithm implements TorrentInterestAlgorithm {
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private final TorrentManager manager;
|
private final TorrentManager manager;
|
||||||
|
private final PieceSelector selector;
|
||||||
|
|
||||||
public TorrentStdInterestAlgorithm(TorrentManager manager) {
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*
|
||||||
|
* @param manager
|
||||||
|
* the manager
|
||||||
|
* @param pieceSelector
|
||||||
|
* the piece selector
|
||||||
|
*/
|
||||||
|
public TorrentStdInterestAlgorithm(TorrentManager manager,
|
||||||
|
PieceSelector pieceSelector) {
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
|
this.selector = pieceSelector;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InterestState interested(TorrentPeer peer) {
|
public InterestState interested(TorrentPeer peer) {
|
||||||
// if(peer.getPort() == 25944)
|
int pieces = selector.countPieces(peer);
|
||||||
// return InterestState.UNINTERESTED;
|
if(pieces >= 5)
|
||||||
|
return InterestState.INTERESTED;
|
||||||
|
|
||||||
|
|
||||||
return InterestState.INTERESTED;
|
return InterestState.INTERESTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import net.torrent.torrent.TorrentPart;
|
|||||||
import net.torrent.torrent.TorrentPiece;
|
import net.torrent.torrent.TorrentPiece;
|
||||||
import net.torrent.torrent.context.TorrentPeer;
|
import net.torrent.torrent.context.TorrentPeer;
|
||||||
import net.torrent.torrent.piece.PieceSelector;
|
import net.torrent.torrent.piece.PieceSelector;
|
||||||
import net.torrent.torrent.piece.RandomPieceSelector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This standard implementation of {@link TorrentPieceDownloadAlgorithm} chooses
|
* This standard implementation of {@link TorrentPieceDownloadAlgorithm} chooses
|
||||||
@@ -39,8 +38,6 @@ public class TorrentStdPieceDownloadAlgorithm implements
|
|||||||
* The torrent manager
|
* The torrent manager
|
||||||
*/
|
*/
|
||||||
private final TorrentManager manager;
|
private final TorrentManager manager;
|
||||||
// private final TorrentContext context;
|
|
||||||
// private final Torrent torrent;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This selector is used to find the next piece to be downloaded. Parts are
|
* This selector is used to find the next piece to be downloaded. Parts are
|
||||||
@@ -61,12 +58,13 @@ public class TorrentStdPieceDownloadAlgorithm implements
|
|||||||
* @param manager
|
* @param manager
|
||||||
* the torrent manager instance. With this object is possible to
|
* the torrent manager instance. With this object is possible to
|
||||||
* retrieve current downloads/uploads and connections.
|
* retrieve current downloads/uploads and connections.
|
||||||
|
* @param pieceSelector
|
||||||
|
* the piece selector
|
||||||
*/
|
*/
|
||||||
public TorrentStdPieceDownloadAlgorithm(TorrentManager manager) {
|
public TorrentStdPieceDownloadAlgorithm(TorrentManager manager,
|
||||||
|
PieceSelector pieceSelector) {
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
// this.context = this.manager.getContext();
|
this.selector = pieceSelector;
|
||||||
// this.torrent = this.manager.getTorrent();
|
|
||||||
selector = new RandomPieceSelector(manager);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ import net.torrent.torrent.context.TorrentPeer;
|
|||||||
import net.torrent.torrent.context.TorrentPeer.ChokingState;
|
import net.torrent.torrent.context.TorrentPeer.ChokingState;
|
||||||
import net.torrent.torrent.context.TorrentPeer.InterestState;
|
import net.torrent.torrent.context.TorrentPeer.InterestState;
|
||||||
import net.torrent.torrent.context.TorrentPeerCapabilities.TorrentPeerCapability;
|
import net.torrent.torrent.context.TorrentPeerCapabilities.TorrentPeerCapability;
|
||||||
import net.torrent.util.PeerCallback;
|
import net.torrent.util.PeerWirePeerCallback;
|
||||||
|
|
||||||
import org.jboss.netty.channel.ChannelFuture;
|
import org.jboss.netty.channel.ChannelFuture;
|
||||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||||
@@ -343,7 +343,7 @@ public class PeerWireAlgorithmHandler extends IdleStateAwareChannelHandler {
|
|||||||
|
|
||||||
if (datastore.checksum(part.getPiece())) {
|
if (datastore.checksum(part.getPiece())) {
|
||||||
manager.getContext().getBitfield().setPiece(part.getPiece(), true);
|
manager.getContext().getBitfield().setPiece(part.getPiece(), true);
|
||||||
manager.getPeerManager().executeActive(new PeerCallback() {
|
manager.getPeerManager().executeActive(new PeerWirePeerCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void callback(PeerWirePeer peer) {
|
public void callback(PeerWirePeer peer) {
|
||||||
peer.have(part.getPiece().getIndex());
|
peer.have(part.getPiece().getIndex());
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import java.util.Set;
|
|||||||
import net.torrent.protocol.peerwire.PeerWirePeer;
|
import net.torrent.protocol.peerwire.PeerWirePeer;
|
||||||
import net.torrent.torrent.context.TorrentContext;
|
import net.torrent.torrent.context.TorrentContext;
|
||||||
import net.torrent.torrent.context.TorrentPeer;
|
import net.torrent.torrent.context.TorrentPeer;
|
||||||
import net.torrent.util.PeerCallback;
|
import net.torrent.util.PeerWirePeerCallback;
|
||||||
|
|
||||||
import org.jboss.netty.channel.Channel;
|
import org.jboss.netty.channel.Channel;
|
||||||
|
|
||||||
@@ -140,21 +140,21 @@ public class PeerManager implements Iterable<PeerWirePeer> {
|
|||||||
return Collections.unmodifiableSet(inactivePeers.keySet());
|
return Collections.unmodifiableSet(inactivePeers.keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void executeActive(PeerCallback callback) {
|
public void executeActive(PeerWirePeerCallback callback) {
|
||||||
for (final Entry<Channel, PeerWirePeer> entry : this.activePeers
|
for (final Entry<Channel, PeerWirePeer> entry : this.activePeers
|
||||||
.entrySet()) {
|
.entrySet()) {
|
||||||
callback.callback(entry.getValue());
|
callback.callback(entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void executeInactive(PeerCallback callback) {
|
public void executeInactive(PeerWirePeerCallback callback) {
|
||||||
for (final Entry<Channel, PeerWirePeer> entry : this.inactivePeers
|
for (final Entry<Channel, PeerWirePeer> entry : this.inactivePeers
|
||||||
.entrySet()) {
|
.entrySet()) {
|
||||||
callback.callback(entry.getValue());
|
callback.callback(entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(PeerCallback callback) {
|
public void execute(PeerWirePeerCallback callback) {
|
||||||
executeActive(callback);
|
executeActive(callback);
|
||||||
executeInactive(callback);
|
executeInactive(callback);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class TorrentContext {
|
|||||||
private final TorrentPeerCapabilities capabilites = new TorrentPeerCapabilities(
|
private final TorrentPeerCapabilities capabilites = new TorrentPeerCapabilities(
|
||||||
TorrentPeerCapability.DHT, TorrentPeerCapability.FAST_PEERS);
|
TorrentPeerCapability.DHT, TorrentPeerCapability.FAST_PEERS);
|
||||||
|
|
||||||
private final Set<TorrentPeer> peers = new HashSet<TorrentPeer>();
|
private final TorrentSwarm swarm = new TorrentSwarm(this);
|
||||||
/**
|
/**
|
||||||
* Unknown peers does not have their IDs, consequently they cannot be
|
* Unknown peers does not have their IDs, consequently they cannot be
|
||||||
* queried using their Id and must be done through IP.
|
* queried using their Id and must be done through IP.
|
||||||
@@ -103,8 +103,8 @@ public class TorrentContext {
|
|||||||
*
|
*
|
||||||
* @return the list of peers
|
* @return the list of peers
|
||||||
*/
|
*/
|
||||||
public Set<TorrentPeer> getPeers() {
|
public TorrentSwarm getSwarm() {
|
||||||
return Collections.unmodifiableSet(peers);
|
return swarm;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -116,73 +116,15 @@ public class TorrentContext {
|
|||||||
return Collections.unmodifiableSet(unknownPeers);
|
return Collections.unmodifiableSet(unknownPeers);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an peer by its PeerID
|
|
||||||
*
|
|
||||||
* @param peerId
|
|
||||||
* the peer id
|
|
||||||
* @return the found peer. Null if not found.
|
|
||||||
*/
|
|
||||||
public TorrentPeer getPeer(TorrentPeerID peerId) {
|
public TorrentPeer getPeer(TorrentPeerID peerId) {
|
||||||
for (final TorrentPeer peer : peers) {
|
return swarm.getPeer(peerId);
|
||||||
if (peer.getPeerID().equals(peerId))
|
|
||||||
return peer;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an peer by its address
|
|
||||||
*
|
|
||||||
* @param address
|
|
||||||
* the address
|
|
||||||
* @return the found peer. Null if not found.
|
|
||||||
*/
|
|
||||||
public TorrentPeer getPeer(InetSocketAddress address) {
|
public TorrentPeer getPeer(InetSocketAddress address) {
|
||||||
for (final TorrentPeer peer : peers) {
|
return swarm.getPeer(address);
|
||||||
if (peer.getSocketAddress().equals(address))
|
|
||||||
return peer;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Lookup for a peer first by its id, then by address, if still not found,
|
|
||||||
* creates a new entry.
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
* the peer id
|
|
||||||
* @param address
|
|
||||||
* the address
|
|
||||||
* @return the found or newly created peer
|
|
||||||
*/
|
|
||||||
public TorrentPeer getPeer(TorrentPeerID id, InetSocketAddress address) {
|
public TorrentPeer getPeer(TorrentPeerID id, InetSocketAddress address) {
|
||||||
TorrentPeer peer = getPeer(id);
|
return swarm.getPeer(id, address);
|
||||||
if (peer == null) {
|
|
||||||
peer = getPeer(address);
|
|
||||||
if (peer != null) {
|
|
||||||
if (peers.remove(peer))
|
|
||||||
peer = peer.createWithID(id);
|
|
||||||
} else {
|
|
||||||
peer = new TorrentPeer(this, id, null);
|
|
||||||
}
|
|
||||||
peers.add(peer);
|
|
||||||
}
|
|
||||||
return peer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If this peer already exists, will update its IP.
|
|
||||||
*
|
|
||||||
* @param peerInfo
|
|
||||||
* the peer info object, returned from the tracker
|
|
||||||
*/
|
|
||||||
public TorrentPeer addPeerByPeerInfo(PeerInfo peerInfo) {
|
|
||||||
final TorrentPeerID id = TorrentPeerID.create(peerInfo.getPeerId());
|
|
||||||
final InetSocketAddress address = new InetSocketAddress(
|
|
||||||
peerInfo.getIp(), peerInfo.getPort());
|
|
||||||
TorrentPeer peer = getPeer(id, address);
|
|
||||||
peer.setSocketAddress(address);
|
|
||||||
return peer;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
175
src/main/java/net/torrent/torrent/context/TorrentSwarm.java
Normal file
175
src/main/java/net/torrent/torrent/context/TorrentSwarm.java
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package net.torrent.torrent.context;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.torrent.protocol.tracker.message.PeerListMessage.PeerInfo;
|
||||||
|
import net.torrent.torrent.TorrentPiece;
|
||||||
|
import net.torrent.util.SwarmCallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An torrent swarm is an set of all connected peers.
|
||||||
|
*
|
||||||
|
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||||
|
*/
|
||||||
|
public class TorrentSwarm implements Iterable<TorrentPeer> {
|
||||||
|
/**
|
||||||
|
* The torrent context
|
||||||
|
*/
|
||||||
|
private final TorrentContext context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of active peers
|
||||||
|
*/
|
||||||
|
private List<TorrentPeer> peers = new ArrayList<TorrentPeer>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* the torrent context
|
||||||
|
*/
|
||||||
|
public TorrentSwarm(final TorrentContext context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an given peer to the swarm
|
||||||
|
*
|
||||||
|
* @param peer
|
||||||
|
* the peer
|
||||||
|
* @return true if was not present in swarm
|
||||||
|
*/
|
||||||
|
public boolean add(TorrentPeer peer) {
|
||||||
|
return this.peers.add(peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an given peer from the swarm
|
||||||
|
*
|
||||||
|
* @param peer
|
||||||
|
* the peer
|
||||||
|
* @return true if peer was in swarm
|
||||||
|
*/
|
||||||
|
public boolean remove(TorrentPeer peer) {
|
||||||
|
return this.peers.remove(peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes an callback on each peer in the swarm
|
||||||
|
*
|
||||||
|
* @param callback
|
||||||
|
* the callback
|
||||||
|
*/
|
||||||
|
public void execute(SwarmCallback callback) {
|
||||||
|
for (final TorrentPeer peer : this) {
|
||||||
|
callback.callback(peer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select the peers which have the <tt>piece</tt>
|
||||||
|
*
|
||||||
|
* @param piece
|
||||||
|
* the piece
|
||||||
|
* @return list of peers with piece
|
||||||
|
*/
|
||||||
|
public List<TorrentPeer> getPeersWithPiece(TorrentPiece piece) {
|
||||||
|
final List<TorrentPeer> hasPieces = new ArrayList<TorrentPeer>();
|
||||||
|
for (final TorrentPeer peer : peers) {
|
||||||
|
if (!peer.getBitfield().hasPiece(piece))
|
||||||
|
continue;
|
||||||
|
hasPieces.add(peer);
|
||||||
|
}
|
||||||
|
return hasPieces;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an peer by its PeerID
|
||||||
|
*
|
||||||
|
* @param peerId
|
||||||
|
* the peer id
|
||||||
|
* @return the found peer. Null if not found.
|
||||||
|
*/
|
||||||
|
public TorrentPeer getPeer(TorrentPeerID peerId) {
|
||||||
|
for (final TorrentPeer peer : peers) {
|
||||||
|
if (peer.getPeerID().equals(peerId))
|
||||||
|
return peer;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an peer by its address
|
||||||
|
*
|
||||||
|
* @param address
|
||||||
|
* the address
|
||||||
|
* @return the found peer. Null if not found.
|
||||||
|
*/
|
||||||
|
public TorrentPeer getPeer(InetSocketAddress address) {
|
||||||
|
for (final TorrentPeer peer : peers) {
|
||||||
|
if (peer.getSocketAddress().equals(address))
|
||||||
|
return peer;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup for a peer first by its id, then by address, if still not found,
|
||||||
|
* creates a new entry.
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* the peer id
|
||||||
|
* @param address
|
||||||
|
* the address
|
||||||
|
* @return the found or newly created peer
|
||||||
|
*/
|
||||||
|
public TorrentPeer getPeer(TorrentPeerID id, InetSocketAddress address) {
|
||||||
|
TorrentPeer peer = getPeer(id);
|
||||||
|
if (peer == null) {
|
||||||
|
peer = getPeer(address);
|
||||||
|
if (peer != null) {
|
||||||
|
if (remove(peer))
|
||||||
|
peer = peer.createWithID(id);
|
||||||
|
} else {
|
||||||
|
peer = new TorrentPeer(context, id, null);
|
||||||
|
}
|
||||||
|
add(peer);
|
||||||
|
}
|
||||||
|
return peer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this peer already exists, will update its IP.
|
||||||
|
*
|
||||||
|
* @param peerInfo
|
||||||
|
* the peer info object, returned from the tracker
|
||||||
|
*/
|
||||||
|
public TorrentPeer addPeerByPeerInfo(PeerInfo peerInfo) {
|
||||||
|
final TorrentPeerID id = TorrentPeerID.create(peerInfo.getPeerId());
|
||||||
|
final InetSocketAddress address = new InetSocketAddress(
|
||||||
|
peerInfo.getIp(), peerInfo.getPort());
|
||||||
|
TorrentPeer peer = getPeer(id, address);
|
||||||
|
peer.setSocketAddress(address);
|
||||||
|
return peer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<TorrentPeer> iterator() {
|
||||||
|
return peers.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the torrent context
|
||||||
|
*
|
||||||
|
* @return the torrent context
|
||||||
|
*/
|
||||||
|
public TorrentContext getContext() {
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,4 +34,11 @@ public interface PieceSelector {
|
|||||||
* @return the {@link TorrentPiece piece} selected for download.
|
* @return the {@link TorrentPiece piece} selected for download.
|
||||||
*/
|
*/
|
||||||
public TorrentPiece select(TorrentPeer peer);
|
public TorrentPiece select(TorrentPeer peer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the amount of pieces available to select
|
||||||
|
*
|
||||||
|
* @return the amount of pieces available
|
||||||
|
*/
|
||||||
|
public int countPieces(TorrentPeer peer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011 Rogiel Josias Sulzbach
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package net.torrent.torrent.piece;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.torrent.protocol.peerwire.manager.TorrentManager;
|
||||||
|
import net.torrent.torrent.TorrentPiece;
|
||||||
|
import net.torrent.torrent.context.TorrentPeer;
|
||||||
|
import net.torrent.torrent.piece.score.PieceRarenessScoreAlgorithm;
|
||||||
|
import net.torrent.torrent.piece.score.ScoredPieceComparator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select pieces in sequential order. Can be used for streaming purposes.
|
||||||
|
*
|
||||||
|
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||||
|
*/
|
||||||
|
public class ScoredPieceSelector extends SortedListPieceSelector {
|
||||||
|
/**
|
||||||
|
* Sort again the list each <tt>n</tt> calls to {@link #select(TorrentPeer)}
|
||||||
|
*/
|
||||||
|
private static final int SORT_INTERVAL = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call counter. Used to sort the list.
|
||||||
|
*/
|
||||||
|
private int calls = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The piece comparator
|
||||||
|
*/
|
||||||
|
private final ScoredPieceComparator comparator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*
|
||||||
|
* @param manager
|
||||||
|
* the torrent manager
|
||||||
|
*/
|
||||||
|
public ScoredPieceSelector(TorrentManager manager) {
|
||||||
|
super(manager, Arrays.asList(manager.getTorrent().getPieces()));
|
||||||
|
this.comparator = new ScoredPieceComparator(manager.getContext()
|
||||||
|
.getSwarm(), new PieceRarenessScoreAlgorithm());
|
||||||
|
// initial sort will be skipped because comparator is null.
|
||||||
|
this.sort(pieces);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void sort(List<TorrentPiece> pieces) {
|
||||||
|
if (comparator != null)
|
||||||
|
Collections.sort(pieces, comparator);
|
||||||
|
System.out.println(pieces);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized TorrentPiece select(TorrentPeer peer) {
|
||||||
|
if (calls % SORT_INTERVAL == 0)
|
||||||
|
this.sort(pieces);
|
||||||
|
calls++;
|
||||||
|
return super.select(peer);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,11 +32,11 @@ public abstract class SortedListPieceSelector implements PieceSelector {
|
|||||||
/**
|
/**
|
||||||
* The torrent manager
|
* The torrent manager
|
||||||
*/
|
*/
|
||||||
private final TorrentManager manager;
|
protected final TorrentManager manager;
|
||||||
/**
|
/**
|
||||||
* The sorted list of pieces
|
* The sorted list of pieces
|
||||||
*/
|
*/
|
||||||
private final List<TorrentPiece> pieces;
|
protected final List<TorrentPiece> pieces;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
@@ -53,6 +53,14 @@ public abstract class SortedListPieceSelector implements PieceSelector {
|
|||||||
this.sort(this.pieces);
|
this.sort(this.pieces);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorts the set using an implementation specific algorithm.
|
||||||
|
*
|
||||||
|
* @param pieces
|
||||||
|
* the unsorted pieces list that will be sorted.
|
||||||
|
*/
|
||||||
|
protected abstract void sort(List<TorrentPiece> pieces);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized TorrentPiece select(TorrentPeer peer) {
|
public synchronized TorrentPiece select(TorrentPeer peer) {
|
||||||
for (int index = 0; index < pieces.size(); index++) {
|
for (int index = 0; index < pieces.size(); index++) {
|
||||||
@@ -68,11 +76,19 @@ public abstract class SortedListPieceSelector implements PieceSelector {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Sorts the set using an implementation specific algorithm.
|
public int countPieces(TorrentPeer peer) {
|
||||||
*
|
int count = 0;
|
||||||
* @param pieces
|
for (int index = 0; index < pieces.size(); index++) {
|
||||||
* the unsorted pieces list that will be sorted.
|
final TorrentPiece piece = pieces.get(index);
|
||||||
*/
|
if (manager.getContext().getBitfield().hasPiece(piece))
|
||||||
protected abstract void sort(List<TorrentPiece> pieces);
|
continue;
|
||||||
|
if (!peer.getBitfield().hasPiece(piece))
|
||||||
|
continue;
|
||||||
|
if (manager.getDownloadManager().isDownloading(piece))
|
||||||
|
continue;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package net.torrent.torrent.piece.score;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import net.torrent.torrent.TorrentPiece;
|
||||||
|
import net.torrent.torrent.context.TorrentPeer;
|
||||||
|
import net.torrent.torrent.context.TorrentSwarm;
|
||||||
|
import net.torrent.util.SwarmCallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||||
|
*/
|
||||||
|
public class PieceRarenessScoreAlgorithm implements PieceScoreAlgorithm {
|
||||||
|
@Override
|
||||||
|
public int calculate(TorrentSwarm swarm, final TorrentPiece piece) {
|
||||||
|
final AtomicInteger score = new AtomicInteger();
|
||||||
|
swarm.execute(new SwarmCallback() {
|
||||||
|
@Override
|
||||||
|
public void callback(TorrentPeer peer) {
|
||||||
|
int peerScore = (int) (Math.random() * 10); // bit of randomness
|
||||||
|
if (!peer.isAccessible()) {
|
||||||
|
peerScore += 100;
|
||||||
|
}
|
||||||
|
if (!peer.getBitfield().hasPiece(piece))
|
||||||
|
peerScore += 1000;
|
||||||
|
score.addAndGet(peerScore);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return score.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package net.torrent.torrent.piece.score;
|
||||||
|
|
||||||
|
import net.torrent.torrent.TorrentPiece;
|
||||||
|
import net.torrent.torrent.context.TorrentSwarm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the score of an piece inside the swarm.
|
||||||
|
* <p>
|
||||||
|
* Pieces with higher scores will be more suitable to download than others.
|
||||||
|
*
|
||||||
|
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||||
|
*/
|
||||||
|
public interface PieceScoreAlgorithm {
|
||||||
|
/**
|
||||||
|
* Computes the score of an piece inside an swarm.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int calculate(TorrentSwarm swarm, TorrentPiece piece);
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package net.torrent.torrent.piece.score;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import net.torrent.torrent.TorrentPiece;
|
||||||
|
import net.torrent.torrent.context.TorrentSwarm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||||
|
*/
|
||||||
|
public class ScoredPieceComparator implements Comparator<TorrentPiece> {
|
||||||
|
private final PieceScoreAlgorithm score;
|
||||||
|
private final TorrentSwarm swarm;
|
||||||
|
|
||||||
|
public ScoredPieceComparator(TorrentSwarm swarm, PieceScoreAlgorithm score) {
|
||||||
|
this.swarm = swarm;
|
||||||
|
this.score = score;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(TorrentPiece piece1, TorrentPiece piece2) {
|
||||||
|
return score.calculate(swarm, piece1) - score.calculate(swarm, piece2);
|
||||||
|
}
|
||||||
|
}
|
||||||
34
src/main/java/net/torrent/util/PeerWirePeerCallback.java
Normal file
34
src/main/java/net/torrent/util/PeerWirePeerCallback.java
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011 Rogiel Josias Sulzbach
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package net.torrent.util;
|
||||||
|
|
||||||
|
import net.torrent.protocol.peerwire.PeerWirePeer;
|
||||||
|
import net.torrent.protocol.peerwire.manager.PeerManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback used in {@link PeerManager#execute(PeerCallback)}
|
||||||
|
*
|
||||||
|
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||||
|
*/
|
||||||
|
public interface PeerWirePeerCallback {
|
||||||
|
/**
|
||||||
|
* Execute the desired action for <tt>peer</tt>
|
||||||
|
*
|
||||||
|
* @param peer
|
||||||
|
* the peer
|
||||||
|
*/
|
||||||
|
void callback(PeerWirePeer peer);
|
||||||
|
}
|
||||||
22
src/main/java/net/torrent/util/SwarmCallback.java
Normal file
22
src/main/java/net/torrent/util/SwarmCallback.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package net.torrent.util;
|
||||||
|
|
||||||
|
import net.torrent.torrent.context.TorrentPeer;
|
||||||
|
import net.torrent.torrent.context.TorrentSwarm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback used in {@link TorrentSwarm#execute(SwarmCallback)}
|
||||||
|
*
|
||||||
|
* @author <a href="http://www.rogiel.com/">Rogiel Josias Sulzbach</a>
|
||||||
|
*/
|
||||||
|
public interface SwarmCallback {
|
||||||
|
/**
|
||||||
|
* Execute the desired action for <tt>peer</tt>
|
||||||
|
*
|
||||||
|
* @param peer
|
||||||
|
* the peer
|
||||||
|
*/
|
||||||
|
void callback(TorrentPeer peer);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user