From 53ba6c2a640b3ac6dba1cbcea01ce97065bed2d9 Mon Sep 17 00:00:00 2001 From: zzz Date: Sun, 14 Jan 2007 19:49:33 +0000 Subject: [PATCH] 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) --- .../src/org/klomp/snark/PeerCheckerTask.java | 34 +++++++++---------- .../src/org/klomp/snark/PeerCoordinator.java | 22 +++++++----- .../java/src/org/klomp/snark/PeerState.java | 9 ++++- .../java/src/org/klomp/snark/Storage.java | 9 ++++- history.txt | 11 +++++- .../src/net/i2p/router/RouterVersion.java | 4 +-- 6 files changed, 59 insertions(+), 30 deletions(-) diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java b/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java index 2e0fdf9ba..150792e08 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java @@ -48,10 +48,7 @@ class PeerCheckerTask extends TimerTask int peers = 0; int uploaders = 0; int downloaders = 0; - int interested = 0; - int interesting = 0; - int choking = 0; - int choked = 0; + int removedCount = 0; long uploaded = 0; long downloaded = 0; @@ -80,14 +77,6 @@ class PeerCheckerTask extends TimerTask uploaders++; if (!peer.isChoked() && peer.isInteresting()) downloaders++; - if (peer.isInterested()) - interested++; - if (peer.isInteresting()) - interesting++; - if (peer.isChoking()) - choking++; - if (peer.isChoked()) - choked++; long upload = peer.getUploaded(); uploaded += upload; @@ -111,7 +100,7 @@ class PeerCheckerTask extends TimerTask // interested peers try to make some room. // (Note use of coordinator.uploaders) if (coordinator.uploaders >= PeerCoordinator.MAX_UPLOADERS - && interested > PeerCoordinator.MAX_UPLOADERS + && coordinator.interestedAndChoking > 0 && !peer.isChoking()) { // Check if it still wants pieces from us. @@ -128,7 +117,7 @@ class PeerCheckerTask extends TimerTask it.remove(); removed.add(peer); } - else if (peer.isChoked()) + else if (peer.isInteresting() && peer.isChoked()) { // If they are choking us make someone else a downloader if (Snark.debug >= Snark.DEBUG) @@ -136,6 +125,7 @@ class PeerCheckerTask extends TimerTask peer.setChoking(true); uploaders--; coordinator.uploaders--; + removedCount++; // Put it at the back of the list it.remove(); @@ -152,17 +142,25 @@ class PeerCheckerTask extends TimerTask peer.setChoking(true); uploaders--; coordinator.uploaders--; + removedCount++; // Put it at the back of the list it.remove(); 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 worstdownload = download; worstDownloader = peer; } + else if (upload < worstdownload && coordinator.completed()) + { + // Make sure upload is good if we are seeding + worstdownload = upload; + worstDownloader = peer; + } } peer.retransmitRequests(); peer.keepAlive(); @@ -172,9 +170,9 @@ class PeerCheckerTask extends TimerTask // (can shift a bit by disconnecting peers) coordinator.uploaders = uploaders; - // Remove the worst downloader if needed. + // Remove the worst downloader if needed. (uploader if seeding) if (uploaders >= PeerCoordinator.MAX_UPLOADERS - && interested > PeerCoordinator.MAX_UPLOADERS + && coordinator.interestedAndChoking > 0 && worstDownloader != null) { if (Snark.debug >= Snark.DEBUG) @@ -183,6 +181,7 @@ class PeerCheckerTask extends TimerTask worstDownloader.setChoking(true); coordinator.uploaders--; + removedCount++; // Put it at the back of the list 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. coordinator.peers.addAll(removed); coordinator.peerCount = coordinator.peers.size(); + coordinator.interestedAndChoking += removedCount; // store the rates coordinator.setRateHistory(uploaded, downloaded); diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java index 2a45b0937..ea1a67687 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java @@ -44,6 +44,7 @@ public class PeerCoordinator implements PeerListener // Approximation of the number of current uploaders. // Resynced by PeerChecker once in a while. int uploaders = 0; + int interestedAndChoking = 0; // final static int MAX_DOWNLOADERS = MAX_CONNECTIONS; // int downloaders = 0; @@ -132,7 +133,7 @@ public class PeerCoordinator implements PeerListener public long getLeft() { // 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. List interested = new LinkedList(); synchronized (peers) { + int count = 0; Iterator it = peers.iterator(); while (it.hasNext()) { Peer peer = (Peer)it.next(); boolean remove = false; - if (uploaders < MAX_UPLOADERS - && peer.isChoking() - && peer.isInterested()) + if (peer.isChoking() && peer.isInterested()) { - if (!peer.isChoked()) - interested.add(0, peer); - else - interested.add(peer); + count++; + if (uploaders < MAX_UPLOADERS) + { + if (!peer.isChoked()) + interested.add(0, peer); + else + interested.add(peer); + } } } @@ -359,11 +363,13 @@ public class PeerCoordinator implements PeerListener _log.debug("Unchoke: " + peer); peer.setChoking(false); uploaders++; + count--; // Put peer back at the end of the list. peers.remove(peer); peers.add(peer); peerCount = peers.size(); } + interestedAndChoking = count; } } diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerState.java b/apps/i2psnark/java/src/org/klomp/snark/PeerState.java index 2f02db39a..cfd04f4e0 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerState.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerState.java @@ -537,7 +537,14 @@ class PeerState && (lastRequest == null || lastRequest.piece != 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); Request req = new Request(nextPiece, bs, 0, length); diff --git a/apps/i2psnark/java/src/org/klomp/snark/Storage.java b/apps/i2psnark/java/src/org/klomp/snark/Storage.java index 296d96b7c..0cf43fffc 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Storage.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Storage.java @@ -473,7 +473,14 @@ public class Storage if (!bitfield.get(piece)) 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); return bs; } diff --git a/history.txt b/history.txt index 128df6e8b..8f8213aa5 100644 --- a/history.txt +++ b/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 * i2psnark: Fix and enable generation of multifile torrents, diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 68034a06d..afe0ce937 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -15,9 +15,9 @@ import net.i2p.CoreVersion; * */ 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 long BUILD = 2; + public final static long BUILD = 3; public static void main(String args[]) { System.out.println("I2P Router version: " + VERSION + "-" + BUILD); System.out.println("Router ID: " + RouterVersion.ID);