2007-01-14 zzz
* i2psnark: Improvements for torrents with > 4 leechers: choke based on upload rate when seeding, and be smarter and fairer about rotating choked peers. * Handle two common i2psnark OOM situations rather than shutting down the whole thing. * Fix reporting to tracker of remaining bytes for torrents > 4GB (but ByteMonsoon still has a bug)
This commit is contained in:
@ -48,10 +48,7 @@ class PeerCheckerTask extends TimerTask
|
|||||||
int peers = 0;
|
int peers = 0;
|
||||||
int uploaders = 0;
|
int uploaders = 0;
|
||||||
int downloaders = 0;
|
int downloaders = 0;
|
||||||
int interested = 0;
|
int removedCount = 0;
|
||||||
int interesting = 0;
|
|
||||||
int choking = 0;
|
|
||||||
int choked = 0;
|
|
||||||
|
|
||||||
long uploaded = 0;
|
long uploaded = 0;
|
||||||
long downloaded = 0;
|
long downloaded = 0;
|
||||||
@ -80,14 +77,6 @@ class PeerCheckerTask extends TimerTask
|
|||||||
uploaders++;
|
uploaders++;
|
||||||
if (!peer.isChoked() && peer.isInteresting())
|
if (!peer.isChoked() && peer.isInteresting())
|
||||||
downloaders++;
|
downloaders++;
|
||||||
if (peer.isInterested())
|
|
||||||
interested++;
|
|
||||||
if (peer.isInteresting())
|
|
||||||
interesting++;
|
|
||||||
if (peer.isChoking())
|
|
||||||
choking++;
|
|
||||||
if (peer.isChoked())
|
|
||||||
choked++;
|
|
||||||
|
|
||||||
long upload = peer.getUploaded();
|
long upload = peer.getUploaded();
|
||||||
uploaded += upload;
|
uploaded += upload;
|
||||||
@ -111,7 +100,7 @@ class PeerCheckerTask extends TimerTask
|
|||||||
// interested peers try to make some room.
|
// interested peers try to make some room.
|
||||||
// (Note use of coordinator.uploaders)
|
// (Note use of coordinator.uploaders)
|
||||||
if (coordinator.uploaders >= PeerCoordinator.MAX_UPLOADERS
|
if (coordinator.uploaders >= PeerCoordinator.MAX_UPLOADERS
|
||||||
&& interested > PeerCoordinator.MAX_UPLOADERS
|
&& coordinator.interestedAndChoking > 0
|
||||||
&& !peer.isChoking())
|
&& !peer.isChoking())
|
||||||
{
|
{
|
||||||
// Check if it still wants pieces from us.
|
// Check if it still wants pieces from us.
|
||||||
@ -128,7 +117,7 @@ class PeerCheckerTask extends TimerTask
|
|||||||
it.remove();
|
it.remove();
|
||||||
removed.add(peer);
|
removed.add(peer);
|
||||||
}
|
}
|
||||||
else if (peer.isChoked())
|
else if (peer.isInteresting() && peer.isChoked())
|
||||||
{
|
{
|
||||||
// If they are choking us make someone else a downloader
|
// If they are choking us make someone else a downloader
|
||||||
if (Snark.debug >= Snark.DEBUG)
|
if (Snark.debug >= Snark.DEBUG)
|
||||||
@ -136,6 +125,7 @@ class PeerCheckerTask extends TimerTask
|
|||||||
peer.setChoking(true);
|
peer.setChoking(true);
|
||||||
uploaders--;
|
uploaders--;
|
||||||
coordinator.uploaders--;
|
coordinator.uploaders--;
|
||||||
|
removedCount++;
|
||||||
|
|
||||||
// Put it at the back of the list
|
// Put it at the back of the list
|
||||||
it.remove();
|
it.remove();
|
||||||
@ -152,17 +142,25 @@ class PeerCheckerTask extends TimerTask
|
|||||||
peer.setChoking(true);
|
peer.setChoking(true);
|
||||||
uploaders--;
|
uploaders--;
|
||||||
coordinator.uploaders--;
|
coordinator.uploaders--;
|
||||||
|
removedCount++;
|
||||||
|
|
||||||
// Put it at the back of the list
|
// Put it at the back of the list
|
||||||
it.remove();
|
it.remove();
|
||||||
removed.add(peer);
|
removed.add(peer);
|
||||||
}
|
}
|
||||||
else if (!peer.isChoking() && download < worstdownload)
|
else if (peer.isInteresting() && !peer.isChoked() &&
|
||||||
|
download < worstdownload)
|
||||||
{
|
{
|
||||||
// Make sure download is good if we are uploading
|
// Make sure download is good if we are uploading
|
||||||
worstdownload = download;
|
worstdownload = download;
|
||||||
worstDownloader = peer;
|
worstDownloader = peer;
|
||||||
}
|
}
|
||||||
|
else if (upload < worstdownload && coordinator.completed())
|
||||||
|
{
|
||||||
|
// Make sure upload is good if we are seeding
|
||||||
|
worstdownload = upload;
|
||||||
|
worstDownloader = peer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
peer.retransmitRequests();
|
peer.retransmitRequests();
|
||||||
peer.keepAlive();
|
peer.keepAlive();
|
||||||
@ -172,9 +170,9 @@ class PeerCheckerTask extends TimerTask
|
|||||||
// (can shift a bit by disconnecting peers)
|
// (can shift a bit by disconnecting peers)
|
||||||
coordinator.uploaders = uploaders;
|
coordinator.uploaders = uploaders;
|
||||||
|
|
||||||
// Remove the worst downloader if needed.
|
// Remove the worst downloader if needed. (uploader if seeding)
|
||||||
if (uploaders >= PeerCoordinator.MAX_UPLOADERS
|
if (uploaders >= PeerCoordinator.MAX_UPLOADERS
|
||||||
&& interested > PeerCoordinator.MAX_UPLOADERS
|
&& coordinator.interestedAndChoking > 0
|
||||||
&& worstDownloader != null)
|
&& worstDownloader != null)
|
||||||
{
|
{
|
||||||
if (Snark.debug >= Snark.DEBUG)
|
if (Snark.debug >= Snark.DEBUG)
|
||||||
@ -183,6 +181,7 @@ class PeerCheckerTask extends TimerTask
|
|||||||
|
|
||||||
worstDownloader.setChoking(true);
|
worstDownloader.setChoking(true);
|
||||||
coordinator.uploaders--;
|
coordinator.uploaders--;
|
||||||
|
removedCount++;
|
||||||
|
|
||||||
// Put it at the back of the list
|
// Put it at the back of the list
|
||||||
coordinator.peers.remove(worstDownloader);
|
coordinator.peers.remove(worstDownloader);
|
||||||
@ -196,6 +195,7 @@ class PeerCheckerTask extends TimerTask
|
|||||||
// Put peers back at the end of the list that we removed earlier.
|
// Put peers back at the end of the list that we removed earlier.
|
||||||
coordinator.peers.addAll(removed);
|
coordinator.peers.addAll(removed);
|
||||||
coordinator.peerCount = coordinator.peers.size();
|
coordinator.peerCount = coordinator.peers.size();
|
||||||
|
coordinator.interestedAndChoking += removedCount;
|
||||||
|
|
||||||
// store the rates
|
// store the rates
|
||||||
coordinator.setRateHistory(uploaded, downloaded);
|
coordinator.setRateHistory(uploaded, downloaded);
|
||||||
|
@ -44,6 +44,7 @@ public class PeerCoordinator implements PeerListener
|
|||||||
// Approximation of the number of current uploaders.
|
// Approximation of the number of current uploaders.
|
||||||
// Resynced by PeerChecker once in a while.
|
// Resynced by PeerChecker once in a while.
|
||||||
int uploaders = 0;
|
int uploaders = 0;
|
||||||
|
int interestedAndChoking = 0;
|
||||||
|
|
||||||
// final static int MAX_DOWNLOADERS = MAX_CONNECTIONS;
|
// final static int MAX_DOWNLOADERS = MAX_CONNECTIONS;
|
||||||
// int downloaders = 0;
|
// int downloaders = 0;
|
||||||
@ -132,7 +133,7 @@ public class PeerCoordinator implements PeerListener
|
|||||||
public long getLeft()
|
public long getLeft()
|
||||||
{
|
{
|
||||||
// XXX - Only an approximation.
|
// XXX - Only an approximation.
|
||||||
return storage.needed() * metainfo.getPieceLength(0);
|
return ((long) storage.needed()) * metainfo.getPieceLength(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -336,19 +337,22 @@ public class PeerCoordinator implements PeerListener
|
|||||||
// other peer that are interested, but are choking us.
|
// other peer that are interested, but are choking us.
|
||||||
List interested = new LinkedList();
|
List interested = new LinkedList();
|
||||||
synchronized (peers) {
|
synchronized (peers) {
|
||||||
|
int count = 0;
|
||||||
Iterator it = peers.iterator();
|
Iterator it = peers.iterator();
|
||||||
while (it.hasNext())
|
while (it.hasNext())
|
||||||
{
|
{
|
||||||
Peer peer = (Peer)it.next();
|
Peer peer = (Peer)it.next();
|
||||||
boolean remove = false;
|
boolean remove = false;
|
||||||
if (uploaders < MAX_UPLOADERS
|
if (peer.isChoking() && peer.isInterested())
|
||||||
&& peer.isChoking()
|
|
||||||
&& peer.isInterested())
|
|
||||||
{
|
{
|
||||||
if (!peer.isChoked())
|
count++;
|
||||||
interested.add(0, peer);
|
if (uploaders < MAX_UPLOADERS)
|
||||||
else
|
{
|
||||||
interested.add(peer);
|
if (!peer.isChoked())
|
||||||
|
interested.add(0, peer);
|
||||||
|
else
|
||||||
|
interested.add(peer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,11 +363,13 @@ public class PeerCoordinator implements PeerListener
|
|||||||
_log.debug("Unchoke: " + peer);
|
_log.debug("Unchoke: " + peer);
|
||||||
peer.setChoking(false);
|
peer.setChoking(false);
|
||||||
uploaders++;
|
uploaders++;
|
||||||
|
count--;
|
||||||
// Put peer back at the end of the list.
|
// Put peer back at the end of the list.
|
||||||
peers.remove(peer);
|
peers.remove(peer);
|
||||||
peers.add(peer);
|
peers.add(peer);
|
||||||
peerCount = peers.size();
|
peerCount = peers.size();
|
||||||
}
|
}
|
||||||
|
interestedAndChoking = count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,7 +537,14 @@ class PeerState
|
|||||||
&& (lastRequest == null || lastRequest.piece != nextPiece))
|
&& (lastRequest == null || lastRequest.piece != nextPiece))
|
||||||
{
|
{
|
||||||
int piece_length = metainfo.getPieceLength(nextPiece);
|
int piece_length = metainfo.getPieceLength(nextPiece);
|
||||||
byte[] bs = new byte[piece_length];
|
//Catch a common place for OOMs esp. on 1MB pieces
|
||||||
|
byte[] bs;
|
||||||
|
try {
|
||||||
|
bs = new byte[piece_length];
|
||||||
|
} catch (OutOfMemoryError oom) {
|
||||||
|
_log.warn("Out of memory, can't request piece " + nextPiece, oom);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int length = Math.min(piece_length, PARTSIZE);
|
int length = Math.min(piece_length, PARTSIZE);
|
||||||
Request req = new Request(nextPiece, bs, 0, length);
|
Request req = new Request(nextPiece, bs, 0, length);
|
||||||
|
@ -473,7 +473,14 @@ public class Storage
|
|||||||
if (!bitfield.get(piece))
|
if (!bitfield.get(piece))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
byte[] bs = new byte[metainfo.getPieceLength(piece)];
|
//Catch a common place for OOMs esp. on 1MB pieces
|
||||||
|
byte[] bs;
|
||||||
|
try {
|
||||||
|
bs = new byte[metainfo.getPieceLength(piece)];
|
||||||
|
} catch (OutOfMemoryError oom) {
|
||||||
|
I2PSnarkUtil.instance().debug("Out of memory, can't honor request for piece " + piece, Snark.WARNING, oom);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
getUncheckedPiece(piece, bs, 0);
|
getUncheckedPiece(piece, bs, 0);
|
||||||
return bs;
|
return bs;
|
||||||
}
|
}
|
||||||
|
11
history.txt
11
history.txt
@ -1,4 +1,13 @@
|
|||||||
$Id: history.txt,v 1.533 2006-10-29 14:29:50 complication Exp $
|
$Id: history.txt,v 1.534 2006-11-09 20:44:36 zzz Exp $
|
||||||
|
|
||||||
|
2007-01-14 zzz
|
||||||
|
* i2psnark: Improvements for torrents with > 4 leechers:
|
||||||
|
choke based on upload rate when seeding, and
|
||||||
|
be smarter and fairer about rotating choked peers.
|
||||||
|
* Handle two common i2psnark OOM situations rather
|
||||||
|
than shutting down the whole thing.
|
||||||
|
* Fix reporting to tracker of remaining bytes for
|
||||||
|
torrents > 4GB (but ByteMonsoon still has a bug)
|
||||||
|
|
||||||
2006-10-29 zzz
|
2006-10-29 zzz
|
||||||
* i2psnark: Fix and enable generation of multifile torrents,
|
* i2psnark: Fix and enable generation of multifile torrents,
|
||||||
|
@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RouterVersion {
|
public class RouterVersion {
|
||||||
public final static String ID = "$Revision: 1.468 $ $Date: 2006-10-29 14:29:53 $";
|
public final static String ID = "$Revision: 1.469 $ $Date: 2006-11-09 20:44:35 $";
|
||||||
public final static String VERSION = "0.6.1.26";
|
public final static String VERSION = "0.6.1.26";
|
||||||
public final static long BUILD = 2;
|
public final static long BUILD = 3;
|
||||||
public static void main(String args[]) {
|
public static void main(String args[]) {
|
||||||
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
|
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
|
||||||
System.out.println("Router ID: " + RouterVersion.ID);
|
System.out.println("Router ID: " + RouterVersion.ID);
|
||||||
|
Reference in New Issue
Block a user