From 4899a6d306d644fd880d3a062b5fd720c8eaefe3 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Sun, 19 Dec 2010 22:14:02 +0000 Subject: [PATCH] Refactor fields to private and replace with getters, and lots of prep for lack of metainfo and storage. --- .../src/org/klomp/snark/PeerAcceptor.java | 2 +- .../src/org/klomp/snark/PeerCheckerTask.java | 3 - .../src/org/klomp/snark/PeerCoordinator.java | 58 +++- .../java/src/org/klomp/snark/Snark.java | 263 ++++++++++++++++-- .../src/org/klomp/snark/SnarkManager.java | 73 +++-- .../java/src/org/klomp/snark/StaticSnark.java | 3 +- .../src/org/klomp/snark/TrackerClient.java | 30 +- .../org/klomp/snark/web/I2PSnarkServlet.java | 140 +++++----- 8 files changed, 409 insertions(+), 163 deletions(-) diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerAcceptor.java b/apps/i2psnark/java/src/org/klomp/snark/PeerAcceptor.java index 58ef3ae2db..050884e5c0 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerAcceptor.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerAcceptor.java @@ -120,7 +120,7 @@ public class PeerAcceptor else { if (_log.shouldLog(Log.DEBUG)) - _log.debug("Rejecting new peer for " + cur.snark.torrent); + _log.debug("Rejecting new peer for " + cur.getName()); socket.close(); return; } diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java b/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java index aa9cf2187d..d6e2c60895 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java @@ -51,10 +51,7 @@ class PeerCheckerTask extends TimerTask { List<Peer> peerList = coordinator.peerList(); if (peerList.isEmpty() || coordinator.halted()) { - coordinator.peerCount = 0; - coordinator.interestedAndChoking = 0; coordinator.setRateHistory(0, 0); - coordinator.uploaders = 0; if (coordinator.halted()) cancel(); return; diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java index c9cdf61419..ba9727d8a6 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java @@ -42,18 +42,33 @@ import net.i2p.util.SimpleTimer2; public class PeerCoordinator implements PeerListener { private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerCoordinator.class); + + /** + * External use by PeerMonitorTask only. + */ final MetaInfo metainfo; + + /** + * External use by PeerMonitorTask only. + */ final Storage storage; - final Snark snark; + private final Snark snark; // package local for access by CheckDownLoadersTask final static long CHECK_PERIOD = 40*1000; // 40 seconds final static int MAX_UPLOADERS = 6; - // Approximation of the number of current uploaders. - // Resynced by PeerChecker once in a while. - int uploaders = 0; - int interestedAndChoking = 0; + /** + * Approximation of the number of current uploaders. + * Resynced by PeerChecker once in a while. + * External use by PeerCheckerTask only. + */ + int uploaders; + + /** + * External use by PeerCheckerTask only. + */ + int interestedAndChoking; // final static int MAX_DOWNLOADERS = MAX_CONNECTIONS; // int downloaders = 0; @@ -61,14 +76,18 @@ public class PeerCoordinator implements PeerListener private long uploaded; private long downloaded; final static int RATE_DEPTH = 3; // make following arrays RATE_DEPTH long - private long uploaded_old[] = {-1,-1,-1}; - private long downloaded_old[] = {-1,-1,-1}; + private final long uploaded_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; + /** estimate of the peers, without requiring any synchronization */ - volatile int peerCount; + private volatile int peerCount; /** Timer to handle all periodical tasks. */ private final CheckEvent timer; @@ -86,12 +105,9 @@ public class PeerCoordinator implements PeerListener private boolean halted = false; private final CoordinatorListener listener; - public I2PSnarkUtil _util; + private final I2PSnarkUtil _util; 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, CoordinatorListener listener, Snark torrent) { @@ -153,7 +169,6 @@ public class PeerCoordinator implements PeerListener } public Storage getStorage() { return storage; } - public CoordinatorListener getListener() { return listener; } // for web page detailed stats public List<Peer> peerList() @@ -166,6 +181,11 @@ public class PeerCoordinator implements PeerListener return id; } + public String getName() + { + return snark.getName(); + } + public boolean completed() { return storage.complete(); @@ -1107,6 +1127,14 @@ public class PeerCoordinator implements PeerListener return MAX_UPLOADERS; } + /** + * @return current + * @since 0.8.4 + */ + public int getUploaders() { + return uploaders; + } + public boolean overUpBWLimit() { if (listener != null) diff --git a/apps/i2psnark/java/src/org/klomp/snark/Snark.java b/apps/i2psnark/java/src/org/klomp/snark/Snark.java index 31105a2693..79807d68f2 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Snark.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Snark.java @@ -26,6 +26,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Properties; @@ -112,6 +113,8 @@ public class Snark } +/******** No, not maintaining a command-line client + public static void main(String[] args) { System.out.println(copyright); @@ -235,19 +238,27 @@ public class Snark } } +***********/ + public static final String PROP_MAX_CONNECTIONS = "i2psnark.maxConnections"; - public String torrent; - public MetaInfo meta; - public Storage storage; - public PeerCoordinator coordinator; - public ConnectionAcceptor acceptor; - public TrackerClient trackerclient; - public String rootDataDir = "."; - public CompleteListener completeListener; - public boolean stopped; - byte[] id; - public I2PSnarkUtil _util; - private PeerCoordinatorSet _peerCoordinatorSet; + + /** most of these used to be public, use accessors below instead */ + private final String torrent; + private MetaInfo meta; + private Storage storage; + private PeerCoordinator coordinator; + private ConnectionAcceptor acceptor; + private TrackerClient trackerclient; + private String rootDataDir = "."; + private final CompleteListener completeListener; + private boolean stopped; + 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 */ Snark(I2PSnarkUtil util, String torrent, String ip, int user_port, @@ -486,7 +497,7 @@ public class Snark // single torrent acceptor = new ConnectionAcceptor(_util, serversocket, new PeerAcceptor(coordinator)); } - trackerclient = new TrackerClient(_util, meta, coordinator); + trackerclient = new TrackerClient(_util, meta, coordinator, this); } stopped = false; @@ -496,8 +507,7 @@ public class Snark // restart safely, so lets build a new one to replace the old if (_peerCoordinatorSet != null) _peerCoordinatorSet.remove(coordinator); - PeerCoordinator newCoord = new PeerCoordinator(_util, coordinator.getID(), coordinator.getMetaInfo(), - coordinator.getStorage(), coordinator.getListener(), this); + PeerCoordinator newCoord = new PeerCoordinator(_util, id, meta, storage, this, this); if (_peerCoordinatorSet != null) _peerCoordinatorSet.add(newCoord); coordinator = newCoord; @@ -517,7 +527,7 @@ public class Snark } 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()) trackerclient.halt(); trackerclient = newClient; @@ -553,18 +563,223 @@ public class Snark _util.disconnect(); } - static Snark parseArguments(String[] args) + private static Snark parseArguments(String[] args) { 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 * instance. Calls usage(), which terminates the program, if * non-valid argument list. The given listeners will be * passed to all components that take one. */ - static Snark parseArguments(String[] args, + private static Snark parseArguments(String[] args, StorageListener slistener, CoordinatorListener clistener) { @@ -719,7 +934,7 @@ public class Snark /** * Aborts program abnormally. */ - public void fatal(String s) + private void fatal(String s) { fatal(s, null); } @@ -727,7 +942,7 @@ public class Snark /** * Aborts program abnormally. */ - public void fatal(String s, Throwable t) + private void fatal(String s, Throwable t) { _util.debug(s, ERROR, t); //System.err.println("snark: " + s + ((t == null) ? "" : (": " + t))); @@ -751,7 +966,7 @@ public class Snark // System.out.println(peer.toString()); } - boolean allocating = false; + private boolean allocating = false; public void storageCreateFile(Storage storage, String name, long length) { //if (allocating) @@ -774,9 +989,9 @@ public class Snark // System.out.println(); // We have all the disk space we need. } - boolean allChecked = false; - boolean checking = false; - boolean prechecking = true; + private boolean allChecked = false; + private boolean checking = false; + private boolean prechecking = true; public void storageChecked(Storage storage, int num, boolean checked) { allocating = false; diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java index 82d1d80f4f..6a4eb4c7c5 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java +++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java @@ -359,7 +359,7 @@ public class SnarkManager implements Snark.CompleteListener { Set names = listTorrentFiles(); for (Iterator iter = names.iterator(); iter.hasNext(); ) { Snark snark = getTorrent((String)iter.next()); - if ( (snark != null) && (!snark.stopped) ) { + if ( (snark != null) && (!snark.isStopped()) ) { snarksActive = true; break; } @@ -398,9 +398,8 @@ public class SnarkManager implements Snark.CompleteListener { for (Iterator iter = names.iterator(); iter.hasNext(); ) { String name = (String)iter.next(); Snark snark = getTorrent(name); - if ( (snark != null) && (snark.acceptor != null) ) { - snark.acceptor.restart(); - addMessage(_("I2CP listener restarted for \"{0}\"", snark.meta.getName())); + if (snark != null && snark.restartAcceptor()) { + addMessage(_("I2CP listener restarted for \"{0}\"", snark.getBaseName())); } } } @@ -478,7 +477,7 @@ public class SnarkManager implements Snark.CompleteListener { public Snark getTorrentByBaseName(String filename) { synchronized (_snarks) { for (Snark s : _snarks.values()) { - if (s.storage.getBaseName().equals(filename)) + if (s.getBaseName().equals(filename)) return s; } } @@ -554,7 +553,6 @@ public class SnarkManager implements Snark.CompleteListener { _peerCoordinatorSet, _connectionAcceptor, false, dataDir.getPath()); loadSavedFilePriorities(torrent); - torrent.completeListener = this; synchronized (_snarks) { _snarks.put(filename, torrent); } @@ -572,12 +570,11 @@ public class SnarkManager implements Snark.CompleteListener { return; } // ok, snark created, now lets start it up or configure it further - File f = new File(filename); if (!dontAutoStart && shouldAutoStart()) { torrent.startTorrent(); - addMessage(_("Torrent added and started: \"{0}\"", torrent.storage.getBaseName())); + addMessage(_("Torrent added and started: \"{0}\"", torrent.getBaseName())); } 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 */ public long getSavedTorrentTime(Snark snark) { - MetaInfo metainfo = snark.meta; - byte[] ih = metainfo.getInfoHash(); + byte[] ih = snark.getInfoHash(); String infohash = Base64.encode(ih); infohash = infohash.replace('=', '$'); 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. */ public BitField getSavedTorrentBitField(Snark snark) { - MetaInfo metainfo = snark.meta; - byte[] ih = metainfo.getInfoHash(); + MetaInfo metainfo = snark.getMetaInfo(); + if (metainfo == null) + return null; + byte[] ih = snark.getInfoHash(); String infohash = Base64.encode(ih); infohash = infohash.replace('=', '$'); 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 */ 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) return; - byte[] ih = metainfo.getInfoHash(); + byte[] ih = snark.getInfoHash(); String infohash = Base64.encode(ih); infohash = infohash.replace('=', '$'); 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) {} } } - snark.storage.setFilePriorities(rv); + storage.setFilePriorities(rv); } /** @@ -777,21 +778,15 @@ public class SnarkManager implements Snark.CompleteListener { remaining = _snarks.size(); } if (torrent != null) { - boolean wasStopped = torrent.stopped; + boolean wasStopped = torrent.isStopped(); torrent.stopTorrent(); if (remaining == 0) { // should we disconnect/reconnect here (taking care to deal with the other thread's // I2PServerSocket.accept() call properly?) ////_util. } - String name; - if (torrent.storage != null) { - name = torrent.storage.getBaseName(); - } else { - name = sfile.getName(); - } if (!wasStopped) - addMessage(_("Torrent stopped: \"{0}\"", name)); + addMessage(_("Torrent stopped: \"{0}\"", torrent.getBaseName())); } return torrent; } @@ -804,14 +799,10 @@ public class SnarkManager implements Snark.CompleteListener { if (torrent != null) { File torrentFile = new File(filename); torrentFile.delete(); - String name; - if (torrent.storage != null) { - removeTorrentStatus(torrent.storage.getMetaInfo()); - name = torrent.storage.getBaseName(); - } else { - name = torrentFile.getName(); - } - addMessage(_("Torrent removed: \"{0}\"", name)); + Storage storage = torrent.getStorage(); + if (storage != null) + removeTorrentStatus(storage.getMetaInfo()); + addMessage(_("Torrent removed: \"{0}\"", torrent.getBaseName())); } } @@ -843,18 +834,24 @@ public class SnarkManager implements Snark.CompleteListener { /** two listeners */ public void torrentComplete(Snark snark) { + MetaInfo meta = snark.getMetaInfo(); + Storage storage = snark.getStorage(); + if (meta == null || storage == null) + return; StringBuilder buf = new StringBuilder(256); - buf.append("<a href=\"/i2psnark/").append(snark.storage.getBaseName()); - if (snark.meta.getFiles() != null) + buf.append("<a href=\"/i2psnark/").append(storage.getBaseName()); + if (meta.getFiles() != null) buf.append('/'); - buf.append("\">").append(snark.storage.getBaseName()).append("</a>"); - long len = snark.meta.getTotalLength(); + buf.append("\">").append(storage.getBaseName()).append("</a>"); addMessage(_("Download finished: {0}", buf.toString())); // + " (" + _("size: {0}B", DataHelper.formatSize2(len)) + ')'); updateStatus(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) { @@ -984,7 +981,7 @@ public class SnarkManager implements Snark.CompleteListener { Set names = listTorrentFiles(); for (Iterator iter = names.iterator(); iter.hasNext(); ) { Snark snark = getTorrent((String)iter.next()); - if ( (snark != null) && (!snark.stopped) ) + if ( (snark != null) && (!snark.isStopped()) ) snark.stopTorrent(); } } diff --git a/apps/i2psnark/java/src/org/klomp/snark/StaticSnark.java b/apps/i2psnark/java/src/org/klomp/snark/StaticSnark.java index 38b470a7c9..52bef12b47 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/StaticSnark.java +++ b/apps/i2psnark/java/src/org/klomp/snark/StaticSnark.java @@ -38,6 +38,7 @@ public class StaticSnark //Security.addProvider(gnu); // And finally call the normal starting point. - Snark.main(args); + //Snark.main(args); + System.err.println("unsupported"); } } diff --git a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java index a1a3f4cc21..6bded21008 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java +++ b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java @@ -34,9 +34,11 @@ import java.util.Random; import java.util.Set; import net.i2p.I2PAppContext; +import net.i2p.data.Hash; import net.i2p.util.I2PAppThread; import net.i2p.util.Log; + /** * Informs metainfo tracker of events and gets new peers for peer * coordinator. @@ -63,6 +65,7 @@ public class TrackerClient extends I2PAppThread private I2PSnarkUtil _util; private final MetaInfo meta; private final PeerCoordinator coordinator; + private final Snark snark; private final int port; private boolean stop; @@ -70,15 +73,16 @@ public class TrackerClient extends I2PAppThread private List trackers; - public TrackerClient(I2PSnarkUtil util, MetaInfo meta, PeerCoordinator coordinator) + public TrackerClient(I2PSnarkUtil util, MetaInfo meta, PeerCoordinator coordinator, Snark snark) { super(); // Set unique name. - String id = urlencode(coordinator.getID()); + String id = urlencode(snark.getID()); setName("TrackerClient " + id.substring(id.length() - 12)); _util = util; this.meta = meta; this.coordinator = coordinator; + this.snark = snark; this.port = 6881; //(port == -1) ? 9 : port; @@ -119,10 +123,10 @@ public class TrackerClient extends I2PAppThread public void run() { String infoHash = urlencode(meta.getInfoHash()); - String peerID = urlencode(coordinator.getID()); + String peerID = urlencode(snark.getID()); _log.debug("Announce: [" + meta.getAnnounce() + "] infoHash: " + infoHash); - + // Construct the list of trackers for this torrent, // starting with the primary one listed in the metainfo, // followed by the secondary open trackers @@ -200,7 +204,7 @@ public class TrackerClient extends I2PAppThread firstTime = false; } else if (completed && runStarted) 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; else // 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, event); - coordinator.trackerProblems = null; + snark.setTrackerProblems(null); tr.trackerProblems = null; tr.registerFails = 0; tr.consecutiveFails = 0; @@ -262,8 +266,8 @@ public class TrackerClient extends I2PAppThread Set peers = info.getPeers(); tr.seenPeers = info.getPeerCount(); - if (coordinator.trackerSeenPeers < tr.seenPeers) // update rising number quickly - coordinator.trackerSeenPeers = tr.seenPeers; + if (snark.getTrackerSeenPeers() < tr.seenPeers) // update rising number quickly + snark.setTrackerSeenPeers(tr.seenPeers); if ( (left > 0) && (!completed) ) { // we only want to talk to new people if we need things // from them (duh) @@ -293,12 +297,12 @@ public class TrackerClient extends I2PAppThread tr.trackerProblems = ioe.getMessage(); // don't show secondary tracker problems to the user if (tr.isPrimary) - coordinator.trackerProblems = tr.trackerProblems; + snark.setTrackerProblems(tr.trackerProblems); if (tr.trackerProblems.toLowerCase().startsWith(NOT_REGISTERED)) { // Give a guy some time to register it if using opentrackers too if (trackers.size() == 1) { stop = true; - coordinator.snark.stopTorrent(); + snark.stopTorrent(); } else { // hopefully each on the opentrackers list is really open if (tr.registerFails++ > MAX_REGISTER_FAILS) tr.stop = true; @@ -316,7 +320,7 @@ public class TrackerClient extends I2PAppThread } // *** end of trackers loop here // we could try and total the unique peers but that's too hard for now - coordinator.trackerSeenPeers = maxSeenPeers; + snark.setTrackerSeenPeers(maxSeenPeers); if (!runStarted) _util.debug(" Retrying in one minute...", Snark.DEBUG); } // *** end of while loop @@ -377,8 +381,8 @@ public class TrackerClient extends I2PAppThread try { in = new FileInputStream(fetched); - TrackerInfo info = new TrackerInfo(in, coordinator.getID(), - coordinator.getMetaInfo()); + TrackerInfo info = new TrackerInfo(in, snark.getID(), + snark.getMetaInfo()); _util.debug("TrackerClient response: " + info, Snark.INFO); String failure = info.getFailureReason(); diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java index d74426ee12..57e8bd4461 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -26,6 +26,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.i2p.I2PAppContext; +import net.i2p.data.Base32; import net.i2p.data.Base64; import net.i2p.data.DataHelper; import net.i2p.util.FileUtil; @@ -361,7 +362,7 @@ public class I2PSnarkServlet extends Default { for (int i = 0; i < snarks.size(); i++) { Snark snark = (Snark)snarks.get(i); 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); } @@ -452,7 +453,7 @@ public class I2PSnarkServlet extends Default { if (newURL != null) { if (newURL.startsWith("http://")) { _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(); } else { _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(); ) { String name = (String)iter.next(); 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); break; } @@ -482,11 +483,9 @@ public class I2PSnarkServlet extends Default { if ( (infoHash != null) && (infoHash.length == 20) ) { // valid sha1 for (String name : _manager.listTorrentFiles()) { Snark snark = _manager.getTorrent(name); - if ( (snark != null) && (DataHelper.eq(infoHash, snark.meta.getInfoHash())) ) { + if ( (snark != null) && (DataHelper.eq(infoHash, snark.getInfoHash())) ) { snark.startTorrent(); - if (snark.storage != null) - name = snark.storage.getBaseName(); - _manager.addMessage(_("Starting up torrent {0}", name)); + _manager.addMessage(_("Starting up torrent {0}", snark.getBaseName())); break; } } @@ -500,8 +499,12 @@ public class I2PSnarkServlet extends Default { for (Iterator iter = _manager.listTorrentFiles().iterator(); iter.hasNext(); ) { String name = (String)iter.next(); 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); + MetaInfo meta = snark.getMetaInfo(); + if (meta == null) { + return; + } // should we delete the torrent file? // yeah, need to, otherwise it'll get autoadded again (at the moment File f = new File(name); @@ -520,13 +523,17 @@ public class I2PSnarkServlet extends Default { for (Iterator iter = _manager.listTorrentFiles().iterator(); iter.hasNext(); ) { String name = (String)iter.next(); 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); + MetaInfo meta = snark.getMetaInfo(); + if (meta == null) { + return; + } File f = new File(name); f.delete(); _manager.addMessage(_("Torrent file deleted: {0}", f.getAbsolutePath())); - List files = snark.meta.getFiles(); - String dataFile = snark.meta.getName(); + List files = meta.getFiles(); + String dataFile = snark.getBaseName(); f = new File(_manager.getDataDir(), dataFile); if (files == null) { // single file torrent if (f.delete()) @@ -617,8 +624,8 @@ public class I2PSnarkServlet extends Default { List snarks = getSortedSnarks(req); for (int i = 0; i < snarks.size(); i++) { Snark snark = (Snark)snarks.get(i); - if (!snark.stopped) - _manager.stopTorrent(snark.torrent, false); + if (!snark.isStopped()) + _manager.stopTorrent(snark.getName(), false); } if (_manager.util().connected()) { // Give the stopped announces time to get out @@ -631,7 +638,7 @@ public class I2PSnarkServlet extends Default { List snarks = getSortedSnarks(req); for (int i = 0; i < snarks.size(); i++) { Snark snark = (Snark)snarks.get(i); - if (snark.stopped) + if (snark.isStopped()) snark.startTorrent(); } } else { @@ -699,7 +706,7 @@ public class I2PSnarkServlet extends Default { private static final int MAX_DISPLAYED_ERROR_LENGTH = 43; private void displaySnark(PrintWriter out, Snark snark, String uri, int row, long stats[], boolean showPeers, boolean isDegraded, boolean showDebug) throws IOException { - String filename = snark.torrent; + String filename = snark.getName(); File f = new File(filename); filename = f.getName(); // the torrent may be the canonical name, so lets just grab the local name int i = filename.lastIndexOf(".torrent"); @@ -710,28 +717,21 @@ public class I2PSnarkServlet extends Default { fullFilename = new String(filename); filename = filename.substring(0, MAX_DISPLAYED_FILENAME_LENGTH) + "…"; } - long total = snark.meta.getTotalLength(); + long total = snark.getTotalLength(); // 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) remaining = total; - long downBps = 0; - long upBps = 0; - if (snark.coordinator != null) { - downBps = snark.coordinator.getDownloadRate(); - upBps = snark.coordinator.getUploadRate(); - } + long downBps = snark.getDownloadRate(); + long upBps = snark.getUploadRate(); long remainingSeconds; if (downBps > 0) remainingSeconds = remaining / downBps; else remainingSeconds = -1; - boolean isRunning = !snark.stopped; - long uploaded = 0; - if (snark.coordinator != null) { - uploaded = snark.coordinator.getUploaded(); - stats[0] += snark.coordinator.getDownloaded(); - } + boolean isRunning = !snark.isStopped(); + long uploaded = snark.getUploaded(); + stats[0] += snark.getDownloaded(); stats[1] += uploaded; if (isRunning) { stats[2] += downBps; @@ -739,25 +739,21 @@ public class I2PSnarkServlet extends Default { } stats[5] += total; - boolean isValid = snark.meta != null; - boolean singleFile = snark.meta.getFiles() == null; + MetaInfo meta = snark.getMetaInfo(); + boolean isValid = meta != null; + boolean singleFile = (!isValid) || meta.getFiles() == null; - String err = null; - int curPeers = 0; - int knownPeers = 0; - if (snark.coordinator != null) { - err = snark.coordinator.trackerProblems; - curPeers = snark.coordinator.getPeerCount(); - stats[4] += curPeers; - knownPeers = Math.max(curPeers, snark.coordinator.trackerSeenPeers); - } + String err = snark.getTrackerProblems(); + int curPeers = snark.getPeerCount(); + stats[4] += curPeers; + int knownPeers = Math.max(curPeers, snark.getTrackerSeenPeers()); String rowClass = (row % 2 == 0 ? "snarkTorrentEven" : "snarkTorrentOdd"); String statusString; if (err != null) { if (isRunning && curPeers > 0 && !showPeers) 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) + ngettext("1 peer", "{0} peers", knownPeers) + "</a>"; else if (isRunning) @@ -773,7 +769,7 @@ public class I2PSnarkServlet extends Default { } else if (remaining <= 0) { if (isRunning && curPeers > 0 && !showPeers) 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) + ngettext("1 peer", "{0} peers", knownPeers) + "</a>"; else if (isRunning) @@ -785,7 +781,7 @@ public class I2PSnarkServlet extends Default { } else { if (isRunning && curPeers > 0 && downBps > 0 && !showPeers) 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) + ngettext("1 peer", "{0} peers", knownPeers) + "</a>"; else if (isRunning && curPeers > 0 && downBps > 0) @@ -794,7 +790,7 @@ public class I2PSnarkServlet extends Default { ngettext("1 peer", "{0} peers", knownPeers); else if (isRunning && curPeers > 0 && !showPeers) 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) + ngettext("1 peer", "{0} peers", knownPeers) + "</a>"; else if (isRunning && curPeers > 0) @@ -816,7 +812,7 @@ public class I2PSnarkServlet extends Default { out.write("<td class=\"" + rowClass + "\">"); // 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") || announce.startsWith("http://lnQ6yoBT") || announce.startsWith("http://tracker2.postman.i2p/") || announce.startsWith("http://ahsplxkbhemefwvvml7qovzl5a2b5xo5i7lyai7ntdunvcyfdtna.b32.i2p/")) { Map trackers = _manager.getTrackers(); @@ -833,7 +829,7 @@ public class I2PSnarkServlet extends Default { continue; baseURL = baseURL.substring(e + 1); out.write("<a href=\"" + baseURL + "details.php?dllist=1&filelist=1&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("<img alt=\"" + _("Info") + "\" border=\"0\" src=\"" + _imgPath + "details.png\">"); out.write("</a>"); @@ -843,13 +839,13 @@ public class I2PSnarkServlet extends Default { out.write("</td>\n<td class=\"" + rowClass + "\">"); StringBuilder buf = null; - if (remaining == 0 || snark.meta.getFiles() != null) { + if (remaining == 0 || meta.getFiles() != null) { buf = new StringBuilder(128); - buf.append("<a href=\"").append(snark.storage.getBaseName()); - if (snark.meta.getFiles() != null) + buf.append("<a href=\"").append(snark.getBaseName()); + if (meta.getFiles() != null) buf.append('/'); buf.append("\" title=\""); - if (snark.meta.getFiles() != null) + if (meta.getFiles() != null) buf.append(_("View files")); else buf.append(_("Open file")); @@ -857,21 +853,21 @@ public class I2PSnarkServlet extends Default { out.write(buf.toString()); } String icon; - if (snark.meta.getFiles() != null) + if (meta.getFiles() != null) icon = "folder"; else - icon = toIcon(snark.meta.getName()); - if (remaining == 0 || snark.meta.getFiles() != null) { + icon = toIcon(meta.getName()); + if (remaining == 0 || meta.getFiles() != null) { out.write(toImg(icon, _("Open"))); out.write("</a>"); } else { out.write(toImg(icon)); } 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(filename); - if (remaining == 0 || snark.meta.getFiles() != null) + if (remaining == 0 || meta.getFiles() != null) out.write("</a>"); out.write("<td align=\"right\" class=\"snarkTorrentETA " + rowClass + "\">"); @@ -897,8 +893,8 @@ public class I2PSnarkServlet extends Default { out.write(formatSize(upBps) + "ps"); out.write("</td>\n\t"); out.write("<td align=\"center\" class=\"snarkTorrentAction " + rowClass + "\">"); - String parameters = "&nonce=" + _nonce + "&torrent=" + Base64.encode(snark.meta.getInfoHash()); - String b64 = Base64.encode(snark.meta.getInfoHash()); + String parameters = "&nonce=" + _nonce + "&torrent=" + Base64.encode(snark.getInfoHash()); + String b64 = Base64.encode(snark.getInfoHash()); if (showPeers) parameters = parameters + "&p=1"; if (isRunning) { @@ -963,7 +959,7 @@ public class I2PSnarkServlet extends Default { out.write("</td>\n</tr>\n"); if(showPeers && isRunning && curPeers > 0) { - List<Peer> peers = snark.coordinator.peerList(); + List<Peer> peers = snark.getPeerList(); if (!showDebug) Collections.sort(peers, new PeerComparator()); for (Peer peer : peers) { @@ -996,7 +992,7 @@ public class I2PSnarkServlet extends Default { out.write("<td class=\"snarkTorrentStatus " + rowClass + "\">"); out.write("</td>\n\t"); 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) out.write(_("Seed")); else { @@ -1358,6 +1354,11 @@ public class I2PSnarkServlet extends Default { 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 */ private String ngettext(String s, String p, int n) { return _manager.util().getString(n, s, p); @@ -1469,7 +1470,7 @@ public class I2PSnarkServlet extends Default { if (parent) // always true 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) buf.append("<form action=\"").append(base).append("\" method=\"POST\">\n"); buf.append("<TABLE BORDER=0 class=\"snarkTorrents\" >" + @@ -1516,15 +1517,16 @@ public class I2PSnarkServlet extends Default { complete = true; status = toImg("tick") + ' ' + _("Directory"); } else { - if (snark == null) { + if (snark == null || snark.getStorage() == null) { // Assume complete, perhaps he removed a completed torrent but kept a bookmark complete = true; status = toImg("cancel") + ' ' + _("Torrent not found?"); } else { + Storage storage = snark.getStorage(); try { File f = item.getFile(); if (f != null) { - long remaining = snark.storage.remaining(f.getCanonicalPath()); + long remaining = storage.remaining(f.getCanonicalPath()); if (remaining < 0) { complete = true; status = toImg("cancel") + ' ' + _("File not found in torrent?"); @@ -1532,7 +1534,7 @@ public class I2PSnarkServlet extends Default { complete = true; status = toImg("tick") + ' ' + _("Complete"); } else { - int priority = snark.storage.getPriority(f.getCanonicalPath()); + int priority = storage.getPriority(f.getCanonicalPath()); if (priority < 0) status = toImg("cancel"); else if (priority == 0) @@ -1588,7 +1590,7 @@ public class I2PSnarkServlet extends Default { buf.append("<td class=\"priority\">"); File f = item.getFile(); 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("\" "); if (pri > 0) buf.append("checked=\"true\""); @@ -1690,6 +1692,9 @@ public class I2PSnarkServlet extends Default { /** @since 0.8.1 */ private void savePriorities(Snark snark, Map postParams) { + Storage storage = snark.getStorage(); + if (storage == null) + return; Set<Map.Entry> entries = postParams.entrySet(); for (Map.Entry entry : entries) { String key = (String)entry.getKey(); @@ -1698,14 +1703,13 @@ public class I2PSnarkServlet extends Default { String file = key.substring(4); String val = ((String[])entry.getValue())[0]; // jetty arrays int pri = Integer.parseInt(val); - snark.storage.setPriority(file, pri); + storage.setPriority(file, pri); //System.err.println("Priority now " + pri + " for " + file); } catch (Throwable t) { t.printStackTrace(); } } } - if (snark.coordinator != null) - snark.coordinator.updatePiecePriorities(); - _manager.saveTorrentStatus(snark.storage.getMetaInfo(), snark.storage.getBitField(), snark.storage.getFilePriorities()); + snark.updatePiecePriorities(); + _manager.saveTorrentStatus(snark.getMetaInfo(), storage.getBitField(), storage.getFilePriorities()); } -- GitLab