propagate from branch 'i2p.i2p.zzz.android' (head cbf2d39e1944b9d601558761d0eedcdebfd2f589)

to branch 'i2p.i2p' (head c2393e50afccfd5682a9086f0eec2a0700cda2c9)
This commit is contained in:
zzz
2011-06-30 12:27:00 +00:00
53 changed files with 850 additions and 215 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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();
}
/**

View File

@@ -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