* Console, TunnelControllerGroup: Don't register shutdown hook if ClientAppManager is present

* JettyStart: Fixes for use by plugins
 * RouterAppManager: Add shutdown hook
This commit is contained in:
zzz
2013-04-24 15:45:15 +00:00
parent 57fd46d3a1
commit 813a1981d9
6 changed files with 75 additions and 14 deletions

View File

@ -125,6 +125,8 @@ public class TunnelControllerGroup implements ClientApp {
loadControllers(_configFile);
if (_mgr != null)
_mgr.register(this);
// RouterAppManager registers its own shutdown hook
else
_context.addShutdownTask(new Shutdown());
}
@ -194,7 +196,9 @@ public class TunnelControllerGroup implements ClientApp {
*
* @since 0.8.8
*/
public void shutdown() {
public synchronized void shutdown() {
if (_state != STARTING && _state != RUNNING)
return;
changeState(STOPPING);
if (_mgr != null)
_mgr.unregister(this);

View File

@ -41,7 +41,6 @@ import org.eclipse.jetty.xml.XmlConfiguration;
*/
public class JettyStart implements ClientApp {
private final I2PAppContext _context;
private final ClientAppManager _mgr;
private final String[] _args;
private final List<LifeCycle> _jettys;
@ -50,10 +49,12 @@ public class JettyStart implements ClientApp {
/**
* All args must be XML file names.
* Does not support any of the other argument types from org.mortbay.start.Main.
*
* @param context unused, may be null
* @param mgr may be null e.g. for use in plugins
*/
public JettyStart(I2PAppContext context, ClientAppManager mgr, String[] args) throws Exception {
_state = UNINITIALIZED;
_context = context;
_mgr = mgr;
_args = args;
_jettys = new ArrayList(args.length);
@ -100,13 +101,13 @@ public class JettyStart implements ClientApp {
private class Starter extends Thread {
public Starter() {
super("JettyStarter");
changeState(STARTING);
}
/**
* Modified from XmlConfiguration.main()
*/
public void run() {
changeState(STARTING);
for (LifeCycle lc : _jettys) {
if (!lc.isRunning()) {
try {
@ -118,11 +119,12 @@ public class JettyStart implements ClientApp {
}
}
changeState(RUNNING);
if (_mgr != null)
_mgr.register(JettyStart.this);
}
}
public void shutdown(String[] args) {
public synchronized void shutdown(String[] args) {
if (_state != RUNNING)
return;
if (_jettys.isEmpty()) {
@ -135,10 +137,10 @@ public class JettyStart implements ClientApp {
private class Stopper extends Thread {
public Stopper() {
super("JettyStopper");
changeState(STOPPING);
}
public void run() {
changeState(STOPPING);
for (LifeCycle lc : _jettys) {
if (lc.isRunning()) {
try {
@ -170,6 +172,22 @@ public class JettyStart implements ClientApp {
private synchronized void changeState(ClientAppState state, Exception e) {
_state = state;
if (_mgr != null)
_mgr.notify(this, state, null, e);
}
/**
* For use in a plugin clients.config
* @param args passed to constructor
* @since 0.9.6
*/
public static void main(String[] args) {
try {
new JettyStart(null, null, args);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@ -214,15 +214,19 @@ public class RouterConsoleRunner implements RouterApp {
/////// ClientApp methods
/** @since 0.9.4 */
public void startup() {
public synchronized void startup() {
changeState(STARTING);
startTrayApp(_context);
startConsole();
}
/** @since 0.9.4 */
public void shutdown(String[] args) {
public synchronized void shutdown(String[] args) {
if (_state == STOPPED)
return;
changeState(STOPPING);
if (PluginStarter.pluginsEnabled(_context))
(new I2PAppThread(new PluginStopper(_context), "PluginStopper")).start();
try {
_server.stop();
} catch (Exception ie) {}
@ -653,9 +657,10 @@ public class RouterConsoleRunner implements RouterApp {
t = new I2PAppThread(new PluginStarter(_context), "PluginStarter", true);
t.setPriority(Thread.NORM_PRIORITY - 1);
t.start();
_context.addShutdownTask(new PluginStopper(_context));
}
// stat summarizer registers its own hook
// RouterAppManager registers its own hook
if (_mgr == null)
_context.addShutdownTask(new ServerShutdown());
ConfigServiceHandler.registerSignalHandler(_context);
}

View File

@ -1,3 +1,8 @@
2013-04-24 zzz
* Console, i2ptunnel: Don't register shutdown hook if ClientAppManager is present
* JettyStart: Fixes for use by plugins
* RouterAppManager: Add shutdown hook
2013-04-23 zzz
* Console: Fix Jetty digest auth bug causing repeated password requests
* i2ptunnel: Block b32.i2p supercookies

View File

@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 13;
public final static long BUILD = 14;
/** for example "-test" */
public final static String EXTRA = "";

View File

@ -5,8 +5,10 @@ import java.io.Writer;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import net.i2p.app.*;
@ -35,6 +37,7 @@ public class RouterAppManager implements ClientAppManager {
_log = ctx.logManager().getLog(RouterAppManager.class);
_clients = new ConcurrentHashMap(16);
_registered = new ConcurrentHashMap(8);
ctx.addShutdownTask(new Shutdown());
}
/**
@ -166,6 +169,32 @@ public class RouterAppManager implements ClientAppManager {
return _registered.get(name);
}
/// end ClientAppManager interface
/**
* @since 0.9.6
*/
public synchronized void shutdown() {
Set<ClientApp> apps = new HashSet(_clients.keySet());
for (ClientApp app : apps) {
ClientAppState state = app.getState();
if (state == RUNNING || state == STARTING) {
try {
app.shutdown(null);
} catch (Throwable t) {}
}
}
}
/**
* @since 0.9.6
*/
public class Shutdown implements Runnable {
public void run() {
shutdown();
}
}
/**
* debug
* @since 0.9.6