Refactor fields to private and replace with getters,

and lots of prep for lack of metainfo and storage.
This commit is contained in:
zzz
2010-12-19 22:14:02 +00:00
parent afe57512ab
commit 4899a6d306
8 changed files with 409 additions and 163 deletions

View File

@ -120,7 +120,7 @@ public class PeerAcceptor
else else
{ {
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("Rejecting new peer for " + cur.snark.torrent); _log.debug("Rejecting new peer for " + cur.getName());
socket.close(); socket.close();
return; return;
} }

View File

@ -51,10 +51,7 @@ class PeerCheckerTask extends TimerTask
{ {
List<Peer> peerList = coordinator.peerList(); List<Peer> peerList = coordinator.peerList();
if (peerList.isEmpty() || coordinator.halted()) { if (peerList.isEmpty() || coordinator.halted()) {
coordinator.peerCount = 0;
coordinator.interestedAndChoking = 0;
coordinator.setRateHistory(0, 0); coordinator.setRateHistory(0, 0);
coordinator.uploaders = 0;
if (coordinator.halted()) if (coordinator.halted())
cancel(); cancel();
return; return;

View File

@ -42,18 +42,33 @@ import net.i2p.util.SimpleTimer2;
public class PeerCoordinator implements PeerListener public class PeerCoordinator implements PeerListener
{ {
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerCoordinator.class); private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerCoordinator.class);
/**
* External use by PeerMonitorTask only.
*/
final MetaInfo metainfo; final MetaInfo metainfo;
/**
* External use by PeerMonitorTask only.
*/
final Storage storage; final Storage storage;
final Snark snark; private final Snark snark;
// package local for access by CheckDownLoadersTask // package local for access by CheckDownLoadersTask
final static long CHECK_PERIOD = 40*1000; // 40 seconds final static long CHECK_PERIOD = 40*1000; // 40 seconds
final static int MAX_UPLOADERS = 6; final static int MAX_UPLOADERS = 6;
// Approximation of the number of current uploaders. /**
// Resynced by PeerChecker once in a while. * Approximation of the number of current uploaders.
int uploaders = 0; * Resynced by PeerChecker once in a while.
int interestedAndChoking = 0; * External use by PeerCheckerTask only.
*/
int uploaders;
/**
* External use by PeerCheckerTask only.
*/
int interestedAndChoking;
// final static int MAX_DOWNLOADERS = MAX_CONNECTIONS; // final static int MAX_DOWNLOADERS = MAX_CONNECTIONS;
// int downloaders = 0; // int downloaders = 0;
@ -61,14 +76,18 @@ public class PeerCoordinator implements PeerListener
private long uploaded; private long uploaded;
private long downloaded; private long downloaded;
final static int RATE_DEPTH = 3; // make following arrays RATE_DEPTH long final static int RATE_DEPTH = 3; // make following arrays RATE_DEPTH long
private long uploaded_old[] = {-1,-1,-1}; private final long uploaded_old[] = {-1,-1,-1};
private long downloaded_old[] = {-1,-1,-1}; private final long downloaded_old[] = {-1,-1,-1};
// synchronize on this when changing peers or downloaders /**
// This is a Queue, not a Set, because PeerCheckerTask keeps things in order for choking/unchoking * synchronize on this when changing peers or downloaders.
* This is a Queue, not a Set, because PeerCheckerTask keeps things in order for choking/unchoking.
* External use by PeerMonitorTask only.
*/
final Queue<Peer> peers; final Queue<Peer> peers;
/** estimate of the peers, without requiring any synchronization */ /** estimate of the peers, without requiring any synchronization */
volatile int peerCount; private volatile int peerCount;
/** Timer to handle all periodical tasks. */ /** Timer to handle all periodical tasks. */
private final CheckEvent timer; private final CheckEvent timer;
@ -86,12 +105,9 @@ public class PeerCoordinator implements PeerListener
private boolean halted = false; private boolean halted = false;
private final CoordinatorListener listener; private final CoordinatorListener listener;
public I2PSnarkUtil _util; private final I2PSnarkUtil _util;
private static final Random _random = I2PAppContext.getGlobalContext().random(); private static final Random _random = I2PAppContext.getGlobalContext().random();
public String trackerProblems = null;
public int trackerSeenPeers = 0;
public PeerCoordinator(I2PSnarkUtil util, byte[] id, MetaInfo metainfo, Storage storage, public PeerCoordinator(I2PSnarkUtil util, byte[] id, MetaInfo metainfo, Storage storage,
CoordinatorListener listener, Snark torrent) CoordinatorListener listener, Snark torrent)
{ {
@ -153,7 +169,6 @@ public class PeerCoordinator implements PeerListener
} }
public Storage getStorage() { return storage; } public Storage getStorage() { return storage; }
public CoordinatorListener getListener() { return listener; }
// for web page detailed stats // for web page detailed stats
public List<Peer> peerList() public List<Peer> peerList()
@ -166,6 +181,11 @@ public class PeerCoordinator implements PeerListener
return id; return id;
} }
public String getName()
{
return snark.getName();
}
public boolean completed() public boolean completed()
{ {
return storage.complete(); return storage.complete();
@ -1107,6 +1127,14 @@ public class PeerCoordinator implements PeerListener
return MAX_UPLOADERS; return MAX_UPLOADERS;
} }
/**
* @return current
* @since 0.8.4
*/
public int getUploaders() {
return uploaders;
}
public boolean overUpBWLimit() public boolean overUpBWLimit()
{ {
if (listener != null) if (listener != null)

View File

@ -26,6 +26,7 @@ import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
@ -112,6 +113,8 @@ public class Snark
} }
/******** No, not maintaining a command-line client
public static void main(String[] args) public static void main(String[] args)
{ {
System.out.println(copyright); System.out.println(copyright);
@ -235,19 +238,27 @@ public class Snark
} }
} }
***********/
public static final String PROP_MAX_CONNECTIONS = "i2psnark.maxConnections"; public static final String PROP_MAX_CONNECTIONS = "i2psnark.maxConnections";
public String torrent;
public MetaInfo meta; /** most of these used to be public, use accessors below instead */
public Storage storage; private final String torrent;
public PeerCoordinator coordinator; private MetaInfo meta;
public ConnectionAcceptor acceptor; private Storage storage;
public TrackerClient trackerclient; private PeerCoordinator coordinator;
public String rootDataDir = "."; private ConnectionAcceptor acceptor;
public CompleteListener completeListener; private TrackerClient trackerclient;
public boolean stopped; private String rootDataDir = ".";
byte[] id; private final CompleteListener completeListener;
public I2PSnarkUtil _util; private boolean stopped;
private PeerCoordinatorSet _peerCoordinatorSet; private byte[] id;
private byte[] infoHash;
private final I2PSnarkUtil _util;
private final PeerCoordinatorSet _peerCoordinatorSet;
private String trackerProblems;
private int trackerSeenPeers;
/** from main() via parseArguments() single torrent */ /** from main() via parseArguments() single torrent */
Snark(I2PSnarkUtil util, String torrent, String ip, int user_port, Snark(I2PSnarkUtil util, String torrent, String ip, int user_port,
@ -486,7 +497,7 @@ public class Snark
// single torrent // single torrent
acceptor = new ConnectionAcceptor(_util, serversocket, new PeerAcceptor(coordinator)); acceptor = new ConnectionAcceptor(_util, serversocket, new PeerAcceptor(coordinator));
} }
trackerclient = new TrackerClient(_util, meta, coordinator); trackerclient = new TrackerClient(_util, meta, coordinator, this);
} }
stopped = false; stopped = false;
@ -496,8 +507,7 @@ public class Snark
// restart safely, so lets build a new one to replace the old // restart safely, so lets build a new one to replace the old
if (_peerCoordinatorSet != null) if (_peerCoordinatorSet != null)
_peerCoordinatorSet.remove(coordinator); _peerCoordinatorSet.remove(coordinator);
PeerCoordinator newCoord = new PeerCoordinator(_util, coordinator.getID(), coordinator.getMetaInfo(), PeerCoordinator newCoord = new PeerCoordinator(_util, id, meta, storage, this, this);
coordinator.getStorage(), coordinator.getListener(), this);
if (_peerCoordinatorSet != null) if (_peerCoordinatorSet != null)
_peerCoordinatorSet.add(newCoord); _peerCoordinatorSet.add(newCoord);
coordinator = newCoord; coordinator = newCoord;
@ -517,7 +527,7 @@ public class Snark
} }
fatal("Could not reopen storage", ioe); fatal("Could not reopen storage", ioe);
} }
TrackerClient newClient = new TrackerClient(_util, coordinator.getMetaInfo(), coordinator); TrackerClient newClient = new TrackerClient(_util, coordinator.getMetaInfo(), coordinator, this);
if (!trackerclient.halted()) if (!trackerclient.halted())
trackerclient.halt(); trackerclient.halt();
trackerclient = newClient; trackerclient = newClient;
@ -553,18 +563,223 @@ public class Snark
_util.disconnect(); _util.disconnect();
} }
static Snark parseArguments(String[] args) private static Snark parseArguments(String[] args)
{ {
return parseArguments(args, null, null); return parseArguments(args, null, null);
} }
// Accessors
/**
* @return file name of .torrent file (should be full absolute path), or a fake name if in magnet mode.
* @since 0.8.4
*/
public String getName() {
return torrent;
}
/**
* @return base name of torrent [filtered version of getMetaInfo.getName()], or a fake name if in magnet mode
* @since 0.8.4
*/
public String getBaseName() {
if (storage != null)
return storage.getBaseName();
return torrent;
}
/**
* @return always will be valid even in magnet mode
* @since 0.8.4
*/
public byte[] getID() {
return id;
}
/**
* @return always will be valid even in magnet mode
* @since 0.8.4
*/
public byte[] getInfoHash() {
if (meta != null)
return meta.getInfoHash();
return infoHash;
}
/**
* @return may be null if in magnet mode
* @since 0.8.4
*/
public MetaInfo getMetaInfo() {
return meta;
}
/**
* @return may be null if in magnet mode
* @since 0.8.4
*/
public Storage getStorage() {
return storage;
}
/**
* @since 0.8.4
*/
public boolean isStopped() {
return stopped;
}
/**
* @since 0.8.4
*/
public long getDownloadRate() {
PeerCoordinator coord = coordinator;
if (coord != null)
return coord.getDownloadRate();
return 0;
}
/**
* @since 0.8.4
*/
public long getUploadRate() {
PeerCoordinator coord = coordinator;
if (coord != null)
return coord.getUploadRate();
return 0;
}
/**
* @since 0.8.4
*/
public long getDownloaded() {
PeerCoordinator coord = coordinator;
if (coord != null)
return coord.getDownloaded();
return 0;
}
/**
* @since 0.8.4
*/
public long getUploaded() {
PeerCoordinator coord = coordinator;
if (coord != null)
return coord.getUploaded();
return 0;
}
/**
* @since 0.8.4
*/
public int getPeerCount() {
PeerCoordinator coord = coordinator;
if (coord != null)
return coord.getPeerCount();
return 0;
}
/**
* @since 0.8.4
*/
public List<Peer> getPeerList() {
PeerCoordinator coord = coordinator;
if (coord != null)
return coord.peerList();
return Collections.EMPTY_LIST;
}
/**
* @return String returned from tracker, or null if no error
* @since 0.8.4
*/
public String getTrackerProblems() {
return trackerProblems;
}
/**
* @param p tracker error string or null
* @since 0.8.4
*/
public void setTrackerProblems(String p) {
trackerProblems = p;
}
/**
* @return count returned from tracker
* @since 0.8.4
*/
public int getTrackerSeenPeers() {
return trackerSeenPeers;
}
/**
* @since 0.8.4
*/
public void setTrackerSeenPeers(int p) {
trackerSeenPeers = p;
}
/**
* @since 0.8.4
*/
public void updatePiecePriorities() {
PeerCoordinator coord = coordinator;
if (coord != null)
coord.updatePiecePriorities();
}
/**
* @return total of all torrent files, or total of metainfo file if fetching magnet, or -1
* @since 0.8.4
*/
public long getTotalLength() {
if (meta != null)
return meta.getTotalLength();
// FIXME else return metainfo length if available
return -1;
}
/**
* @return needed of all torrent files, or total of metainfo file if fetching magnet, or -1
* @since 0.8.4
*/
public long getNeeded() {
if (storage != null)
return storage.needed();
// FIXME else return metainfo length if available
return -1;
}
/**
* @param p the piece number
* @return metainfo piece length or 16K if fetching magnet
* @since 0.8.4
*/
public int getPieceLength(int p) {
if (meta != null)
return meta.getPieceLength(p);
return 16*1024;
}
/**
* @return true if restarted
* @since 0.8.4
*/
public boolean restartAcceptor() {
if (acceptor == null)
return false;
acceptor.restart();
return true;
}
/** /**
* Sets debug, ip and torrent variables then creates a Snark * Sets debug, ip and torrent variables then creates a Snark
* instance. Calls usage(), which terminates the program, if * instance. Calls usage(), which terminates the program, if
* non-valid argument list. The given listeners will be * non-valid argument list. The given listeners will be
* passed to all components that take one. * passed to all components that take one.
*/ */
static Snark parseArguments(String[] args, private static Snark parseArguments(String[] args,
StorageListener slistener, StorageListener slistener,
CoordinatorListener clistener) CoordinatorListener clistener)
{ {
@ -719,7 +934,7 @@ public class Snark
/** /**
* Aborts program abnormally. * Aborts program abnormally.
*/ */
public void fatal(String s) private void fatal(String s)
{ {
fatal(s, null); fatal(s, null);
} }
@ -727,7 +942,7 @@ public class Snark
/** /**
* Aborts program abnormally. * Aborts program abnormally.
*/ */
public void fatal(String s, Throwable t) private void fatal(String s, Throwable t)
{ {
_util.debug(s, ERROR, t); _util.debug(s, ERROR, t);
//System.err.println("snark: " + s + ((t == null) ? "" : (": " + t))); //System.err.println("snark: " + s + ((t == null) ? "" : (": " + t)));
@ -751,7 +966,7 @@ public class Snark
// System.out.println(peer.toString()); // System.out.println(peer.toString());
} }
boolean allocating = false; private boolean allocating = false;
public void storageCreateFile(Storage storage, String name, long length) public void storageCreateFile(Storage storage, String name, long length)
{ {
//if (allocating) //if (allocating)
@ -774,9 +989,9 @@ public class Snark
// System.out.println(); // We have all the disk space we need. // System.out.println(); // We have all the disk space we need.
} }
boolean allChecked = false; private boolean allChecked = false;
boolean checking = false; private boolean checking = false;
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;

View File

@ -359,7 +359,7 @@ public class SnarkManager implements Snark.CompleteListener {
Set names = listTorrentFiles(); Set names = listTorrentFiles();
for (Iterator iter = names.iterator(); iter.hasNext(); ) { for (Iterator iter = names.iterator(); iter.hasNext(); ) {
Snark snark = getTorrent((String)iter.next()); Snark snark = getTorrent((String)iter.next());
if ( (snark != null) && (!snark.stopped) ) { if ( (snark != null) && (!snark.isStopped()) ) {
snarksActive = true; snarksActive = true;
break; break;
} }
@ -398,9 +398,8 @@ public class SnarkManager implements Snark.CompleteListener {
for (Iterator iter = names.iterator(); iter.hasNext(); ) { for (Iterator iter = names.iterator(); iter.hasNext(); ) {
String name = (String)iter.next(); String name = (String)iter.next();
Snark snark = getTorrent(name); Snark snark = getTorrent(name);
if ( (snark != null) && (snark.acceptor != null) ) { if (snark != null && snark.restartAcceptor()) {
snark.acceptor.restart(); addMessage(_("I2CP listener restarted for \"{0}\"", snark.getBaseName()));
addMessage(_("I2CP listener restarted for \"{0}\"", snark.meta.getName()));
} }
} }
} }
@ -478,7 +477,7 @@ public class SnarkManager implements Snark.CompleteListener {
public Snark getTorrentByBaseName(String filename) { public Snark getTorrentByBaseName(String filename) {
synchronized (_snarks) { synchronized (_snarks) {
for (Snark s : _snarks.values()) { for (Snark s : _snarks.values()) {
if (s.storage.getBaseName().equals(filename)) if (s.getBaseName().equals(filename))
return s; return s;
} }
} }
@ -554,7 +553,6 @@ public class SnarkManager implements Snark.CompleteListener {
_peerCoordinatorSet, _connectionAcceptor, _peerCoordinatorSet, _connectionAcceptor,
false, dataDir.getPath()); false, dataDir.getPath());
loadSavedFilePriorities(torrent); loadSavedFilePriorities(torrent);
torrent.completeListener = this;
synchronized (_snarks) { synchronized (_snarks) {
_snarks.put(filename, torrent); _snarks.put(filename, torrent);
} }
@ -572,12 +570,11 @@ public class SnarkManager implements Snark.CompleteListener {
return; return;
} }
// ok, snark created, now lets start it up or configure it further // ok, snark created, now lets start it up or configure it further
File f = new File(filename);
if (!dontAutoStart && shouldAutoStart()) { if (!dontAutoStart && shouldAutoStart()) {
torrent.startTorrent(); torrent.startTorrent();
addMessage(_("Torrent added and started: \"{0}\"", torrent.storage.getBaseName())); addMessage(_("Torrent added and started: \"{0}\"", torrent.getBaseName()));
} else { } else {
addMessage(_("Torrent added: \"{0}\"", torrent.storage.getBaseName())); addMessage(_("Torrent added: \"{0}\"", torrent.getBaseName()));
} }
} }
@ -585,8 +582,7 @@ public class SnarkManager implements Snark.CompleteListener {
* Get the timestamp for a torrent from the config file * Get the timestamp for a torrent from the config file
*/ */
public long getSavedTorrentTime(Snark snark) { public long getSavedTorrentTime(Snark snark) {
MetaInfo metainfo = snark.meta; byte[] ih = snark.getInfoHash();
byte[] ih = metainfo.getInfoHash();
String infohash = Base64.encode(ih); String infohash = Base64.encode(ih);
infohash = infohash.replace('=', '$'); infohash = infohash.replace('=', '$');
String time = _config.getProperty(PROP_META_PREFIX + infohash + PROP_META_BITFIELD_SUFFIX); String time = _config.getProperty(PROP_META_PREFIX + infohash + PROP_META_BITFIELD_SUFFIX);
@ -605,8 +601,10 @@ public class SnarkManager implements Snark.CompleteListener {
* Convert "." to a full bitfield. * Convert "." to a full bitfield.
*/ */
public BitField getSavedTorrentBitField(Snark snark) { public BitField getSavedTorrentBitField(Snark snark) {
MetaInfo metainfo = snark.meta; MetaInfo metainfo = snark.getMetaInfo();
byte[] ih = metainfo.getInfoHash(); if (metainfo == null)
return null;
byte[] ih = snark.getInfoHash();
String infohash = Base64.encode(ih); String infohash = Base64.encode(ih);
infohash = infohash.replace('=', '$'); infohash = infohash.replace('=', '$');
String bf = _config.getProperty(PROP_META_PREFIX + infohash + PROP_META_BITFIELD_SUFFIX); String bf = _config.getProperty(PROP_META_PREFIX + infohash + PROP_META_BITFIELD_SUFFIX);
@ -636,10 +634,13 @@ public class SnarkManager implements Snark.CompleteListener {
* @since 0.8.1 * @since 0.8.1
*/ */
public void loadSavedFilePriorities(Snark snark) { public void loadSavedFilePriorities(Snark snark) {
MetaInfo metainfo = snark.meta; MetaInfo metainfo = snark.getMetaInfo();
Storage storage = snark.getStorage();
if (metainfo == null || storage == null)
return;
if (metainfo.getFiles() == null) if (metainfo.getFiles() == null)
return; return;
byte[] ih = metainfo.getInfoHash(); byte[] ih = snark.getInfoHash();
String infohash = Base64.encode(ih); String infohash = Base64.encode(ih);
infohash = infohash.replace('=', '$'); infohash = infohash.replace('=', '$');
String pri = _config.getProperty(PROP_META_PREFIX + infohash + PROP_META_PRIORITY_SUFFIX); String pri = _config.getProperty(PROP_META_PREFIX + infohash + PROP_META_PRIORITY_SUFFIX);
@ -655,7 +656,7 @@ public class SnarkManager implements Snark.CompleteListener {
} catch (Throwable t) {} } catch (Throwable t) {}
} }
} }
snark.storage.setFilePriorities(rv); storage.setFilePriorities(rv);
} }
/** /**
@ -777,21 +778,15 @@ public class SnarkManager implements Snark.CompleteListener {
remaining = _snarks.size(); remaining = _snarks.size();
} }
if (torrent != null) { if (torrent != null) {
boolean wasStopped = torrent.stopped; boolean wasStopped = torrent.isStopped();
torrent.stopTorrent(); torrent.stopTorrent();
if (remaining == 0) { if (remaining == 0) {
// should we disconnect/reconnect here (taking care to deal with the other thread's // should we disconnect/reconnect here (taking care to deal with the other thread's
// I2PServerSocket.accept() call properly?) // I2PServerSocket.accept() call properly?)
////_util. ////_util.
} }
String name;
if (torrent.storage != null) {
name = torrent.storage.getBaseName();
} else {
name = sfile.getName();
}
if (!wasStopped) if (!wasStopped)
addMessage(_("Torrent stopped: \"{0}\"", name)); addMessage(_("Torrent stopped: \"{0}\"", torrent.getBaseName()));
} }
return torrent; return torrent;
} }
@ -804,14 +799,10 @@ public class SnarkManager implements Snark.CompleteListener {
if (torrent != null) { if (torrent != null) {
File torrentFile = new File(filename); File torrentFile = new File(filename);
torrentFile.delete(); torrentFile.delete();
String name; Storage storage = torrent.getStorage();
if (torrent.storage != null) { if (storage != null)
removeTorrentStatus(torrent.storage.getMetaInfo()); removeTorrentStatus(storage.getMetaInfo());
name = torrent.storage.getBaseName(); addMessage(_("Torrent removed: \"{0}\"", torrent.getBaseName()));
} else {
name = torrentFile.getName();
}
addMessage(_("Torrent removed: \"{0}\"", name));
} }
} }
@ -843,18 +834,24 @@ public class SnarkManager implements Snark.CompleteListener {
/** two listeners */ /** two listeners */
public void torrentComplete(Snark snark) { public void torrentComplete(Snark snark) {
MetaInfo meta = snark.getMetaInfo();
Storage storage = snark.getStorage();
if (meta == null || storage == null)
return;
StringBuilder buf = new StringBuilder(256); StringBuilder buf = new StringBuilder(256);
buf.append("<a href=\"/i2psnark/").append(snark.storage.getBaseName()); buf.append("<a href=\"/i2psnark/").append(storage.getBaseName());
if (snark.meta.getFiles() != null) if (meta.getFiles() != null)
buf.append('/'); buf.append('/');
buf.append("\">").append(snark.storage.getBaseName()).append("</a>"); buf.append("\">").append(storage.getBaseName()).append("</a>");
long len = snark.meta.getTotalLength();
addMessage(_("Download finished: {0}", buf.toString())); // + " (" + _("size: {0}B", DataHelper.formatSize2(len)) + ')'); addMessage(_("Download finished: {0}", buf.toString())); // + " (" + _("size: {0}B", DataHelper.formatSize2(len)) + ')');
updateStatus(snark); updateStatus(snark);
} }
public void updateStatus(Snark snark) { public void updateStatus(Snark snark) {
saveTorrentStatus(snark.meta, snark.storage.getBitField(), snark.storage.getFilePriorities()); MetaInfo meta = snark.getMetaInfo();
Storage storage = snark.getStorage();
if (meta != null && storage != null)
saveTorrentStatus(meta, storage.getBitField(), storage.getFilePriorities());
} }
private void monitorTorrents(File dir) { private void monitorTorrents(File dir) {
@ -984,7 +981,7 @@ public class SnarkManager implements Snark.CompleteListener {
Set names = listTorrentFiles(); Set names = listTorrentFiles();
for (Iterator iter = names.iterator(); iter.hasNext(); ) { for (Iterator iter = names.iterator(); iter.hasNext(); ) {
Snark snark = getTorrent((String)iter.next()); Snark snark = getTorrent((String)iter.next());
if ( (snark != null) && (!snark.stopped) ) if ( (snark != null) && (!snark.isStopped()) )
snark.stopTorrent(); snark.stopTorrent();
} }
} }

View File

@ -38,6 +38,7 @@ public class StaticSnark
//Security.addProvider(gnu); //Security.addProvider(gnu);
// And finally call the normal starting point. // And finally call the normal starting point.
Snark.main(args); //Snark.main(args);
System.err.println("unsupported");
} }
} }

View File

@ -34,9 +34,11 @@ import java.util.Random;
import java.util.Set; import java.util.Set;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.data.Hash;
import net.i2p.util.I2PAppThread; import net.i2p.util.I2PAppThread;
import net.i2p.util.Log; import net.i2p.util.Log;
/** /**
* Informs metainfo tracker of events and gets new peers for peer * Informs metainfo tracker of events and gets new peers for peer
* coordinator. * coordinator.
@ -63,6 +65,7 @@ public class TrackerClient extends I2PAppThread
private I2PSnarkUtil _util; private I2PSnarkUtil _util;
private final MetaInfo meta; private final MetaInfo meta;
private final PeerCoordinator coordinator; private final PeerCoordinator coordinator;
private final Snark snark;
private final int port; private final int port;
private boolean stop; private boolean stop;
@ -70,15 +73,16 @@ public class TrackerClient extends I2PAppThread
private List trackers; private List trackers;
public TrackerClient(I2PSnarkUtil util, MetaInfo meta, PeerCoordinator coordinator) public TrackerClient(I2PSnarkUtil util, MetaInfo meta, PeerCoordinator coordinator, Snark snark)
{ {
super(); super();
// Set unique name. // Set unique name.
String id = urlencode(coordinator.getID()); String id = urlencode(snark.getID());
setName("TrackerClient " + id.substring(id.length() - 12)); setName("TrackerClient " + id.substring(id.length() - 12));
_util = util; _util = util;
this.meta = meta; this.meta = meta;
this.coordinator = coordinator; this.coordinator = coordinator;
this.snark = snark;
this.port = 6881; //(port == -1) ? 9 : port; this.port = 6881; //(port == -1) ? 9 : port;
@ -119,10 +123,10 @@ public class TrackerClient extends I2PAppThread
public void run() public void run()
{ {
String infoHash = urlencode(meta.getInfoHash()); String infoHash = urlencode(meta.getInfoHash());
String peerID = urlencode(coordinator.getID()); String peerID = urlencode(snark.getID());
_log.debug("Announce: [" + meta.getAnnounce() + "] infoHash: " + infoHash); _log.debug("Announce: [" + meta.getAnnounce() + "] infoHash: " + infoHash);
// Construct the list of trackers for this torrent, // Construct the list of trackers for this torrent,
// starting with the primary one listed in the metainfo, // starting with the primary one listed in the metainfo,
// followed by the secondary open trackers // followed by the secondary open trackers
@ -200,7 +204,7 @@ public class TrackerClient extends I2PAppThread
firstTime = false; firstTime = false;
} else if (completed && runStarted) } else if (completed && runStarted)
delay = 3*SLEEP*60*1000 + random; delay = 3*SLEEP*60*1000 + random;
else if (coordinator.trackerProblems != null && ++consecutiveFails < MAX_CONSEC_FAILS) else if (snark.getTrackerProblems() != null && ++consecutiveFails < MAX_CONSEC_FAILS)
delay = INITIAL_SLEEP; delay = INITIAL_SLEEP;
else else
// sleep a while, when we wake up we will contact only the trackers whose intervals have passed // sleep a while, when we wake up we will contact only the trackers whose intervals have passed
@ -251,7 +255,7 @@ public class TrackerClient extends I2PAppThread
uploaded, downloaded, left, uploaded, downloaded, left,
event); event);
coordinator.trackerProblems = null; snark.setTrackerProblems(null);
tr.trackerProblems = null; tr.trackerProblems = null;
tr.registerFails = 0; tr.registerFails = 0;
tr.consecutiveFails = 0; tr.consecutiveFails = 0;
@ -262,8 +266,8 @@ public class TrackerClient extends I2PAppThread
Set peers = info.getPeers(); Set peers = info.getPeers();
tr.seenPeers = info.getPeerCount(); tr.seenPeers = info.getPeerCount();
if (coordinator.trackerSeenPeers < tr.seenPeers) // update rising number quickly if (snark.getTrackerSeenPeers() < tr.seenPeers) // update rising number quickly
coordinator.trackerSeenPeers = tr.seenPeers; snark.setTrackerSeenPeers(tr.seenPeers);
if ( (left > 0) && (!completed) ) { if ( (left > 0) && (!completed) ) {
// we only want to talk to new people if we need things // we only want to talk to new people if we need things
// from them (duh) // from them (duh)
@ -293,12 +297,12 @@ public class TrackerClient extends I2PAppThread
tr.trackerProblems = ioe.getMessage(); tr.trackerProblems = ioe.getMessage();
// don't show secondary tracker problems to the user // don't show secondary tracker problems to the user
if (tr.isPrimary) if (tr.isPrimary)
coordinator.trackerProblems = tr.trackerProblems; snark.setTrackerProblems(tr.trackerProblems);
if (tr.trackerProblems.toLowerCase().startsWith(NOT_REGISTERED)) { if (tr.trackerProblems.toLowerCase().startsWith(NOT_REGISTERED)) {
// Give a guy some time to register it if using opentrackers too // Give a guy some time to register it if using opentrackers too
if (trackers.size() == 1) { if (trackers.size() == 1) {
stop = true; stop = true;
coordinator.snark.stopTorrent(); snark.stopTorrent();
} else { // hopefully each on the opentrackers list is really open } else { // hopefully each on the opentrackers list is really open
if (tr.registerFails++ > MAX_REGISTER_FAILS) if (tr.registerFails++ > MAX_REGISTER_FAILS)
tr.stop = true; tr.stop = true;
@ -316,7 +320,7 @@ public class TrackerClient extends I2PAppThread
} // *** end of trackers loop here } // *** end of trackers loop here
// we could try and total the unique peers but that's too hard for now // we could try and total the unique peers but that's too hard for now
coordinator.trackerSeenPeers = maxSeenPeers; snark.setTrackerSeenPeers(maxSeenPeers);
if (!runStarted) if (!runStarted)
_util.debug(" Retrying in one minute...", Snark.DEBUG); _util.debug(" Retrying in one minute...", Snark.DEBUG);
} // *** end of while loop } // *** end of while loop
@ -377,8 +381,8 @@ public class TrackerClient extends I2PAppThread
try { try {
in = new FileInputStream(fetched); in = new FileInputStream(fetched);
TrackerInfo info = new TrackerInfo(in, coordinator.getID(), TrackerInfo info = new TrackerInfo(in, snark.getID(),
coordinator.getMetaInfo()); snark.getMetaInfo());
_util.debug("TrackerClient response: " + info, Snark.INFO); _util.debug("TrackerClient response: " + info, Snark.INFO);
String failure = info.getFailureReason(); String failure = info.getFailureReason();

View File

@ -26,6 +26,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.data.Base32;
import net.i2p.data.Base64; import net.i2p.data.Base64;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.util.FileUtil; import net.i2p.util.FileUtil;
@ -361,7 +362,7 @@ public class I2PSnarkServlet extends Default {
for (int i = 0; i < snarks.size(); i++) { for (int i = 0; i < snarks.size(); i++) {
Snark snark = (Snark)snarks.get(i); Snark snark = (Snark)snarks.get(i);
boolean showDebug = "2".equals(peerParam); boolean showDebug = "2".equals(peerParam);
boolean showPeers = showDebug || "1".equals(peerParam) || Base64.encode(snark.meta.getInfoHash()).equals(peerParam); boolean showPeers = showDebug || "1".equals(peerParam) || Base64.encode(snark.getInfoHash()).equals(peerParam);
displaySnark(out, snark, uri, i, stats, showPeers, isDegraded, showDebug); displaySnark(out, snark, uri, i, stats, showPeers, isDegraded, showDebug);
} }
@ -452,7 +453,7 @@ public class I2PSnarkServlet extends Default {
if (newURL != null) { if (newURL != null) {
if (newURL.startsWith("http://")) { if (newURL.startsWith("http://")) {
_manager.addMessage(_("Fetching {0}", urlify(newURL))); _manager.addMessage(_("Fetching {0}", urlify(newURL)));
I2PAppThread fetch = new I2PAppThread(new FetchAndAdd(_manager, newURL), "Fetch and add"); I2PAppThread fetch = new I2PAppThread(new FetchAndAdd(_manager, newURL), "Fetch and add", true);
fetch.start(); fetch.start();
} else { } else {
_manager.addMessage(_("Invalid URL - must start with http://")); _manager.addMessage(_("Invalid URL - must start with http://"));
@ -468,7 +469,7 @@ public class I2PSnarkServlet extends Default {
for (Iterator iter = _manager.listTorrentFiles().iterator(); iter.hasNext(); ) { for (Iterator iter = _manager.listTorrentFiles().iterator(); iter.hasNext(); ) {
String name = (String)iter.next(); String name = (String)iter.next();
Snark snark = _manager.getTorrent(name); Snark snark = _manager.getTorrent(name);
if ( (snark != null) && (DataHelper.eq(infoHash, snark.meta.getInfoHash())) ) { if ( (snark != null) && (DataHelper.eq(infoHash, snark.getInfoHash())) ) {
_manager.stopTorrent(name, false); _manager.stopTorrent(name, false);
break; break;
} }
@ -482,11 +483,9 @@ public class I2PSnarkServlet extends Default {
if ( (infoHash != null) && (infoHash.length == 20) ) { // valid sha1 if ( (infoHash != null) && (infoHash.length == 20) ) { // valid sha1
for (String name : _manager.listTorrentFiles()) { for (String name : _manager.listTorrentFiles()) {
Snark snark = _manager.getTorrent(name); Snark snark = _manager.getTorrent(name);
if ( (snark != null) && (DataHelper.eq(infoHash, snark.meta.getInfoHash())) ) { if ( (snark != null) && (DataHelper.eq(infoHash, snark.getInfoHash())) ) {
snark.startTorrent(); snark.startTorrent();
if (snark.storage != null) _manager.addMessage(_("Starting up torrent {0}", snark.getBaseName()));
name = snark.storage.getBaseName();
_manager.addMessage(_("Starting up torrent {0}", name));
break; break;
} }
} }
@ -500,8 +499,12 @@ public class I2PSnarkServlet extends Default {
for (Iterator iter = _manager.listTorrentFiles().iterator(); iter.hasNext(); ) { for (Iterator iter = _manager.listTorrentFiles().iterator(); iter.hasNext(); ) {
String name = (String)iter.next(); String name = (String)iter.next();
Snark snark = _manager.getTorrent(name); Snark snark = _manager.getTorrent(name);
if ( (snark != null) && (DataHelper.eq(infoHash, snark.meta.getInfoHash())) ) { if ( (snark != null) && (DataHelper.eq(infoHash, snark.getInfoHash())) ) {
_manager.stopTorrent(name, true); _manager.stopTorrent(name, true);
MetaInfo meta = snark.getMetaInfo();
if (meta == null) {
return;
}
// should we delete the torrent file? // should we delete the torrent file?
// yeah, need to, otherwise it'll get autoadded again (at the moment // yeah, need to, otherwise it'll get autoadded again (at the moment
File f = new File(name); File f = new File(name);
@ -520,13 +523,17 @@ public class I2PSnarkServlet extends Default {
for (Iterator iter = _manager.listTorrentFiles().iterator(); iter.hasNext(); ) { for (Iterator iter = _manager.listTorrentFiles().iterator(); iter.hasNext(); ) {
String name = (String)iter.next(); String name = (String)iter.next();
Snark snark = _manager.getTorrent(name); Snark snark = _manager.getTorrent(name);
if ( (snark != null) && (DataHelper.eq(infoHash, snark.meta.getInfoHash())) ) { if ( (snark != null) && (DataHelper.eq(infoHash, snark.getInfoHash())) ) {
_manager.stopTorrent(name, true); _manager.stopTorrent(name, true);
MetaInfo meta = snark.getMetaInfo();
if (meta == null) {
return;
}
File f = new File(name); File f = new File(name);
f.delete(); f.delete();
_manager.addMessage(_("Torrent file deleted: {0}", f.getAbsolutePath())); _manager.addMessage(_("Torrent file deleted: {0}", f.getAbsolutePath()));
List files = snark.meta.getFiles(); List files = meta.getFiles();
String dataFile = snark.meta.getName(); String dataFile = snark.getBaseName();
f = new File(_manager.getDataDir(), dataFile); f = new File(_manager.getDataDir(), dataFile);
if (files == null) { // single file torrent if (files == null) { // single file torrent
if (f.delete()) if (f.delete())
@ -617,8 +624,8 @@ public class I2PSnarkServlet extends Default {
List snarks = getSortedSnarks(req); List snarks = getSortedSnarks(req);
for (int i = 0; i < snarks.size(); i++) { for (int i = 0; i < snarks.size(); i++) {
Snark snark = (Snark)snarks.get(i); Snark snark = (Snark)snarks.get(i);
if (!snark.stopped) if (!snark.isStopped())
_manager.stopTorrent(snark.torrent, false); _manager.stopTorrent(snark.getName(), false);
} }
if (_manager.util().connected()) { if (_manager.util().connected()) {
// Give the stopped announces time to get out // Give the stopped announces time to get out
@ -631,7 +638,7 @@ public class I2PSnarkServlet extends Default {
List snarks = getSortedSnarks(req); List snarks = getSortedSnarks(req);
for (int i = 0; i < snarks.size(); i++) { for (int i = 0; i < snarks.size(); i++) {
Snark snark = (Snark)snarks.get(i); Snark snark = (Snark)snarks.get(i);
if (snark.stopped) if (snark.isStopped())
snark.startTorrent(); snark.startTorrent();
} }
} else { } else {
@ -699,7 +706,7 @@ public class I2PSnarkServlet extends Default {
private static final int MAX_DISPLAYED_ERROR_LENGTH = 43; private static final int MAX_DISPLAYED_ERROR_LENGTH = 43;
private void displaySnark(PrintWriter out, Snark snark, String uri, int row, long stats[], boolean showPeers, private void displaySnark(PrintWriter out, Snark snark, String uri, int row, long stats[], boolean showPeers,
boolean isDegraded, boolean showDebug) throws IOException { boolean isDegraded, boolean showDebug) throws IOException {
String filename = snark.torrent; String filename = snark.getName();
File f = new File(filename); File f = new File(filename);
filename = f.getName(); // the torrent may be the canonical name, so lets just grab the local name filename = f.getName(); // the torrent may be the canonical name, so lets just grab the local name
int i = filename.lastIndexOf(".torrent"); int i = filename.lastIndexOf(".torrent");
@ -710,28 +717,21 @@ public class I2PSnarkServlet extends Default {
fullFilename = new String(filename); fullFilename = new String(filename);
filename = filename.substring(0, MAX_DISPLAYED_FILENAME_LENGTH) + "&hellip;"; filename = filename.substring(0, MAX_DISPLAYED_FILENAME_LENGTH) + "&hellip;";
} }
long total = snark.meta.getTotalLength(); long total = snark.getTotalLength();
// Early typecast, avoid possibly overflowing a temp integer // Early typecast, avoid possibly overflowing a temp integer
long remaining = (long) snark.storage.needed() * (long) snark.meta.getPieceLength(0); long remaining = (long) snark.getNeeded() * (long) snark.getPieceLength(0);
if (remaining > total) if (remaining > total)
remaining = total; remaining = total;
long downBps = 0; long downBps = snark.getDownloadRate();
long upBps = 0; long upBps = snark.getUploadRate();
if (snark.coordinator != null) {
downBps = snark.coordinator.getDownloadRate();
upBps = snark.coordinator.getUploadRate();
}
long remainingSeconds; long remainingSeconds;
if (downBps > 0) if (downBps > 0)
remainingSeconds = remaining / downBps; remainingSeconds = remaining / downBps;
else else
remainingSeconds = -1; remainingSeconds = -1;
boolean isRunning = !snark.stopped; boolean isRunning = !snark.isStopped();
long uploaded = 0; long uploaded = snark.getUploaded();
if (snark.coordinator != null) { stats[0] += snark.getDownloaded();
uploaded = snark.coordinator.getUploaded();
stats[0] += snark.coordinator.getDownloaded();
}
stats[1] += uploaded; stats[1] += uploaded;
if (isRunning) { if (isRunning) {
stats[2] += downBps; stats[2] += downBps;
@ -739,25 +739,21 @@ public class I2PSnarkServlet extends Default {
} }
stats[5] += total; stats[5] += total;
boolean isValid = snark.meta != null; MetaInfo meta = snark.getMetaInfo();
boolean singleFile = snark.meta.getFiles() == null; boolean isValid = meta != null;
boolean singleFile = (!isValid) || meta.getFiles() == null;
String err = null; String err = snark.getTrackerProblems();
int curPeers = 0; int curPeers = snark.getPeerCount();
int knownPeers = 0; stats[4] += curPeers;
if (snark.coordinator != null) { int knownPeers = Math.max(curPeers, snark.getTrackerSeenPeers());
err = snark.coordinator.trackerProblems;
curPeers = snark.coordinator.getPeerCount();
stats[4] += curPeers;
knownPeers = Math.max(curPeers, snark.coordinator.trackerSeenPeers);
}
String rowClass = (row % 2 == 0 ? "snarkTorrentEven" : "snarkTorrentOdd"); String rowClass = (row % 2 == 0 ? "snarkTorrentEven" : "snarkTorrentOdd");
String statusString; String statusString;
if (err != null) { if (err != null) {
if (isRunning && curPeers > 0 && !showPeers) if (isRunning && curPeers > 0 && !showPeers)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") + statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") +
": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" + ": <a href=\"" + uri + "?p=" + Base64.encode(snark.getInfoHash()) + "\">" +
curPeers + thinsp(isDegraded) + curPeers + thinsp(isDegraded) +
ngettext("1 peer", "{0} peers", knownPeers) + "</a>"; ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
else if (isRunning) else if (isRunning)
@ -773,7 +769,7 @@ public class I2PSnarkServlet extends Default {
} else if (remaining <= 0) { } else if (remaining <= 0) {
if (isRunning && curPeers > 0 && !showPeers) if (isRunning && curPeers > 0 && !showPeers)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "seeding.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Seeding") + statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "seeding.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Seeding") +
": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" + ": <a href=\"" + uri + "?p=" + Base64.encode(snark.getInfoHash()) + "\">" +
curPeers + thinsp(isDegraded) + curPeers + thinsp(isDegraded) +
ngettext("1 peer", "{0} peers", knownPeers) + "</a>"; ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
else if (isRunning) else if (isRunning)
@ -785,7 +781,7 @@ public class I2PSnarkServlet extends Default {
} else { } else {
if (isRunning && curPeers > 0 && downBps > 0 && !showPeers) if (isRunning && curPeers > 0 && downBps > 0 && !showPeers)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "downloading.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("OK") + statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "downloading.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("OK") +
": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" + ": <a href=\"" + uri + "?p=" + Base64.encode(snark.getInfoHash()) + "\">" +
curPeers + thinsp(isDegraded) + curPeers + thinsp(isDegraded) +
ngettext("1 peer", "{0} peers", knownPeers) + "</a>"; ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
else if (isRunning && curPeers > 0 && downBps > 0) else if (isRunning && curPeers > 0 && downBps > 0)
@ -794,7 +790,7 @@ public class I2PSnarkServlet extends Default {
ngettext("1 peer", "{0} peers", knownPeers); ngettext("1 peer", "{0} peers", knownPeers);
else if (isRunning && curPeers > 0 && !showPeers) else if (isRunning && curPeers > 0 && !showPeers)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Stalled") + statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Stalled") +
": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" + ": <a href=\"" + uri + "?p=" + Base64.encode(snark.getInfoHash()) + "\">" +
curPeers + thinsp(isDegraded) + curPeers + thinsp(isDegraded) +
ngettext("1 peer", "{0} peers", knownPeers) + "</a>"; ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
else if (isRunning && curPeers > 0) else if (isRunning && curPeers > 0)
@ -816,7 +812,7 @@ public class I2PSnarkServlet extends Default {
out.write("<td class=\"" + rowClass + "\">"); out.write("<td class=\"" + rowClass + "\">");
// temporarily hardcoded for postman* and anonymity, requires bytemonsoon patch for lookup by info_hash // temporarily hardcoded for postman* and anonymity, requires bytemonsoon patch for lookup by info_hash
String announce = snark.meta.getAnnounce(); String announce = meta.getAnnounce();
if (announce.startsWith("http://YRgrgTLG") || announce.startsWith("http://8EoJZIKr") || if (announce.startsWith("http://YRgrgTLG") || announce.startsWith("http://8EoJZIKr") ||
announce.startsWith("http://lnQ6yoBT") || announce.startsWith("http://tracker2.postman.i2p/") || announce.startsWith("http://ahsplxkbhemefwvvml7qovzl5a2b5xo5i7lyai7ntdunvcyfdtna.b32.i2p/")) { announce.startsWith("http://lnQ6yoBT") || announce.startsWith("http://tracker2.postman.i2p/") || announce.startsWith("http://ahsplxkbhemefwvvml7qovzl5a2b5xo5i7lyai7ntdunvcyfdtna.b32.i2p/")) {
Map trackers = _manager.getTrackers(); Map trackers = _manager.getTrackers();
@ -833,7 +829,7 @@ public class I2PSnarkServlet extends Default {
continue; continue;
baseURL = baseURL.substring(e + 1); baseURL = baseURL.substring(e + 1);
out.write("<a href=\"" + baseURL + "details.php?dllist=1&amp;filelist=1&amp;info_hash="); out.write("<a href=\"" + baseURL + "details.php?dllist=1&amp;filelist=1&amp;info_hash=");
out.write(TrackerClient.urlencode(snark.meta.getInfoHash())); out.write(TrackerClient.urlencode(snark.getInfoHash()));
out.write("\" title=\"" + _("Details at {0} tracker", name) + "\" target=\"_blank\">"); out.write("\" title=\"" + _("Details at {0} tracker", name) + "\" target=\"_blank\">");
out.write("<img alt=\"" + _("Info") + "\" border=\"0\" src=\"" + _imgPath + "details.png\">"); out.write("<img alt=\"" + _("Info") + "\" border=\"0\" src=\"" + _imgPath + "details.png\">");
out.write("</a>"); out.write("</a>");
@ -843,13 +839,13 @@ public class I2PSnarkServlet extends Default {
out.write("</td>\n<td class=\"" + rowClass + "\">"); out.write("</td>\n<td class=\"" + rowClass + "\">");
StringBuilder buf = null; StringBuilder buf = null;
if (remaining == 0 || snark.meta.getFiles() != null) { if (remaining == 0 || meta.getFiles() != null) {
buf = new StringBuilder(128); buf = new StringBuilder(128);
buf.append("<a href=\"").append(snark.storage.getBaseName()); buf.append("<a href=\"").append(snark.getBaseName());
if (snark.meta.getFiles() != null) if (meta.getFiles() != null)
buf.append('/'); buf.append('/');
buf.append("\" title=\""); buf.append("\" title=\"");
if (snark.meta.getFiles() != null) if (meta.getFiles() != null)
buf.append(_("View files")); buf.append(_("View files"));
else else
buf.append(_("Open file")); buf.append(_("Open file"));
@ -857,21 +853,21 @@ public class I2PSnarkServlet extends Default {
out.write(buf.toString()); out.write(buf.toString());
} }
String icon; String icon;
if (snark.meta.getFiles() != null) if (meta.getFiles() != null)
icon = "folder"; icon = "folder";
else else
icon = toIcon(snark.meta.getName()); icon = toIcon(meta.getName());
if (remaining == 0 || snark.meta.getFiles() != null) { if (remaining == 0 || meta.getFiles() != null) {
out.write(toImg(icon, _("Open"))); out.write(toImg(icon, _("Open")));
out.write("</a>"); out.write("</a>");
} else { } else {
out.write(toImg(icon)); out.write(toImg(icon));
} }
out.write("</td><td class=\"snarkTorrentName " + rowClass + "\">"); out.write("</td><td class=\"snarkTorrentName " + rowClass + "\">");
if (remaining == 0 || snark.meta.getFiles() != null) if (remaining == 0 || meta.getFiles() != null)
out.write(buf.toString()); out.write(buf.toString());
out.write(filename); out.write(filename);
if (remaining == 0 || snark.meta.getFiles() != null) if (remaining == 0 || meta.getFiles() != null)
out.write("</a>"); out.write("</a>");
out.write("<td align=\"right\" class=\"snarkTorrentETA " + rowClass + "\">"); out.write("<td align=\"right\" class=\"snarkTorrentETA " + rowClass + "\">");
@ -897,8 +893,8 @@ public class I2PSnarkServlet extends Default {
out.write(formatSize(upBps) + "ps"); out.write(formatSize(upBps) + "ps");
out.write("</td>\n\t"); out.write("</td>\n\t");
out.write("<td align=\"center\" class=\"snarkTorrentAction " + rowClass + "\">"); out.write("<td align=\"center\" class=\"snarkTorrentAction " + rowClass + "\">");
String parameters = "&nonce=" + _nonce + "&torrent=" + Base64.encode(snark.meta.getInfoHash()); String parameters = "&nonce=" + _nonce + "&torrent=" + Base64.encode(snark.getInfoHash());
String b64 = Base64.encode(snark.meta.getInfoHash()); String b64 = Base64.encode(snark.getInfoHash());
if (showPeers) if (showPeers)
parameters = parameters + "&p=1"; parameters = parameters + "&p=1";
if (isRunning) { if (isRunning) {
@ -963,7 +959,7 @@ public class I2PSnarkServlet extends Default {
out.write("</td>\n</tr>\n"); out.write("</td>\n</tr>\n");
if(showPeers && isRunning && curPeers > 0) { if(showPeers && isRunning && curPeers > 0) {
List<Peer> peers = snark.coordinator.peerList(); List<Peer> peers = snark.getPeerList();
if (!showDebug) if (!showDebug)
Collections.sort(peers, new PeerComparator()); Collections.sort(peers, new PeerComparator());
for (Peer peer : peers) { for (Peer peer : peers) {
@ -996,7 +992,7 @@ public class I2PSnarkServlet extends Default {
out.write("<td class=\"snarkTorrentStatus " + rowClass + "\">"); out.write("<td class=\"snarkTorrentStatus " + rowClass + "\">");
out.write("</td>\n\t"); out.write("</td>\n\t");
out.write("<td align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">"); out.write("<td align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
float pct = (float) (100.0 * (float) peer.completed() / snark.meta.getPieces()); float pct = (float) (100.0 * (float) peer.completed() / meta.getPieces());
if (pct == 100.0) if (pct == 100.0)
out.write(_("Seed")); out.write(_("Seed"));
else { else {
@ -1358,6 +1354,11 @@ public class I2PSnarkServlet extends Default {
return _manager.util().getString(s, o); return _manager.util().getString(s, o);
} }
/** translate */
private String _(String s, Object o, Object o2) {
return _manager.util().getString(s, o, o2);
}
/** translate (ngettext) @since 0.7.14 */ /** translate (ngettext) @since 0.7.14 */
private String ngettext(String s, String p, int n) { private String ngettext(String s, String p, int n) {
return _manager.util().getString(n, s, p); return _manager.util().getString(n, s, p);
@ -1469,7 +1470,7 @@ public class I2PSnarkServlet extends Default {
if (parent) // always true if (parent) // always true
buf.append("<div class=\"page\"><div class=\"mainsection\">"); buf.append("<div class=\"page\"><div class=\"mainsection\">");
boolean showPriority = snark != null && !snark.storage.complete(); boolean showPriority = snark != null && snark.getStorage() != null && !snark.getStorage().complete();
if (showPriority) if (showPriority)
buf.append("<form action=\"").append(base).append("\" method=\"POST\">\n"); buf.append("<form action=\"").append(base).append("\" method=\"POST\">\n");
buf.append("<TABLE BORDER=0 class=\"snarkTorrents\" >" + buf.append("<TABLE BORDER=0 class=\"snarkTorrents\" >" +
@ -1516,15 +1517,16 @@ public class I2PSnarkServlet extends Default {
complete = true; complete = true;
status = toImg("tick") + ' ' + _("Directory"); status = toImg("tick") + ' ' + _("Directory");
} else { } else {
if (snark == null) { if (snark == null || snark.getStorage() == null) {
// Assume complete, perhaps he removed a completed torrent but kept a bookmark // Assume complete, perhaps he removed a completed torrent but kept a bookmark
complete = true; complete = true;
status = toImg("cancel") + ' ' + _("Torrent not found?"); status = toImg("cancel") + ' ' + _("Torrent not found?");
} else { } else {
Storage storage = snark.getStorage();
try { try {
File f = item.getFile(); File f = item.getFile();
if (f != null) { if (f != null) {
long remaining = snark.storage.remaining(f.getCanonicalPath()); long remaining = storage.remaining(f.getCanonicalPath());
if (remaining < 0) { if (remaining < 0) {
complete = true; complete = true;
status = toImg("cancel") + ' ' + _("File not found in torrent?"); status = toImg("cancel") + ' ' + _("File not found in torrent?");
@ -1532,7 +1534,7 @@ public class I2PSnarkServlet extends Default {
complete = true; complete = true;
status = toImg("tick") + ' ' + _("Complete"); status = toImg("tick") + ' ' + _("Complete");
} else { } else {
int priority = snark.storage.getPriority(f.getCanonicalPath()); int priority = storage.getPriority(f.getCanonicalPath());
if (priority < 0) if (priority < 0)
status = toImg("cancel"); status = toImg("cancel");
else if (priority == 0) else if (priority == 0)
@ -1588,7 +1590,7 @@ public class I2PSnarkServlet extends Default {
buf.append("<td class=\"priority\">"); buf.append("<td class=\"priority\">");
File f = item.getFile(); File f = item.getFile();
if ((!complete) && (!item.isDirectory()) && f != null) { if ((!complete) && (!item.isDirectory()) && f != null) {
int pri = snark.storage.getPriority(f.getCanonicalPath()); int pri = snark.getStorage().getPriority(f.getCanonicalPath());
buf.append("<input type=\"radio\" value=\"5\" name=\"pri.").append(f.getCanonicalPath()).append("\" "); buf.append("<input type=\"radio\" value=\"5\" name=\"pri.").append(f.getCanonicalPath()).append("\" ");
if (pri > 0) if (pri > 0)
buf.append("checked=\"true\""); buf.append("checked=\"true\"");
@ -1690,6 +1692,9 @@ public class I2PSnarkServlet extends Default {
/** @since 0.8.1 */ /** @since 0.8.1 */
private void savePriorities(Snark snark, Map postParams) { private void savePriorities(Snark snark, Map postParams) {
Storage storage = snark.getStorage();
if (storage == null)
return;
Set<Map.Entry> entries = postParams.entrySet(); Set<Map.Entry> entries = postParams.entrySet();
for (Map.Entry entry : entries) { for (Map.Entry entry : entries) {
String key = (String)entry.getKey(); String key = (String)entry.getKey();
@ -1698,14 +1703,13 @@ public class I2PSnarkServlet extends Default {
String file = key.substring(4); String file = key.substring(4);
String val = ((String[])entry.getValue())[0]; // jetty arrays String val = ((String[])entry.getValue())[0]; // jetty arrays
int pri = Integer.parseInt(val); int pri = Integer.parseInt(val);
snark.storage.setPriority(file, pri); storage.setPriority(file, pri);
//System.err.println("Priority now " + pri + " for " + file); //System.err.println("Priority now " + pri + " for " + file);
} catch (Throwable t) { t.printStackTrace(); } } catch (Throwable t) { t.printStackTrace(); }
} }
} }
if (snark.coordinator != null) snark.updatePiecePriorities();
snark.coordinator.updatePiecePriorities(); _manager.saveTorrentStatus(snark.getMetaInfo(), storage.getBitField(), storage.getFilePriorities());
_manager.saveTorrentStatus(snark.storage.getMetaInfo(), snark.storage.getBitField(), snark.storage.getFilePriorities());
} }