diff --git a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java index bfd74206cbf6c926b7cef56deffab9e049909ab4..9497258cb243e4b290ecd7cb97ce2dfc8076fa4d 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java +++ b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java @@ -2,12 +2,15 @@ package org.klomp.snark; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; +import java.util.StringTokenizer; import net.i2p.I2PAppContext; import net.i2p.I2PException; @@ -44,6 +47,12 @@ public class I2PSnarkUtil { private int _maxUploaders; private int _maxUpBW; + public static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers"; + public static final boolean DEFAULT_USE_OPENTRACKERS = true; + public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers"; + public static final String DEFAULT_OPENTRACKERS = "http://tracker.welterde.i2p/a"; + public static final int DEFAULT_MAX_UP_BW = 8; //KBps + private I2PSnarkUtil() { _context = I2PAppContext.getGlobalContext(); _log = _context.logManager().getLog(Snark.class); @@ -53,6 +62,7 @@ public class I2PSnarkUtil { _shitlist = new HashSet(64); _configured = false; _maxUploaders = Snark.MAX_TOTAL_UPLOADERS; + _maxUpBW = DEFAULT_MAX_UP_BW; } /** @@ -267,6 +277,36 @@ public class I2PSnarkUtil { return rv; } + public String getOpenTrackerString() { + String rv = (String) _opts.get(PROP_OPENTRACKERS); + if (rv == null) + return DEFAULT_OPENTRACKERS; + return rv; + } + + /** comma delimited list open trackers to use as backups */ + /** sorted map of name to announceURL=baseURL */ + public List getOpenTrackers() { + if (!shouldUseOpenTrackers()) + return null; + List rv = new ArrayList(1); + String trackers = getOpenTrackerString(); + StringTokenizer tok = new StringTokenizer(trackers, ", "); + while (tok.hasMoreTokens()) + rv.add(tok.nextToken()); + + if (rv.size() <= 0) + return null; + return rv; + } + + public boolean shouldUseOpenTrackers() { + String rv = (String) _opts.get(PROP_USE_OPENTRACKERS); + if (rv == null) + return DEFAULT_USE_OPENTRACKERS; + return Boolean.valueOf(rv).booleanValue(); + } + /** hook between snark's logger and an i2p log */ void debug(String msg, int snarkDebugLevel, Throwable t) { if (t instanceof OutOfMemoryError) { diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java b/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java index f8e36fe42e69c5d14f7a5a3a118a54161f68bedb..7ff569aca5227fb4afa5eb9201f55ed0de6a39f2 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java @@ -32,7 +32,7 @@ import java.util.TimerTask; */ class PeerCheckerTask extends TimerTask { - private final long KILOPERSECOND = 1024*(PeerCoordinator.CHECK_PERIOD/1000); + private static final long KILOPERSECOND = 1024*(PeerCoordinator.CHECK_PERIOD/1000); private final PeerCoordinator coordinator; @@ -247,6 +247,10 @@ class PeerCheckerTask extends TimerTask // store the rates coordinator.setRateHistory(uploaded, downloaded); + // close out unused files, but we don't need to do it every time + if (random.nextInt(4) == 0) + coordinator.getStorage().cleanRAFs(); + } } } diff --git a/apps/i2psnark/java/src/org/klomp/snark/Snark.java b/apps/i2psnark/java/src/org/klomp/snark/Snark.java index de9dd1ad7edb7d97d1c34b5e4b61818e5c7b5e10..c1eedba324b37ef6f1e08867f31e255b93137136 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Snark.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Snark.java @@ -247,10 +247,11 @@ public class Snark Snark(String torrent, String ip, int user_port, StorageListener slistener, CoordinatorListener clistener) { - this(torrent, ip, user_port, slistener, clistener, true, "."); + this(torrent, ip, user_port, slistener, clistener, null, true, "."); } - Snark(String torrent, String ip, int user_port, - StorageListener slistener, CoordinatorListener clistener, boolean start, String rootDir) + public Snark(String torrent, String ip, int user_port, + StorageListener slistener, CoordinatorListener clistener, + CompleteListener complistener, boolean start, String rootDir) { if (slistener == null) slistener = this; @@ -258,6 +259,8 @@ public class Snark //if (clistener == null) // clistener = this; + completeListener = complistener; + this.torrent = torrent; this.rootDataDir = rootDir; @@ -379,7 +382,13 @@ public class Snark { activity = "Checking storage"; storage = new Storage(meta, slistener); - storage.check(rootDataDir); + if (completeListener != null) { + storage.check(rootDataDir, + completeListener.getSavedTorrentTime(this), + completeListener.getSavedTorrentBitField(this)); + } else { + storage.check(rootDataDir); + } // have to figure out when to reopen // if (!start) // storage.close(); @@ -480,14 +489,15 @@ public class Snark pc.halt(); Storage st = storage; if (st != null) { - if (storage.changed) - SnarkManager.instance().saveTorrentStatus(storage.getMetaInfo(), storage.getBitField()); + boolean changed = storage.changed; try { storage.close(); } catch (IOException ioe) { System.out.println("Error closing " + torrent); ioe.printStackTrace(); } + if (changed && completeListener != null) + completeListener.updateStatus(this); } if (pc != null) PeerCoordinatorSet.instance().remove(pc); @@ -743,6 +753,8 @@ public class Snark allChecked = true; checking = false; + if (storage.changed && completeListener != null) + completeListener.updateStatus(this); } public void storageCompleted(Storage storage) @@ -768,6 +780,10 @@ public class Snark public interface CompleteListener { public void torrentComplete(Snark snark); + public void updateStatus(Snark snark); + // not really listeners but the easiest way to get back to an optional SnarkManager + public long getSavedTorrentTime(Snark snark); + public BitField getSavedTorrentBitField(Snark snark); } /** Maintain a configurable total uploader cap diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java index 5e3fc60fd6e88568e5c254019a469393f16d4c59..b3d3393972c8af9b61c98eff987122f098d60dfe 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java +++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java @@ -51,10 +51,6 @@ public class SnarkManager implements Snark.CompleteListener { public static final String PROP_AUTO_START = "i2snark.autoStart"; // oops public static final String DEFAULT_AUTO_START = "false"; - public static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers"; - public static final String DEFAULT_USE_OPENTRACKERS = "true"; - public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers"; - public static final String DEFAULT_OPENTRACKERS = "http://tracker.welterde.i2p/a"; public static final String PROP_LINK_PREFIX = "i2psnark.linkPrefix"; public static final String DEFAULT_LINK_PREFIX = "file:///"; @@ -98,9 +94,6 @@ public class SnarkManager implements Snark.CompleteListener { public boolean shouldAutoStart() { return Boolean.valueOf(_config.getProperty(PROP_AUTO_START, DEFAULT_AUTO_START+"")).booleanValue(); } - public boolean shouldUseOpenTrackers() { - return Boolean.valueOf(_config.getProperty(PROP_USE_OPENTRACKERS, DEFAULT_USE_OPENTRACKERS)).booleanValue(); - } public String linkPrefix() { return _config.getProperty(PROP_LINK_PREFIX, DEFAULT_LINK_PREFIX + getDataDir().getAbsolutePath() + File.separatorChar); } @@ -322,14 +315,14 @@ public class SnarkManager implements Snark.CompleteListener { addMessage("Adjusted autostart to " + autoStart); changed = true; } - if (shouldUseOpenTrackers() != useOpenTrackers) { - _config.setProperty(PROP_USE_OPENTRACKERS, useOpenTrackers + ""); + if (I2PSnarkUtil.instance().shouldUseOpenTrackers() != useOpenTrackers) { + _config.setProperty(I2PSnarkUtil.PROP_USE_OPENTRACKERS, useOpenTrackers + ""); addMessage((useOpenTrackers ? "En" : "Dis") + "abled open trackers - torrent restart required to take effect"); changed = true; } if (openTrackers != null) { - if (openTrackers.trim().length() > 0 && !openTrackers.trim().equals(getOpenTrackerString())) { - _config.setProperty(PROP_OPENTRACKERS, openTrackers.trim()); + if (openTrackers.trim().length() > 0 && !openTrackers.trim().equals(I2PSnarkUtil.instance().getOpenTrackerString())) { + _config.setProperty(I2PSnarkUtil.PROP_OPENTRACKERS, openTrackers.trim()); addMessage("Open Tracker list changed - torrent restart required to take effect"); changed = true; } @@ -407,7 +400,7 @@ public class SnarkManager implements Snark.CompleteListener { addMessage(rejectMessage); return; } else { - torrent = new Snark(filename, null, -1, null, null, false, dataDir.getPath()); + torrent = new Snark(filename, null, -1, null, null, this, false, dataDir.getPath()); torrent.completeListener = this; synchronized (_snarks) { _snarks.put(filename, torrent); @@ -438,7 +431,8 @@ public class SnarkManager implements Snark.CompleteListener { /** * Get the timestamp for a torrent from the config file */ - public long getSavedTorrentTime(MetaInfo metainfo) { + public long getSavedTorrentTime(Snark snark) { + MetaInfo metainfo = snark.meta; byte[] ih = metainfo.getInfoHash(); String infohash = Base64.encode(ih); infohash = infohash.replace('=', '$'); @@ -457,7 +451,8 @@ public class SnarkManager implements Snark.CompleteListener { * Get the saved bitfield for a torrent from the config file. * Convert "." to a full bitfield. */ - public BitField getSavedTorrentBitField(MetaInfo metainfo) { + public BitField getSavedTorrentBitField(Snark snark) { + MetaInfo metainfo = snark.meta; byte[] ih = metainfo.getInfoHash(); String infohash = Base64.encode(ih); infohash = infohash.replace('=', '$'); @@ -618,11 +613,17 @@ public class SnarkManager implements Snark.CompleteListener { } } + /** two listeners */ public void torrentComplete(Snark snark) { File f = new File(snark.torrent); long len = snark.meta.getTotalLength(); addMessage("Download complete of " + f.getName() + (len < 5*1024*1024 ? " (size: " + (len/1024) + "KB)" : " (size: " + (len/(1024*1024l)) + "MB)")); + updateStatus(snark); + } + + public void updateStatus(Snark snark) { + saveTorrentStatus(snark.meta, snark.storage.getBitField()); } private void monitorTorrents(File dir) { @@ -706,26 +707,6 @@ public class SnarkManager implements Snark.CompleteListener { return trackerMap; } - public String getOpenTrackerString() { - return _config.getProperty(PROP_OPENTRACKERS, DEFAULT_OPENTRACKERS); - } - - /** comma delimited list open trackers to use as backups */ - /** sorted map of name to announceURL=baseURL */ - public List getOpenTrackers() { - if (!shouldUseOpenTrackers()) - return null; - List rv = new ArrayList(1); - String trackers = getOpenTrackerString(); - StringTokenizer tok = new StringTokenizer(trackers, ", "); - while (tok.hasMoreTokens()) - rv.add(tok.nextToken()); - - if (rv.size() <= 0) - return null; - return rv; - } - private static class TorrentFilenameFilter implements FilenameFilter { private static final TorrentFilenameFilter _filter = new TorrentFilenameFilter(); public static TorrentFilenameFilter instance() { return _filter; } diff --git a/apps/i2psnark/java/src/org/klomp/snark/Storage.java b/apps/i2psnark/java/src/org/klomp/snark/Storage.java index fd3d034f0b2a9e02f5be288eb2f933079022a0aa..ba68cb8381d0a43281becdc368a526f911915463 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Storage.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Storage.java @@ -39,11 +39,15 @@ public class Storage private long[] lengths; private RandomAccessFile[] rafs; private String[] names; + private Object[] RAFlock; // lock on RAF access + private long[] RAFtime; // when was RAF last accessed, or 0 if closed + private File[] RAFfile; // File to make it easier to reopen private final StorageListener listener; private BitField bitfield; // BitField to represent the pieces private int needed; // Number of pieces needed + private boolean _probablyComplete; // use this to decide whether to open files RO // XXX - Not always set correctly int piece_size; @@ -68,6 +72,7 @@ public class Storage this.metainfo = metainfo; this.listener = listener; needed = metainfo.getPieces(); + _probablyComplete = false; bitfield = new BitField(needed); } @@ -119,7 +124,6 @@ public class Storage files.add(file); } - String name = baseFile.getName(); if (files.size() == 1) // FIXME: ...and if base file not a directory or should this be the only check? // this makes a bad metainfo if the directory has only one file in it { @@ -133,7 +137,8 @@ public class Storage } - // Creates piece hases for a new storage. + // Creates piece hashes for a new storage. + // This does NOT create the files, just the hashes public void create() throws IOException { // if (true) { @@ -197,14 +202,8 @@ public class Storage piece_hashes[20 * i + j] = hash[j]; bitfield.set(i); - - if (listener != null) - listener.storageChecked(this, i, true); } - if (listener != null) - listener.storageAllChecked(this); - // Reannounce to force recalculating the info_hash. metainfo = metainfo.reannounce(metainfo.getAnnounce()); } @@ -218,6 +217,9 @@ public class Storage names = new String[size]; lengths = new long[size]; rafs = new RandomAccessFile[size]; + RAFlock = new Object[size]; + RAFtime = new long[size]; + RAFfile = new File[size]; int i = 0; Iterator it = files.iterator(); @@ -228,7 +230,8 @@ public class Storage if (base.isDirectory() && names[i].startsWith(base.getPath())) names[i] = names[i].substring(base.getPath().length() + 1); lengths[i] = f.length(); - rafs[i] = new RandomAccessFile(f, "r"); + RAFlock[i] = new Object(); + RAFfile[i] = f; i++; } } @@ -288,11 +291,14 @@ public class Storage * Creates (and/or checks) all files from the metainfo file list. */ public void check(String rootDir) throws IOException + { + check(rootDir, 0, null); + } + + /** use a saved bitfield and timestamp from a config file */ + public void check(String rootDir, long savedTime, BitField savedBitField) throws IOException { File base = new File(rootDir, filterName(metainfo.getName())); - // look for saved bitfield and timestamp in the config file - long savedTime = SnarkManager.instance().getSavedTorrentTime(metainfo); - BitField savedBitField = SnarkManager.instance().getSavedTorrentBitField(metainfo); boolean useSavedBitField = savedTime > 0 && savedBitField != null; List files = metainfo.getFiles(); @@ -306,16 +312,17 @@ public class Storage lengths = new long[1]; rafs = new RandomAccessFile[1]; names = new String[1]; + RAFlock = new Object[1]; + RAFtime = new long[1]; + RAFfile = new File[1]; lengths[0] = metainfo.getTotalLength(); + RAFlock[0] = new Object(); + RAFfile[0] = base; if (useSavedBitField) { long lm = base.lastModified(); if (lm <= 0 || lm > savedTime) useSavedBitField = false; } - if (base.exists() && ((useSavedBitField && savedBitField.complete()) || !base.canWrite())) - rafs[0] = new RandomAccessFile(base, "r"); - else - rafs[0] = new RandomAccessFile(base, "rw"); names[0] = base.getName(); } else @@ -331,20 +338,21 @@ public class Storage lengths = new long[size]; rafs = new RandomAccessFile[size]; names = new String[size]; + RAFlock = new Object[size]; + RAFtime = new long[size]; + RAFfile = new File[size]; for (int i = 0; i < size; i++) { File f = createFileFromNames(base, (List)files.get(i)); lengths[i] = ((Long)ls.get(i)).longValue(); + RAFlock[i] = new Object(); + RAFfile[i] = f; total += lengths[i]; if (useSavedBitField) { long lm = base.lastModified(); if (lm <= 0 || lm > savedTime) useSavedBitField = false; } - if (f.exists() && ((useSavedBitField && savedBitField.complete()) || !f.canWrite())) - rafs[i] = new RandomAccessFile(f, "r"); - else - rafs[i] = new RandomAccessFile(f, "rw"); names[i] = f.getName(); } @@ -357,11 +365,17 @@ public class Storage if (useSavedBitField) { bitfield = savedBitField; needed = metainfo.getPieces() - bitfield.count(); + _probablyComplete = complete(); Snark.debug("Found saved state and files unchanged, skipping check", Snark.NOTICE); } else { + // the following sets the needed variable + changed = true; checkCreateFiles(); - SnarkManager.instance().saveTorrentStatus(metainfo, bitfield); } + if (complete()) + Snark.debug("Torrent is complete", Snark.NOTICE); + else + Snark.debug("Still need " + needed + " out of " + metainfo.getPieces() + " pieces", Snark.NOTICE); } /** @@ -379,11 +393,6 @@ public class Storage Snark.debug("Reopening file: " + base, Snark.NOTICE); if (!base.exists()) throw new IOException("Could not reopen file " + base); - - if (complete() || !base.canWrite()) // hope we can get away with this, if we are only seeding... - rafs[0] = new RandomAccessFile(base, "r"); - else - rafs[0] = new RandomAccessFile(base, "rw"); } else { @@ -398,10 +407,6 @@ public class Storage File f = getFileFromNames(base, (List)files.get(i)); if (!f.exists()) throw new IOException("Could not reopen file " + f); - if (complete() || !f.canWrite()) // see above re: only seeding - rafs[i] = new RandomAccessFile(f, "r"); - else - rafs[i] = new RandomAccessFile(f, "rw"); } } @@ -453,27 +458,43 @@ public class Storage return base; } + /** + * This is called at the beginning, and at presumed completion, + * so we have to be careful about locking. + */ private void checkCreateFiles() throws IOException { // Whether we are resuming or not, // if any of the files already exists we assume we are resuming. boolean resume = false; + _probablyComplete = true; + needed = metainfo.getPieces(); + // Make sure all files are available and of correct length for (int i = 0; i < rafs.length; i++) { - long length = rafs[i].length(); - if(length == lengths[i]) + long length = RAFfile[i].length(); + if(RAFfile[i].exists() && length == lengths[i]) { if (listener != null) listener.storageAllocated(this, length); resume = true; // XXX Could dynamicly check } - else if (length == 0) - allocateFile(i); - else { + else if (length == 0) { + changed = true; + synchronized(RAFlock[i]) { + allocateFile(i); + } + } else { Snark.debug("File '" + names[i] + "' exists, but has wrong length - repairing corruption", Snark.ERROR); - rafs[i].setLength(lengths[i]); + changed = true; + _probablyComplete = false; // to force RW + synchronized(RAFlock[i]) { + checkRAF(i); + rafs[i].setLength(lengths[i]); + } + // will be closed below } } @@ -497,6 +518,17 @@ public class Storage } } + _probablyComplete = complete(); + // close all the files so we don't end up with a zillion open ones; + // we will reopen as needed + for (int i = 0; i < rafs.length; i++) { + synchronized(RAFlock[i]) { + try { + closeRAF(i); + } catch (IOException ioe) {} + } + } + if (listener != null) { listener.storageAllChecked(this); if (needed <= 0) @@ -506,6 +538,8 @@ public class Storage private void allocateFile(int nr) throws IOException { + // caller synchronized + openRAF(nr, false); // RW // XXX - Is this the best way to make sure we have enough space for // the whole file? listener.storageCreateFile(this, names[nr], lengths[nr]); @@ -520,6 +554,7 @@ public class Storage } int size = (int)(lengths[nr] - i*ZEROBLOCKSIZE); rafs[nr].write(zeros, 0, size); + // caller will close rafs[nr] if (listener != null) listener.storageAllocated(this, size); } @@ -535,12 +570,11 @@ public class Storage for (int i = 0; i < rafs.length; i++) { try { - synchronized(rafs[i]) - { - rafs[i].close(); - } + synchronized(RAFlock[i]) { + closeRAF(i); + } } catch (IOException ioe) { - I2PSnarkUtil.instance().debug("Error closing " + rafs[i], Snark.ERROR, ioe); + I2PSnarkUtil.instance().debug("Error closing " + RAFfile[i], Snark.ERROR, ioe); // gobble gobble } } @@ -587,18 +621,10 @@ public class Storage if (!correctHash) return false; - boolean complete; synchronized(bitfield) { if (bitfield.get(piece)) return true; // No need to store twice. - else - { - bitfield.set(piece); - needed--; - complete = needed == 0; - } - } // Early typecast, avoid possibly overflowing a temp integer @@ -618,8 +644,9 @@ public class Storage { int need = length - written; int len = (start + need < raflen) ? need : (int)(raflen - start); - synchronized(rafs[i]) + synchronized(RAFlock[i]) { + checkRAF(i); rafs[i].seek(start); rafs[i].write(bs, off + written, len); } @@ -633,8 +660,21 @@ public class Storage } changed = true; + + // do this after the write, so we know it succeeded, and we don't set the + // needed count to zero, which would cause checkRAF() to open the file readonly. + boolean complete = false; + synchronized(bitfield) + { + if (!bitfield.get(piece)) + { + bitfield.set(piece); + needed--; + complete = needed == 0; + } + } + if (complete) { -// listener.storageCompleted(this); // do we also need to close all of the files and reopen // them readonly? @@ -649,11 +689,13 @@ public class Storage bitfield = new BitField(needed); checkCreateFiles(); if (needed > 0) { - listener.setWantedPieces(this); + if (listener != null) + listener.setWantedPieces(this); Snark.debug("WARNING: Not really done, missing " + needed + " pieces", Snark.WARNING); } else { - SnarkManager.instance().saveTorrentStatus(metainfo, bitfield); + if (listener != null) + listener.storageCompleted(this); } } @@ -688,8 +730,9 @@ public class Storage { int need = length - read; int len = (start + need < raflen) ? need : (int)(raflen - start); - synchronized(rafs[i]) + synchronized(RAFlock[i]) { + checkRAF(i); rafs[i].seek(start); rafs[i].readFully(bs, read, len); } @@ -704,4 +747,59 @@ public class Storage return length; } + + /** + * Close unused RAFs - call periodically + */ + private static final long RAFCloseDelay = 7*60*1000; + public void cleanRAFs() { + long cutoff = System.currentTimeMillis() - RAFCloseDelay; + for (int i = 0; i < RAFlock.length; i++) { + synchronized(RAFlock[i]) { + if (RAFtime[i] > 0 && RAFtime[i] < cutoff) { + try { + closeRAF(i); + } catch (IOException ioe) {} + } + } + } + } + + /* + * For each of the following, + * caller must synchronize on RAFlock[i] + * ... except at the beginning if you're careful + */ + + /** + * This must be called before using the RAF to ensure it is open + */ + private void checkRAF(int i) throws IOException { + if (RAFtime[i] > 0) { + RAFtime[i] = System.currentTimeMillis(); + return; + } + openRAF(i); + } + + private void openRAF(int i) throws IOException { + openRAF(i, _probablyComplete); + } + + private void openRAF(int i, boolean readonly) throws IOException { + rafs[i] = new RandomAccessFile(RAFfile[i], (readonly || !RAFfile[i].canWrite()) ? "r" : "rw"); + RAFtime[i] = System.currentTimeMillis(); + } + + /** + * Can be called even if not open + */ + private void closeRAF(int i) throws IOException { + RAFtime[i] = 0; + if (rafs[i] == null) + return; + rafs[i].close(); + rafs[i] = null; + } + } diff --git a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java index 66217f30a8826e9bdc4c60fd27581abf2c2d2b7b..c312c22d8ab4a39a466f38ec46036701f16b8383 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java +++ b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java @@ -121,7 +121,7 @@ public class TrackerClient extends I2PThread // the primary tracker, that we don't add it twice. trackers = new ArrayList(2); trackers.add(new Tracker(meta.getAnnounce(), true)); - List tlist = SnarkManager.instance().getOpenTrackers(); + List tlist = I2PSnarkUtil.instance().getOpenTrackers(); if (tlist != null) { for (int i = 0; i < tlist.size(); i++) { String url = (String)tlist.get(i); 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 bdb6850780c9ac0b29b679a122a8f0885376f6c7..9745b275f704c95bc32c6f9aa214607a161545a4 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -690,8 +690,8 @@ public class I2PSnarkServlet extends HttpServlet { String uri = req.getRequestURI(); String dataDir = _manager.getDataDir().getAbsolutePath(); boolean autoStart = _manager.shouldAutoStart(); - boolean useOpenTrackers = _manager.shouldUseOpenTrackers(); - String openTrackers = _manager.getOpenTrackerString(); + boolean useOpenTrackers = I2PSnarkUtil.instance().shouldUseOpenTrackers(); + String openTrackers = I2PSnarkUtil.instance().getOpenTrackerString(); //int seedPct = 0; out.write("<form action=\"" + uri + "\" method=\"POST\">\n");