diff --git a/apps/i2psnark/java/src/org/klomp/snark/ConnectionAcceptor.java b/apps/i2psnark/java/src/org/klomp/snark/ConnectionAcceptor.java index 5f5e02abc..6d4aad1a3 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/ConnectionAcceptor.java +++ b/apps/i2psnark/java/src/org/klomp/snark/ConnectionAcceptor.java @@ -28,7 +28,7 @@ import java.io.OutputStream; import net.i2p.I2PException; import net.i2p.client.streaming.I2PServerSocket; import net.i2p.client.streaming.I2PSocket; -import net.i2p.util.I2PThread; +import net.i2p.util.I2PAppThread; import net.i2p.util.Log; /** @@ -55,7 +55,7 @@ public class ConnectionAcceptor implements Runnable stop = false; socketChanged = true; if (thread == null) { - thread = new I2PThread(this, "I2PSnark acceptor"); + thread = new I2PAppThread(this, "I2PSnark acceptor"); thread.setDaemon(true); thread.start(); } @@ -71,7 +71,7 @@ public class ConnectionAcceptor implements Runnable socketChanged = false; stop = false; - thread = new I2PThread(this, "I2PSnark acceptor"); + thread = new I2PAppThread(this, "I2PSnark acceptor"); thread.setDaemon(true); thread.start(); } @@ -136,7 +136,7 @@ public class ConnectionAcceptor implements Runnable } } } else { - Thread t = new I2PThread(new Handler(socket), "Connection-" + socket); + Thread t = new I2PAppThread(new Handler(socket), "Connection-" + socket); t.start(); } } diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java b/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java index eeb6455c6..8fed9577a 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java @@ -26,7 +26,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import net.i2p.util.I2PThread; +import net.i2p.util.I2PAppThread; import net.i2p.util.Log; import net.i2p.util.SimpleTimer; @@ -58,7 +58,7 @@ class PeerConnectionOut implements Runnable } public void startup() { - thread = new I2PThread(this, "Snark sender " + _id + ": " + peer); + thread = new I2PAppThread(this, "Snark sender " + _id + ": " + peer); thread.start(); } diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java index 042340160..b54cbdafa 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java @@ -29,7 +29,7 @@ import java.util.List; import java.util.Random; import java.util.Timer; -import net.i2p.util.I2PThread; +import net.i2p.util.I2PAppThread; import net.i2p.util.Log; /** @@ -372,7 +372,7 @@ public class PeerCoordinator implements PeerListener } }; String threadName = peer.toString(); - new I2PThread(r, threadName).start(); + new I2PAppThread(r, threadName).start(); return true; } if (_log.shouldLog(Log.DEBUG)) { diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java index 4df69d080..6ae2be6dd 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java +++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java @@ -19,7 +19,7 @@ import net.i2p.I2PAppContext; import net.i2p.data.Base64; import net.i2p.data.DataHelper; import net.i2p.router.RouterContext; -import net.i2p.util.I2PThread; +import net.i2p.util.I2PAppThread; import net.i2p.util.Log; /** @@ -72,7 +72,7 @@ public class SnarkManager implements Snark.CompleteListener { loadConfig("i2psnark.config"); int minutes = getStartupDelayMinutes(); _messages.add("Adding torrents in " + minutes + (minutes == 1 ? " minute" : " minutes")); - I2PThread monitor = new I2PThread(new DirMonitor(), "Snark DirMonitor"); + I2PAppThread monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor"); monitor.setDaemon(true); monitor.start(); if (_context instanceof RouterContext) @@ -726,7 +726,7 @@ public class SnarkManager implements Snark.CompleteListener { } } - public class SnarkManagerShutdown extends I2PThread { + public class SnarkManagerShutdown extends I2PAppThread { public void run() { Set names = listTorrentFiles(); for (Iterator iter = names.iterator(); iter.hasNext(); ) { diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkShutdown.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkShutdown.java index 44832a212..376d17fa5 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/SnarkShutdown.java +++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkShutdown.java @@ -22,12 +22,12 @@ package org.klomp.snark; import java.io.IOException; -import net.i2p.util.I2PThread; +import net.i2p.util.I2PAppThread; /** * Makes sure everything ends correctly when shutting down. */ -public class SnarkShutdown extends I2PThread +public class SnarkShutdown extends I2PAppThread { private final Storage storage; private final PeerCoordinator coordinator; diff --git a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java index 2b33db94d..21e6bcac2 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java +++ b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java @@ -31,7 +31,7 @@ import java.util.List; import java.util.Random; import java.util.Set; -import net.i2p.util.I2PThread; +import net.i2p.util.I2PAppThread; import net.i2p.util.Log; /** @@ -40,7 +40,7 @@ import net.i2p.util.Log; * * @author Mark Wielaard (mark@klomp.org) */ -public class TrackerClient extends I2PThread +public class TrackerClient extends I2PAppThread { private static final Log _log = new Log(TrackerClient.class); private static final String NO_EVENT = ""; 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 b5491891a..c4baa45cd 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -23,7 +23,7 @@ import net.i2p.I2PAppContext; import net.i2p.data.Base64; import net.i2p.data.DataHelper; import net.i2p.util.FileUtil; -import net.i2p.util.I2PThread; +import net.i2p.util.I2PAppThread; import net.i2p.util.Log; import org.klomp.snark.I2PSnarkUtil; @@ -201,7 +201,7 @@ public class I2PSnarkServlet extends HttpServlet { } } else if ( (newURL != null) && (newURL.trim().length() > "http://.i2p/".length()) ) { _manager.addMessage("Fetching " + newURL); - I2PThread fetch = new I2PThread(new FetchAndAdd(_manager, newURL), "Fetch and add"); + I2PAppThread fetch = new I2PAppThread(new FetchAndAdd(_manager, newURL), "Fetch and add"); fetch.start(); } else { // no file or URL specified diff --git a/core/java/src/net/i2p/util/I2PAppThread.java b/core/java/src/net/i2p/util/I2PAppThread.java new file mode 100644 index 000000000..fd7256578 --- /dev/null +++ b/core/java/src/net/i2p/util/I2PAppThread.java @@ -0,0 +1,62 @@ +package net.i2p.util; + +/* + * free (adj.): unencumbered; not under the control of others + * Written by jrandom in 2003 and released into the public domain + * with no warranty of any kind, either expressed or implied. + * It probably won't make your computer catch on fire, or eat + * your children, but it might. Use at your own risk. + * + */ + + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +/** + * Like I2PThread but with per-thread OOM listeners, + * rather than a static router-wide listener list, + * so that an OOM in an app won't call the router listener + * to shutdown the whole router. + */ +public class I2PAppThread extends I2PThread { + + private Set _threadListeners = new HashSet(0); + + public I2PAppThread() { + super(); + } + + public I2PAppThread(String name) { + super(name); + } + + public I2PAppThread(Runnable r) { + super(r); + } + + public I2PAppThread(Runnable r, String name) { + super(r, name); + } + public I2PAppThread(Runnable r, String name, boolean isDaemon) { + super(r, name); + } + + protected void fireOOM(OutOfMemoryError oom) { + for (Iterator iter = _threadListeners.iterator(); iter.hasNext(); ) { + OOMEventListener listener = (OOMEventListener)iter.next(); + listener.outOfMemory(oom); + } + } + + /** register a new component that wants notification of OOM events */ + public void addOOMEventThreadListener(OOMEventListener lsnr) { + _threadListeners.add(lsnr); + } + + /** unregister a component that wants notification of OOM events */ + public void removeOOMEventThreadListener(OOMEventListener lsnr) { + _threadListeners.remove(lsnr); + } +} diff --git a/core/java/src/net/i2p/util/I2PThread.java b/core/java/src/net/i2p/util/I2PThread.java index 3756eda9e..dcbddd89e 100644 --- a/core/java/src/net/i2p/util/I2PThread.java +++ b/core/java/src/net/i2p/util/I2PThread.java @@ -88,7 +88,7 @@ public class I2PThread extends Thread { super.finalize(); } - private void fireOOM(OutOfMemoryError oom) { + protected void fireOOM(OutOfMemoryError oom) { for (Iterator iter = _listeners.iterator(); iter.hasNext(); ) { OOMEventListener listener = (OOMEventListener)iter.next(); listener.outOfMemory(oom);