* i2psnark:

- Don't send a keepalive to a peer we are going to disconnect
   - Disconnect peer when idle a long time
   - PeerCheckerTask cleanup
   - Static ref cleanup
   - Don't show a downloaded torrent file as "seeding"
   - Better torrent file download icon (from Silk, same license as the others)
This commit is contained in:
zzz
2012-07-01 16:16:08 +00:00
parent 63f22a54e1
commit 0d8bcd5dad
10 changed files with 73 additions and 44 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

View File

@ -122,6 +122,9 @@ public class I2PSnarkUtil {
}
******/
/** @since 0.9.1 */
public I2PAppContext getContext() { return _context; }
public boolean configured() { return _configured; }
public void setI2CPConfig(String i2cpHost, int i2cpPort, Map opts) {

View File

@ -5,10 +5,10 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.util.RandomSource;
import org.klomp.snark.bencode.BDecoder;
import org.klomp.snark.bencode.BEValue;
@ -27,7 +27,6 @@ import org.klomp.snark.bencode.BEValue;
*/
class MagnetState {
public static final int CHUNK_SIZE = 16*1024;
private static final Random random = I2PAppContext.getGlobalContext().random();
private final byte[] infohash;
private boolean complete;
@ -129,7 +128,7 @@ class MagnetState {
throw new IllegalArgumentException("not initialized");
if (complete)
throw new IllegalArgumentException("complete");
int rand = random.nextInt(totalChunks);
int rand = RandomSource.getInstance().nextInt(totalChunks);
for (int i = 0; i < totalChunks; i++) {
int chk = (i + rand) % totalChunks;
if (!(have.get(chk) || requested.get(chk))) {

View File

@ -25,6 +25,8 @@ import java.util.List;
import java.util.Random;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.util.Log;
/**
* TimerTask that checks for good/bad up/downloader. Works together
@ -36,16 +38,18 @@ class PeerCheckerTask implements Runnable
private final PeerCoordinator coordinator;
private final I2PSnarkUtil _util;
private final Log _log;
private final Random random;
private int _runCount;
PeerCheckerTask(I2PSnarkUtil util, PeerCoordinator coordinator)
{
_util = util;
_log = util.getContext().logManager().getLog(PeerCheckerTask.class);
random = util.getContext().random();
this.coordinator = coordinator;
}
private static final Random random = I2PAppContext.getGlobalContext().random();
public void run()
{
_runCount++;
@ -82,6 +86,14 @@ class PeerCheckerTask implements Runnable
continue;
}
if (peer.getInactiveTime() > PeerCoordinator.MAX_INACTIVE) {
if (_log.shouldLog(Log.WARN))
_log.warn("Disconnecting peer idle " +
DataHelper.formatDuration(peer.getInactiveTime()) + ": " + peer);
peer.disconnect();
continue;
}
if (!peer.isChoking())
uploaders++;
@ -92,14 +104,15 @@ class PeerCheckerTask implements Runnable
peer.setRateHistory(upload, download);
peer.resetCounters();
_util.debug(peer + ":", Snark.DEBUG);
_util.debug(" ul: " + upload*1024/KILOPERSECOND
if (_log.shouldLog(Log.DEBUG)) {
_log.debug(peer + ":"
+ " ul: " + upload*1024/KILOPERSECOND
+ " dl: " + download*1024/KILOPERSECOND
+ " i: " + peer.isInterested()
+ " I: " + peer.isInteresting()
+ " c: " + peer.isChoking()
+ " C: " + peer.isChoked(),
Snark.DEBUG);
+ " C: " + peer.isChoked());
}
// Choke a percentage of them rather than all so it isn't so drastic...
// unless this torrent is over the limit all by itself.
@ -120,8 +133,8 @@ class PeerCheckerTask implements Runnable
// Check if it still wants pieces from us.
if (!peer.isInterested())
{
_util.debug("Choke uninterested peer: " + peer,
Snark.INFO);
if (_log.shouldLog(Log.INFO))
_log.debug("Choke uninterested peer: " + peer);
peer.setChoking(true);
uploaders--;
coordinator.uploaders--;
@ -131,8 +144,8 @@ class PeerCheckerTask implements Runnable
}
else if (overBWLimitChoke)
{
_util.debug("BW limit (" + upload + "/" + uploaded + "), choke peer: " + peer,
Snark.INFO);
if (_log.shouldLog(Log.INFO))
_log.debug("BW limit (" + upload + "/" + uploaded + "), choke peer: " + peer);
peer.setChoking(true);
uploaders--;
coordinator.uploaders--;
@ -144,7 +157,8 @@ class PeerCheckerTask implements Runnable
else if (peer.isInteresting() && peer.isChoked())
{
// If they are choking us make someone else a downloader
_util.debug("Choke choking peer: " + peer, Snark.DEBUG);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Choke choking peer: " + peer);
peer.setChoking(true);
uploaders--;
coordinator.uploaders--;
@ -156,7 +170,8 @@ class PeerCheckerTask implements Runnable
else if (!peer.isInteresting() && !coordinator.completed())
{
// If they aren't interesting make someone else a downloader
_util.debug("Choke uninteresting peer: " + peer, Snark.DEBUG);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Choke uninteresting peer: " + peer);
peer.setChoking(true);
uploaders--;
coordinator.uploaders--;
@ -170,8 +185,8 @@ class PeerCheckerTask implements Runnable
&& download == 0)
{
// We are downloading but didn't receive anything...
_util.debug("Choke downloader that doesn't deliver:"
+ peer, Snark.DEBUG);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Choke downloader that doesn't deliver: " + peer);
peer.setChoking(true);
uploaders--;
coordinator.uploaders--;
@ -198,7 +213,10 @@ class PeerCheckerTask implements Runnable
// send PEX
if ((_runCount % 17) == 0 && !peer.isCompleted())
coordinator.sendPeers(peer);
peer.keepAlive();
// cheap failsafe for seeds connected to seeds, stop pinging and hopefully
// the inactive checker (above) will eventually disconnect it
if (coordinator.getNeededLength() > 0 || !peer.isCompleted())
peer.keepAlive();
// announce them to local tracker (TrackerClient does this too)
if (_util.getDHT() != null && (_runCount % 5) == 0) {
_util.getDHT().announce(coordinator.getInfoHash(), peer.getPeerID().getDestHash());
@ -215,8 +233,8 @@ class PeerCheckerTask implements Runnable
|| uploaders > uploadLimit)
&& worstDownloader != null)
{
_util.debug("Choke worst downloader: " + worstDownloader,
Snark.DEBUG);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Choke worst downloader: " + worstDownloader);
worstDownloader.setChoking(true);
coordinator.uploaders--;

View File

@ -68,6 +68,7 @@ class PeerCoordinator implements PeerListener
// package local for access by CheckDownLoadersTask
final static long CHECK_PERIOD = 40*1000; // 40 seconds
final static int MAX_UPLOADERS = 6;
public static final long MAX_INACTIVE = 8*60*1000;
/**
* Approximation of the number of current uploaders.
@ -130,7 +131,7 @@ class PeerCoordinator implements PeerListener
private final MagnetState magnetState;
private final CoordinatorListener listener;
private final I2PSnarkUtil _util;
private static final Random _random = I2PAppContext.getGlobalContext().random();
private final Random _random;
/**
* @param metainfo null if in magnet mode
@ -140,6 +141,7 @@ class PeerCoordinator implements PeerListener
CoordinatorListener listener, Snark torrent)
{
_util = util;
_random = util.getContext().random();
this.id = id;
this.infohash = infohash;
this.metainfo = metainfo;
@ -377,8 +379,10 @@ class PeerCoordinator implements PeerListener
}
/**
* Reduce max if huge pieces to keep from ooming when leeching
* @return 512K: 16; 1M: 11; 2M: 6
* Formerly used to
* reduce max if huge pieces to keep from ooming when leeching
* but now we don't
* @return usually 16
*/
private int getMaxConnections() {
if (metainfo == null)
@ -388,7 +392,7 @@ class PeerCoordinator implements PeerListener
return 4;
if (pieces <= 5)
return 6;
int size = metainfo.getPieceLength(0);
//int size = metainfo.getPieceLength(0);
int max = _util.getMaxConnections();
// Now that we use temp files, no memory concern
//if (size <= 512*1024 || completed())
@ -449,7 +453,7 @@ class PeerCoordinator implements PeerListener
synchronized(peers)
{
Peer old = peerIDInList(peer.getPeerID(), peers);
if ( (old != null) && (old.getInactiveTime() > 8*60*1000) ) {
if ( (old != null) && (old.getInactiveTime() > MAX_INACTIVE) ) {
// idle for 8 minutes, kill the old con (32KB/8min = 68B/sec minimum for one block)
if (_log.shouldLog(Log.WARN))
_log.warn("Remomving old peer: " + peer + ": " + old + ", inactive for " + old.getInactiveTime());
@ -543,7 +547,7 @@ class PeerCoordinator implements PeerListener
need_more = (!peer.isConnected()) && peersize < getMaxConnections();
// Check if we already have this peer before we build the connection
Peer old = peerIDInList(peer.getPeerID(), peers);
need_more = need_more && ((old == null) || (old.getInactiveTime() > 8*60*1000));
need_more = need_more && ((old == null) || (old.getInactiveTime() > MAX_INACTIVE));
}
if (need_more)
@ -974,11 +978,8 @@ class PeerCoordinator implements PeerListener
// Announce to the world we have it!
// Disconnect from other seeders when we get the last piece
List<Peer> toDisconnect = new ArrayList();
Iterator<Peer> it = peers.iterator();
while (it.hasNext())
{
Peer p = it.next();
List<Peer> toDisconnect = done ? new ArrayList() : null;
for (Peer p : peers) {
if (p.isConnected())
{
if (done && p.isCompleted())
@ -986,15 +987,13 @@ class PeerCoordinator implements PeerListener
else
p.have(piece);
}
}
it = toDisconnect.iterator();
while (it.hasNext())
{
Peer p = it.next();
p.disconnect(true);
}
}
if (done) {
for (Peer p : toDisconnect) {
p.disconnect(true);
}
// put msg on the console if partial, since Storage won't do it
if (!completed())
snark.storageCompleted(storage);

View File

@ -243,11 +243,12 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl
}
/**
* @return torrent file bytes remaining or -1
* @return -1 when done so the web will list us as "complete" instead of "seeding"
*/
@Override
public long getRemainingLength() {
return _remaining;
long rv = _remaining;
return rv > 0 ? rv : -1;
}
/**

View File

@ -1073,7 +1073,7 @@ public class I2PSnarkServlet extends DefaultServlet {
else if (isValid)
icon = toIcon(meta.getName());
else if (snark instanceof FetchAndAdd)
icon = "arrow_down";
icon = "basket_put";
else
icon = "magnet";
if (isValid) {
@ -1104,7 +1104,7 @@ public class I2PSnarkServlet extends DefaultServlet {
out.write("<td align=\"right\" class=\"snarkTorrentETA " + rowClass + "\">");
if(isRunning && remainingSeconds > 0)
out.write(DataHelper.formatDuration2(remainingSeconds*1000)); // (eta 6h)
out.write(DataHelper.formatDuration2(Math.max(remainingSeconds, 10) * 1000)); // (eta 6h)
out.write("</td>\n\t");
out.write("<td align=\"right\" class=\"snarkTorrentDownloaded " + rowClass + "\">");
if (remaining > 0)

View File

@ -1,3 +1,12 @@
2012-07-01 zzz
* i2psnark:
- Don't send a keepalive to a peer we are going to disconnect
- Disconnect peer when idle a long time
- PeerCheckerTask cleanup
- Static ref cleanup
- Don't show a downloaded torrent file as "seeding"
- Better torrent file download icon
2012-06-29 zzz
* HTTP Proxy: Change the error code for unknown host from 404 to 500
* SimpleTimer: Fix logging

View File

@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 20;
public final static long BUILD = 21;
/** for example "-test" */
public final static String EXTRA = "";