i2psnark:

- Don't create SnarkManager instance until first call,
      so it doesn't create the i2psnark dir, read the config,
      etc., for single Snark instances.
    - Don't read i2psnark.config twice; fix setting
      i2psnark.dir
    - More Snark constructor changes for calling from router
    - Make max connections per torrent configurable
This commit is contained in:
zzz
2008-11-18 02:18:23 +00:00
parent 134764b154
commit 0ff8167425
5 changed files with 71 additions and 21 deletions

View File

@ -47,12 +47,14 @@ public class I2PSnarkUtil {
private Set _shitlist; private Set _shitlist;
private int _maxUploaders; private int _maxUploaders;
private int _maxUpBW; private int _maxUpBW;
private int _maxConnections;
public static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers"; public static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers";
public static final boolean DEFAULT_USE_OPENTRACKERS = true; public static final boolean DEFAULT_USE_OPENTRACKERS = true;
public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers"; public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers";
public static final String DEFAULT_OPENTRACKERS = "http://tracker.welterde.i2p/a"; public static final String DEFAULT_OPENTRACKERS = "http://tracker.welterde.i2p/a";
public static final int DEFAULT_MAX_UP_BW = 8; //KBps public static final int DEFAULT_MAX_UP_BW = 8; //KBps
public static final int MAX_CONNECTIONS = 16; // per torrent
public I2PSnarkUtil(I2PAppContext ctx) { public I2PSnarkUtil(I2PAppContext ctx) {
_context = ctx; _context = ctx;
@ -64,6 +66,7 @@ public class I2PSnarkUtil {
_configured = false; _configured = false;
_maxUploaders = Snark.MAX_TOTAL_UPLOADERS; _maxUploaders = Snark.MAX_TOTAL_UPLOADERS;
_maxUpBW = DEFAULT_MAX_UP_BW; _maxUpBW = DEFAULT_MAX_UP_BW;
_maxConnections = MAX_CONNECTIONS;
} }
/** /**
@ -87,7 +90,9 @@ public class I2PSnarkUtil {
public boolean configured() { return _configured; } public boolean configured() { return _configured; }
public void setI2CPConfig(String i2cpHost, int i2cpPort, Map opts) { public void setI2CPConfig(String i2cpHost, int i2cpPort, Map opts) {
if (i2cpHost != null)
_i2cpHost = i2cpHost; _i2cpHost = i2cpHost;
if (i2cpPort > 0)
_i2cpPort = i2cpPort; _i2cpPort = i2cpPort;
if (opts != null) if (opts != null)
_opts.putAll(opts); _opts.putAll(opts);
@ -104,6 +109,11 @@ public class I2PSnarkUtil {
_configured = true; _configured = true;
} }
public void setMaxConnections(int limit) {
_maxConnections = limit;
_configured = true;
}
public String getI2CPHost() { return _i2cpHost; } public String getI2CPHost() { return _i2cpHost; }
public int getI2CPPort() { return _i2cpPort; } public int getI2CPPort() { return _i2cpPort; }
public Map getI2CPOptions() { return _opts; } public Map getI2CPOptions() { return _opts; }
@ -112,6 +122,7 @@ public class I2PSnarkUtil {
public boolean getEepProxySet() { return _shouldProxy; } public boolean getEepProxySet() { return _shouldProxy; }
public int getMaxUploaders() { return _maxUploaders; } public int getMaxUploaders() { return _maxUploaders; }
public int getMaxUpBW() { return _maxUpBW; } public int getMaxUpBW() { return _maxUpBW; }
public int getMaxConnections() { return _maxConnections; }
/** /**
* Connect to the router, if we aren't already * Connect to the router, if we aren't already

View File

@ -44,7 +44,6 @@ public class PeerCoordinator implements PeerListener
// 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_CONNECTIONS = 16;
final static int MAX_UPLOADERS = 6; final static int MAX_UPLOADERS = 6;
// Approximation of the number of current uploaders. // Approximation of the number of current uploaders.
@ -237,7 +236,7 @@ public class PeerCoordinator implements PeerListener
{ {
synchronized(peers) synchronized(peers)
{ {
return !halted && peers.size() < MAX_CONNECTIONS; return !halted && peers.size() < _util.getMaxConnections();
} }
} }
@ -295,7 +294,7 @@ public class PeerCoordinator implements PeerListener
peer.disconnect(false); // Don't deregister this connection/peer. peer.disconnect(false); // Don't deregister this connection/peer.
} }
// This is already checked in addPeer() but we could have gone over the limit since then // This is already checked in addPeer() but we could have gone over the limit since then
else if (peers.size() >= MAX_CONNECTIONS) else if (peers.size() >= _util.getMaxConnections())
{ {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
_log.warn("Already at MAX_CONNECTIONS in connected() with peer: " + peer); _log.warn("Already at MAX_CONNECTIONS in connected() with peer: " + peer);
@ -351,7 +350,7 @@ public class PeerCoordinator implements PeerListener
peersize = peers.size(); peersize = peers.size();
// This isn't a strict limit, as we may have several pending connections; // This isn't a strict limit, as we may have several pending connections;
// thus there is an additional check in connected() // thus there is an additional check in connected()
need_more = (!peer.isConnected()) && peersize < MAX_CONNECTIONS; need_more = (!peer.isConnected()) && peersize < _util.getMaxConnections();
// Check if we already have this peer before we build the connection // Check if we already have this peer before we build the connection
Peer old = peerIDInList(peer.getPeerID(), peers); Peer old = peerIDInList(peer.getPeerID(), peers);
need_more = need_more && ((old == null) || (old.getInactiveTime() > 8*60*1000)); need_more = need_more && ((old == null) || (old.getInactiveTime() > 8*60*1000));
@ -379,7 +378,7 @@ public class PeerCoordinator implements PeerListener
if (peer.isConnected()) if (peer.isConnected())
_log.info("Add peer already connected: " + peer); _log.info("Add peer already connected: " + peer);
else else
_log.info("Connections: " + peersize + "/" + MAX_CONNECTIONS _log.info("Connections: " + peersize + "/" + _util.getMaxConnections()
+ " not accepting extra peer: " + peer); + " not accepting extra peer: " + peer);
} }
return false; return false;

View File

@ -28,6 +28,7 @@ import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Random; import java.util.Random;
import java.util.StringTokenizer; import java.util.StringTokenizer;
@ -35,6 +36,7 @@ import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.router.client.ClientManagerFacadeImpl;
import net.i2p.client.streaming.I2PServerSocket; import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.data.Destination; import net.i2p.data.Destination;
import net.i2p.util.I2PThread; import net.i2p.util.I2PThread;
@ -235,6 +237,7 @@ public class Snark
} }
} }
public static final String PROP_MAX_CONNECTIONS = "i2psnark.maxConnections";
public String torrent; public String torrent;
public MetaInfo meta; public MetaInfo meta;
public Storage storage; public Storage storage;
@ -254,10 +257,35 @@ public class Snark
this(util, torrent, ip, user_port, slistener, clistener, null, null, null, true, "."); this(util, torrent, ip, user_port, slistener, clistener, null, null, null, true, ".");
} }
/** single torrent */ /** single torrent - via router */
Snark(I2PAppContext ctx, String torrent, String ip, int user_port, public Snark(I2PAppContext ctx, Properties opts, String torrent,
StorageListener slistener, CoordinatorListener clistener) { StorageListener slistener, boolean start, String rootDir) {
this(new I2PSnarkUtil(ctx), torrent, ip, user_port, slistener, clistener, null, null, null, true, "."); this(new I2PSnarkUtil(ctx), torrent, null, -1, slistener, null, null, null, null, false, rootDir);
String host = opts.getProperty(ClientManagerFacadeImpl.PROP_CLIENT_HOST);
int port = 0;
String s = opts.getProperty(ClientManagerFacadeImpl.PROP_CLIENT_PORT);
if (s != null) {
try {
port = Integer.parseInt(s);
} catch (NumberFormatException nfe) {}
}
_util.setI2CPConfig(host, port, opts);
s = opts.getProperty(SnarkManager.PROP_UPBW_MAX);
if (s != null) {
try {
int v = Integer.parseInt(s);
_util.setMaxUpBW(v);
} catch (NumberFormatException nfe) {}
}
s = opts.getProperty(PROP_MAX_CONNECTIONS);
if (s != null) {
try {
int v = Integer.parseInt(s);
_util.setMaxConnections(v);
} catch (NumberFormatException nfe) {}
}
if (start)
this.startTorrent();
} }
/** multitorrent */ /** multitorrent */
@ -523,6 +551,8 @@ public class Snark
} }
if (pc != null && _peerCoordinatorSet != null) if (pc != null && _peerCoordinatorSet != null)
_peerCoordinatorSet.remove(pc); _peerCoordinatorSet.remove(pc);
if (_peerCoordinatorSet == null)
_util.disconnect();
} }
static Snark parseArguments(String[] args) static Snark parseArguments(String[] args)

