forked from I2P_Developers/i2p.i2p
propagate from branch 'i2p.i2p.zzz.android' (head cbf2d39e1944b9d601558761d0eedcdebfd2f589)
to branch 'i2p.i2p' (head c2393e50afccfd5682a9086f0eec2a0700cda2c9)
This commit is contained in:
@@ -233,7 +233,7 @@ class HTTPResponseOutputStream extends FilterOutputStream {
|
||||
// there after the accept().
|
||||
// Overridden in I2PTunnelHTTPServer, where it does not use the client pool.
|
||||
try {
|
||||
I2PTunnelClientBase._executor.execute(new Pusher(pi, out));
|
||||
I2PTunnelClientBase.getClientExecutor().execute(new Pusher(pi, out));
|
||||
} catch (RejectedExecutionException ree) {
|
||||
// shouldn't happen
|
||||
throw ree;
|
||||
|
@@ -73,12 +73,12 @@ import net.i2p.util.Log;
|
||||
* Todo: Most events are not listened to elsewhere, so error propagation is poor
|
||||
*/
|
||||
public class I2PTunnel implements Logging, EventDispatcher {
|
||||
private Log _log;
|
||||
private EventDispatcherImpl _event;
|
||||
private I2PAppContext _context;
|
||||
private final Log _log;
|
||||
private final EventDispatcherImpl _event;
|
||||
private final I2PAppContext _context;
|
||||
private static long __tunnelId = 0;
|
||||
private long _tunnelId;
|
||||
private Properties _clientOptions;
|
||||
private final long _tunnelId;
|
||||
private final Properties _clientOptions;
|
||||
private final List<I2PSession> _sessions;
|
||||
|
||||
public static final int PACKET_DELAY = 100;
|
||||
|
@@ -83,11 +83,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
* Extending classes may use it for other purposes.
|
||||
* Not for use by servers, as there is no limit on threads.
|
||||
*/
|
||||
static final Executor _executor;
|
||||
private static volatile ThreadPoolExecutor _executor;
|
||||
private static int _executorThreadCount;
|
||||
static {
|
||||
_executor = new CustomThreadPoolExecutor();
|
||||
}
|
||||
|
||||
public I2PTunnelClientBase(int localPort, Logging l, I2PSocketManager sktMgr,
|
||||
I2PTunnel tunnel, EventDispatcher notifyThis, long clientId )
|
||||
@@ -107,6 +104,11 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
_context.statManager().createRateStat("i2ptunnel.client.buildRunTime", "How long it takes to run a queued socket into an i2ptunnel runner?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
|
||||
_log = _context.logManager().getLog(getClass());
|
||||
|
||||
synchronized (I2PTunnelClientBase.class) {
|
||||
if (_executor == null)
|
||||
_executor = new CustomThreadPoolExecutor();
|
||||
}
|
||||
|
||||
Thread t = new I2PAppThread(this, "Client " + tunnel.listenHost + ':' + localPort);
|
||||
listenerReady = false;
|
||||
t.start();
|
||||
@@ -160,6 +162,11 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
_context.statManager().createRateStat("i2ptunnel.client.buildRunTime", "How long it takes to run a queued socket into an i2ptunnel runner?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
|
||||
_log = _context.logManager().getLog(getClass());
|
||||
|
||||
synchronized (I2PTunnelClientBase.class) {
|
||||
if (_executor == null)
|
||||
_executor = new CustomThreadPoolExecutor();
|
||||
}
|
||||
|
||||
// normalize path so we can find it
|
||||
if (pkf != null) {
|
||||
File keyFile = new File(pkf);
|
||||
@@ -551,6 +558,30 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return may be null if no class has been instantiated
|
||||
* @since 0.8.8
|
||||
*/
|
||||
static ThreadPoolExecutor getClientExecutor() {
|
||||
return _executor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.8.8
|
||||
*/
|
||||
static void killClientExecutor() {
|
||||
synchronized (I2PTunnelClientBase.class) {
|
||||
if (_executor != null) {
|
||||
_executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
|
||||
_executor.shutdownNow();
|
||||
_executor = null;
|
||||
}
|
||||
// kill the shared client, so that on restart in android
|
||||
// we won't latch onto the old one
|
||||
socketManager = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage the connection just opened on the specified socket
|
||||
*
|
||||
@@ -558,8 +589,16 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
*/
|
||||
protected void manageConnection(Socket s) {
|
||||
if (s == null) return;
|
||||
ThreadPoolExecutor tpe = _executor;
|
||||
if (tpe == null) {
|
||||
_log.error("No executor for socket!");
|
||||
try {
|
||||
s.close();
|
||||
} catch (IOException ioe) {}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
_executor.execute(new BlockingRunner(s));
|
||||
tpe.execute(new BlockingRunner(s));
|
||||
} catch (RejectedExecutionException ree) {
|
||||
// should never happen, we have an unbounded pool and never stop the executor
|
||||
try {
|
||||
@@ -635,7 +674,6 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
}
|
||||
//l.log("Client closed.");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -67,6 +67,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
|
||||
protected I2PTunnelTask task = null;
|
||||
protected boolean bidir = false;
|
||||
private ThreadPoolExecutor _executor;
|
||||
|
||||
private int DEFAULT_LOCALPORT = 4488;
|
||||
protected int localPort = DEFAULT_LOCALPORT;
|
||||
@@ -259,6 +260,10 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
}
|
||||
//l.log("Server shut down.");
|
||||
open = false;
|
||||
if (_usePool && _executor != null) {
|
||||
_executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
|
||||
_executor.shutdownNow();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -283,7 +288,6 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
*/
|
||||
public void run() {
|
||||
I2PServerSocket i2pS_S = sockMgr.getServerSocket();
|
||||
ThreadPoolExecutor executor = null;
|
||||
if (_log.shouldLog(Log.WARN)) {
|
||||
if (_usePool)
|
||||
_log.warn("Starting executor with " + getHandlerCount() + " threads max");
|
||||
@@ -291,7 +295,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
_log.warn("Threads disabled, running blockingHandles inline");
|
||||
}
|
||||
if (_usePool) {
|
||||
executor = new CustomThreadPoolExecutor(getHandlerCount(), "ServerHandler pool " + remoteHost + ':' + remotePort);
|
||||
_executor = new CustomThreadPoolExecutor(getHandlerCount(), "ServerHandler pool " + remoteHost + ':' + remotePort);
|
||||
}
|
||||
while (open) {
|
||||
try {
|
||||
@@ -299,7 +303,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
if (i2ps == null) throw new I2PException("I2PServerSocket closed");
|
||||
if (_usePool) {
|
||||
try {
|
||||
executor.execute(new Handler(i2ps));
|
||||
_executor.execute(new Handler(i2ps));
|
||||
} catch (RejectedExecutionException ree) {
|
||||
try {
|
||||
i2ps.close();
|
||||
@@ -328,8 +332,8 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
// ignored, we never set the timeout
|
||||
}
|
||||
}
|
||||
if (executor != null)
|
||||
executor.shutdownNow();
|
||||
if (_executor != null)
|
||||
_executor.shutdownNow();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -26,7 +26,7 @@ import net.i2p.util.OrderedProperties;
|
||||
* Warning - this is a singleton. Todo: fix
|
||||
*/
|
||||
public class TunnelControllerGroup {
|
||||
private final Log _log;
|
||||
private Log _log;
|
||||
private static TunnelControllerGroup _instance;
|
||||
static final String DEFAULT_CONFIG_FILE = "i2ptunnel.config";
|
||||
|
||||
@@ -55,6 +55,7 @@ public class TunnelControllerGroup {
|
||||
_configFile = configFile;
|
||||
_sessions = new HashMap(4);
|
||||
loadControllers(_configFile);
|
||||
I2PAppContext.getGlobalContext().addShutdownTask(new Shutdown());
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
@@ -71,6 +72,34 @@ public class TunnelControllerGroup {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Warning - destroys the singleton!
|
||||
* @since 0.8.8
|
||||
*/
|
||||
private static class Shutdown implements Runnable {
|
||||
public void run() {
|
||||
shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Warning - destroys the singleton!
|
||||
* Caller must root a new context before calling instance() or main() again.
|
||||
* Agressively kill and null everything to reduce memory usage in the JVM
|
||||
* after stopping, and to recognize what must be reinitialized on restart (Android)
|
||||
*
|
||||
* @since 0.8.8
|
||||
*/
|
||||
public static void shutdown() {
|
||||
synchronized (TunnelControllerGroup.class) {
|
||||
if (_instance == null) return;
|
||||
_instance.unloadControllers();
|
||||
_instance._log = null;
|
||||
_instance = null;
|
||||
}
|
||||
I2PTunnelClientBase.killClientExecutor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load up all of the tunnels configured in the given file (but do not start
|
||||
|
Reference in New Issue
Block a user