- Add fail timers

- Add progress indication
- Listener cleanup
This commit is contained in:
zzz
2012-10-22 14:51:41 +00:00
parent 8b2889e317
commit 95e0c37222
5 changed files with 96 additions and 27 deletions

View File

@ -49,6 +49,11 @@ public interface CompleteListener {
*/ */
public void addMessage(Snark snark, String message); public void addMessage(Snark snark, String message);
/**
* @since 0.9.4
*/
public void gotPiece(Snark snark);
// not really listeners but the easiest way to get back to an optional SnarkManager // not really listeners but the easiest way to get back to an optional SnarkManager
public long getSavedTorrentTime(Snark snark); public long getSavedTorrentTime(Snark snark);
public BitField getSavedTorrentBitField(Snark snark); public BitField getSavedTorrentBitField(Snark snark);

View File

@ -515,8 +515,8 @@ class PeerCoordinator implements PeerListener
peerCount = peers.size(); peerCount = peers.size();
unchokePeer(); unchokePeer();
if (listener != null) //if (listener != null)
listener.peerChange(this, peer); // listener.peerChange(this, peer);
} }
} }
if (toDisconnect != null) { if (toDisconnect != null) {
@ -652,8 +652,8 @@ class PeerCoordinator implements PeerListener
*/ */
public boolean gotHave(Peer peer, int piece) public boolean gotHave(Peer peer, int piece)
{ {
if (listener != null) //if (listener != null)
listener.peerChange(this, peer); // listener.peerChange(this, peer);
synchronized(wantedPieces) { synchronized(wantedPieces) {
for (Piece pc : wantedPieces) { for (Piece pc : wantedPieces) {
@ -672,8 +672,8 @@ class PeerCoordinator implements PeerListener
*/ */
public boolean gotBitField(Peer peer, BitField bitfield) public boolean gotBitField(Peer peer, BitField bitfield)
{ {
if (listener != null) //if (listener != null)
listener.peerChange(this, peer); // listener.peerChange(this, peer);
boolean rv = false; boolean rv = false;
synchronized(wantedPieces) { synchronized(wantedPieces) {
@ -919,8 +919,8 @@ class PeerCoordinator implements PeerListener
{ {
uploaded += size; uploaded += size;
if (listener != null) //if (listener != null)
listener.peerChange(this, peer); // listener.peerChange(this, peer);
} }
/** /**
@ -930,8 +930,8 @@ class PeerCoordinator implements PeerListener
{ {
downloaded += size; downloaded += size;
if (listener != null) //if (listener != null)
listener.peerChange(this, peer); // listener.peerChange(this, peer);
} }
/** /**
@ -1040,8 +1040,8 @@ class PeerCoordinator implements PeerListener
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("Got choke(" + choke + "): " + peer); _log.info("Got choke(" + choke + "): " + peer);
if (listener != null) //if (listener != null)
listener.peerChange(this, peer); // listener.peerChange(this, peer);
} }
public void gotInterest(Peer peer, boolean interest) public void gotInterest(Peer peer, boolean interest)
@ -1060,8 +1060,8 @@ class PeerCoordinator implements PeerListener
} }
} }
if (listener != null) //if (listener != null)
listener.peerChange(this, peer); // listener.peerChange(this, peer);
} }
public void disconnected(Peer peer) public void disconnected(Peer peer)
@ -1081,8 +1081,8 @@ class PeerCoordinator implements PeerListener
peerCount = peers.size(); peerCount = peers.size();
} }
if (listener != null) //if (listener != null)
listener.peerChange(this, peer); // listener.peerChange(this, peer);
} }
/** Called when a peer is removed, to prevent it from being used in /** Called when a peer is removed, to prevent it from being used in

View File

@ -1115,7 +1115,12 @@ public class Snark
} }
} }
///////////// Begin StorageListener methods
//private boolean allocating = false; //private boolean allocating = false;
/** does nothing */
public void storageCreateFile(Storage storage, String name, long length) public void storageCreateFile(Storage storage, String name, long length)
{ {
//if (allocating) //if (allocating)
@ -1129,6 +1134,7 @@ public class Snark
// How much storage space has been allocated // How much storage space has been allocated
private long allocated = 0; private long allocated = 0;
/** does nothing */
public void storageAllocated(Storage storage, long length) public void storageAllocated(Storage storage, long length)
{ {
//allocating = true; //allocating = true;
@ -1140,7 +1146,8 @@ public class Snark
private boolean allChecked = false; private boolean allChecked = false;
private boolean checking = false; private boolean checking = false;
private boolean prechecking = true; //private boolean prechecking = true;
public void storageChecked(Storage storage, int num, boolean checked) public void storageChecked(Storage storage, int num, boolean checked)
{ {
//allocating = false; //allocating = false;
@ -1158,6 +1165,8 @@ public class Snark
if (!checking) { if (!checking) {
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("Got " + (checked ? "" : "BAD ") + "piece: " + num); _log.info("Got " + (checked ? "" : "BAD ") + "piece: " + num);
if (completeListener != null)
completeListener.gotPiece(this);
} }
} }
@ -1187,6 +1196,9 @@ public class Snark
coordinator.setWantedPieces(); coordinator.setWantedPieces();
} }
///////////// End StorageListener methods
/** SnarkSnutdown callback unused */ /** SnarkSnutdown callback unused */
public void shutdown() public void shutdown()
{ {

View File

@ -1517,6 +1517,12 @@ public class SnarkManager implements CompleteListener {
addMessage(message); addMessage(message);
} }
/**
* A Snark.CompleteListener method.
* @since 0.9.4
*/
public void gotPiece(Snark snark) {}
// End Snark.CompleteListeners // End Snark.CompleteListeners
/** /**

View File

@ -1,17 +1,15 @@
package org.klomp.snark; package org.klomp.snark;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;
import java.util.StringTokenizer;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.crypto.TrustedUpdate; import net.i2p.crypto.TrustedUpdate;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.update.*; import net.i2p.update.*;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.SimpleTimer2;
import net.i2p.util.VersionComparator; import net.i2p.util.VersionComparator;
/** /**
@ -25,15 +23,16 @@ class UpdateRunner implements UpdateTask, CompleteListener {
private final UpdateManager _umgr; private final UpdateManager _umgr;
private final SnarkManager _smgr; private final SnarkManager _smgr;
private final List<URI> _urls; private final List<URI> _urls;
private final String _updateFile;
private volatile boolean _isRunning; private volatile boolean _isRunning;
private volatile boolean _hasMetaInfo;
private volatile boolean _isComplete;
private final String _newVersion; private final String _newVersion;
private ByteArrayOutputStream _baos;
private URI _currentURI; private URI _currentURI;
private Snark _snark; private Snark _snark;
private boolean _hasMetaInfo;
private static final long MAX_LENGTH = 30*1024*1024; private static final long MAX_LENGTH = 30*1024*1024;
private static final long METAINFO_TIMEOUT = 30*60*1000;
private static final long COMPLETE_TIMEOUT = 3*60*60*1000;
public UpdateRunner(I2PAppContext ctx, UpdateManager umgr, SnarkManager smgr, public UpdateRunner(I2PAppContext ctx, UpdateManager umgr, SnarkManager smgr,
List<URI> uris, String newVersion) { List<URI> uris, String newVersion) {
@ -43,7 +42,6 @@ class UpdateRunner implements UpdateTask, CompleteListener {
_smgr = smgr; _smgr = smgr;
_urls = uris; _urls = uris;
_newVersion = newVersion; _newVersion = newVersion;
_updateFile = (new File(ctx.getTempDir(), "update" + ctx.random().nextInt() + ".tmp")).getAbsolutePath();
} }
//////// begin UpdateTask methods //////// begin UpdateTask methods
@ -79,7 +77,6 @@ class UpdateRunner implements UpdateTask, CompleteListener {
* If it is, get the whole thing. * If it is, get the whole thing.
*/ */
private void update() { private void update() {
if (_urls.isEmpty()) { if (_urls.isEmpty()) {
_umgr.notifyTaskFailed(this, "", null); _umgr.notifyTaskFailed(this, "", null);
return; return;
@ -93,9 +90,16 @@ class UpdateRunner implements UpdateTask, CompleteListener {
String name = magnet.getName(); String name = magnet.getName();
byte[] ih = magnet.getInfoHash(); byte[] ih = magnet.getInfoHash();
String trackerURL = magnet.getTrackerURL(); String trackerURL = magnet.getTrackerURL();
if (trackerURL == null && !_smgr.util().shouldUseDHT() &&
!_smgr.util().shouldUseOpenTrackers()) {
// but won't we use OT as a failsafe even if disabled?
_umgr.notifyAttemptFailed(this, "No tracker, no DHT, no OT", null);
continue;
}
_snark = _smgr.addMagnet(name, ih, trackerURL, true, true, this); _snark = _smgr.addMagnet(name, ih, trackerURL, true, true, this);
if (_snark != null) { if (_snark != null) {
updateStatus("<b>" + _smgr.util().getString("Updating from {0}", updateURL) + "</b>"); updateStatus("<b>" + _smgr.util().getString("Updating from {0}", updateURL) + "</b>");
new Timeout();
break; break;
} }
} catch (IllegalArgumentException iae) {} } catch (IllegalArgumentException iae) {}
@ -104,6 +108,32 @@ class UpdateRunner implements UpdateTask, CompleteListener {
fatal("No valid URLs"); fatal("No valid URLs");
} }
/**
* This will run twice, once at the metainfo timeout and
* once at the complete timeout.
*/
private class Timeout extends SimpleTimer2.TimedEvent {
private final long _start = _context.clock().now();
public Timeout() {
super(_context.simpleTimer2(), METAINFO_TIMEOUT);
}
public void timeReached() {
if (_isComplete || !_isRunning)
return;
if (!_hasMetaInfo) {
fatal("Metainfo timeout");
return;
}
if (_context.clock().now() - _start >= COMPLETE_TIMEOUT) {
fatal("Complete timeout");
return;
}
reschedule(COMPLETE_TIMEOUT - METAINFO_TIMEOUT);
}
}
private void fatal(String error) { private void fatal(String error) {
if (_snark != null) { if (_snark != null) {
if (_hasMetaInfo) { if (_hasMetaInfo) {
@ -138,15 +168,21 @@ class UpdateRunner implements UpdateTask, CompleteListener {
} }
_umgr.notifyComplete(this, _newVersion, f); _umgr.notifyComplete(this, _newVersion, f);
_smgr.torrentComplete(snark); _smgr.torrentComplete(snark);
_isComplete = true;
} }
/**
* This is called by stopTorrent() among others
*/
public void updateStatus(Snark snark) { public void updateStatus(Snark snark) {
if (snark.isStopped()) {
if (!_isComplete)
fatal("stopped by user");
}
_smgr.updateStatus(snark); _smgr.updateStatus(snark);
} }
public String gotMetaInfo(Snark snark) { public String gotMetaInfo(Snark snark) {
Storage storage = snark.getStorage();
MetaInfo info = snark.getMetaInfo(); MetaInfo info = snark.getMetaInfo();
if (info.getFiles() != null) { if (info.getFiles() != null) {
fatal("more than 1 file"); fatal("more than 1 file");
@ -173,6 +209,16 @@ class UpdateRunner implements UpdateTask, CompleteListener {
_smgr.addMessage(snark, message); _smgr.addMessage(snark, message);
} }
public void gotPiece(Snark snark) {
if (_hasMetaInfo) {
long total = snark.getTotalLength();
long remaining = snark.getRemainingLength();
String status = "<b>" + _smgr.util().getString("Updating") + "</b>";
_umgr.notifyProgress(this, status, total - remaining, total);
}
_smgr.gotPiece(snark);
}
public long getSavedTorrentTime(Snark snark) { public long getSavedTorrentTime(Snark snark) {
return _smgr.getSavedTorrentTime(snark); return _smgr.getSavedTorrentTime(snark);
} }