View File

@ -32,7 +32,7 @@ public class SnarkManager implements Snark.CompleteListener {
/** map of (canonical) filename to Snark instance (unsynchronized) */ /** map of (canonical) filename to Snark instance (unsynchronized) */
private Map _snarks; private Map _snarks;
private Object _addSnarkLock; private Object _addSnarkLock;
private String _configFile; private String _configFile = "i2psnark.config";
private Properties _config; private Properties _config;
private I2PAppContext _context; private I2PAppContext _context;
private Log _log; private Log _log;
@ -67,9 +67,15 @@ public class SnarkManager implements Snark.CompleteListener {
_log = _context.logManager().getLog(SnarkManager.class); _log = _context.logManager().getLog(SnarkManager.class);
_messages = new ArrayList(16); _messages = new ArrayList(16);
_util = new I2PSnarkUtil(_context); _util = new I2PSnarkUtil(_context);
loadConfig(null);
}
/** Caller _must_ call loadConfig(file) before this if setting new values
* for i2cp host/port or i2psnark.dir
*/
public void start() {
_peerCoordinatorSet = new PeerCoordinatorSet(); _peerCoordinatorSet = new PeerCoordinatorSet();
_connectionAcceptor = new ConnectionAcceptor(_util); _connectionAcceptor = new ConnectionAcceptor(_util);
loadConfig("i2psnark.config");
int minutes = getStartupDelayMinutes(); int minutes = getStartupDelayMinutes();
_messages.add("Adding torrents in " + minutes + (minutes == 1 ? " minute" : " minutes")); _messages.add("Adding torrents in " + minutes + (minutes == 1 ? " minute" : " minutes"));
I2PAppThread monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor"); I2PAppThread monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor");
@ -114,10 +120,12 @@ public class SnarkManager implements Snark.CompleteListener {
return new File(dir); return new File(dir);
} }
/** null to set initial defaults */
public void loadConfig(String filename) { public void loadConfig(String filename) {
_configFile = filename;
if (_config == null) if (_config == null)
_config = new Properties(); _config = new Properties();
if (filename != null) {
_configFile = filename;
File cfg = new File(filename); File cfg = new File(filename);
if (cfg.exists()) { if (cfg.exists()) {
try { try {
@ -126,6 +134,7 @@ public class SnarkManager implements Snark.CompleteListener {
_log.error("Error loading I2PSnark config '" + filename + "'", ioe); _log.error("Error loading I2PSnark config '" + filename + "'", ioe);
} }
} }
}
// now add sane defaults // now add sane defaults
if (!_config.containsKey(PROP_I2CP_HOST)) if (!_config.containsKey(PROP_I2CP_HOST))
_config.setProperty(PROP_I2CP_HOST, "localhost"); _config.setProperty(PROP_I2CP_HOST, "localhost");

View File

@ -55,6 +55,7 @@ public class I2PSnarkServlet extends HttpServlet {
if ( (configFile == null) || (configFile.trim().length() <= 0) ) if ( (configFile == null) || (configFile.trim().length() <= 0) )
configFile = "i2psnark.config"; configFile = "i2psnark.config";
_manager.loadConfig(configFile); _manager.loadConfig(configFile);
_manager.start();
} }
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {