From b4f65bafaca8e8013c417355a3c470ed2f997ee7 Mon Sep 17 00:00:00 2001 From: "Hiram R. Chirino" Date: Mon, 12 May 2008 20:54:31 +0000 Subject: [PATCH] Fix for https://issues.apache.org/activemq/browse/AMQ-1720 added the ability to get a callback when the broker is shutdown. Also added an option to System.exit when the broker is shutdown. git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@655639 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/activemq/console/Main.java | 3 ++ .../console/command/StartCommand.java | 36 +++++++++++---- .../apache/activemq/broker/BrokerService.java | 45 ++++++++++++++++++- .../store/jdbc/JDBCPersistenceAdapter.java | 2 +- .../activemq/xbean/BrokerFactoryBean.java | 35 +++++++++++++++ 5 files changed, 109 insertions(+), 12 deletions(-) diff --git a/activemq-console/src/main/java/org/apache/activemq/console/Main.java b/activemq-console/src/main/java/org/apache/activemq/console/Main.java index 1edb8f034d..7bf409c5c7 100644 --- a/activemq-console/src/main/java/org/apache/activemq/console/Main.java +++ b/activemq-console/src/main/java/org/apache/activemq/console/Main.java @@ -104,6 +104,7 @@ public class Main { try { app.runTaskClass(tokens); + System.exit(0); } catch (ClassNotFoundException e) { System.out.println("Could not load class: " + e.getMessage()); try { @@ -114,8 +115,10 @@ public class Main { } } catch (MalformedURLException e1) { } + System.exit(1); } catch (Throwable e) { System.out.println("Failed to execute main task. Reason: " + e); + System.exit(1); } } diff --git a/activemq-console/src/main/java/org/apache/activemq/console/command/StartCommand.java b/activemq-console/src/main/java/org/apache/activemq/console/command/StartCommand.java index ab7910ee58..9862effc61 100644 --- a/activemq-console/src/main/java/org/apache/activemq/console/command/StartCommand.java +++ b/activemq-console/src/main/java/org/apache/activemq/console/command/StartCommand.java @@ -22,6 +22,7 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; import org.apache.activemq.broker.BrokerFactory; import org.apache.activemq.broker.BrokerService; @@ -93,11 +94,14 @@ public class StartCommand extends AbstractCommand { // Prevent the main thread from exiting unless it is terminated // elsewhere - waitForShutdown(); } catch (Exception e) { context.printException(new RuntimeException("Failed to execute start task. Reason: " + e, e)); throw new Exception(e); } + + // The broker start up fine. If this unblocks it's cause they were stopped + // and this would occur because of an internal error (like the DB going offline) + waitForShutdown(); } /** @@ -122,14 +126,33 @@ public class StartCommand extends AbstractCommand { final boolean[] shutdown = new boolean[] { false }; + Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { - synchronized (shutdown) { - shutdown[0] = true; - shutdown.notify(); + for (Iterator i = brokers.iterator(); i.hasNext();) { + try { + BrokerService broker = i.next(); + broker.stop(); + } catch (Exception e) { + } } } }); + + final AtomicInteger brokerCounter = new AtomicInteger(brokers.size()); + for (BrokerService bs : brokers) { + bs.addShutdownHook(new Runnable() { + public void run() { + // When the last broker lets us know he is closed.... + if( brokerCounter.decrementAndGet() == 0 ) { + synchronized (shutdown) { + shutdown[0] = true; + shutdown.notify(); + } + } + } + }); + } // Wait for any shutdown event synchronized (shutdown) { @@ -141,11 +164,6 @@ public class StartCommand extends AbstractCommand { } } - // Stop each broker - for (Iterator i = brokers.iterator(); i.hasNext();) { - BrokerService broker = i.next(); - broker.stop(); - } } /** diff --git a/activemq-core/src/main/java/org/apache/activemq/broker/BrokerService.java b/activemq-core/src/main/java/org/apache/activemq/broker/BrokerService.java index f31c885914..16e5308c85 100644 --- a/activemq-core/src/main/java/org/apache/activemq/broker/BrokerService.java +++ b/activemq-core/src/main/java/org/apache/activemq/broker/BrokerService.java @@ -170,8 +170,10 @@ public class BrokerService implements Service { private boolean dedicatedTaskRunner; private boolean cacheTempDestinations=false;//useful for failover private int timeBeforePurgeTempDestinations = 5000; - - + private List shutdownHooks= new ArrayList(); + private boolean systemExitOnShutdown; + private int systemExitOnShutdownExitCode; + static { String localHostName = "localhost"; try { @@ -425,6 +427,15 @@ public class BrokerService implements Service { } try { + + if( systemExitOnShutdown ) { + addShutdownHook(new Runnable(){ + public void run() { + System.exit(systemExitOnShutdownExitCode); + } + }); + } + processHelperProperties(); BrokerRegistry.getInstance().bind(getBrokerName(), this); @@ -510,6 +521,15 @@ public class BrokerService implements Service { stopped.set(true); stoppedLatch.countDown(); LOG.info("ActiveMQ JMS Message Broker (" + getBrokerName() + ", " + brokerId + ") stopped"); + synchronized(shutdownHooks) { + for (Runnable hook : shutdownHooks) { + try { + hook.run(); + } catch ( Throwable e ) { + stopper.onException(hook, e); + } + } + } stopper.throwFirstException(); } @@ -1912,4 +1932,25 @@ public class BrokerService implements Service { this.regionBroker = regionBroker; } + + public void addShutdownHook(Runnable hook) { + synchronized(shutdownHooks) { + shutdownHooks.add(hook); + } + } + + public void removeShutdownHook(Runnable hook) { + synchronized(shutdownHooks) { + shutdownHooks.remove(hook); + } + } + + public boolean isSystemExitOnShutdown() { + return systemExitOnShutdown; + } + + public void setSystemExitOnShutdown(boolean systemExitOnShutdown) { + this.systemExitOnShutdown = systemExitOnShutdown; + } + } \ No newline at end of file diff --git a/activemq-core/src/main/java/org/apache/activemq/store/jdbc/JDBCPersistenceAdapter.java b/activemq-core/src/main/java/org/apache/activemq/store/jdbc/JDBCPersistenceAdapter.java index fc19bb2a9b..2adb6f7198 100755 --- a/activemq-core/src/main/java/org/apache/activemq/store/jdbc/JDBCPersistenceAdapter.java +++ b/activemq-core/src/main/java/org/apache/activemq/store/jdbc/JDBCPersistenceAdapter.java @@ -473,7 +473,7 @@ public class JDBCPersistenceAdapter extends DataSourceSupport implements Persist try { brokerService.stop(); } catch (Exception e) { - LOG.warn("Failed to stop broker"); + LOG.warn("Failure occured while stopping broker"); } } diff --git a/activemq-core/src/main/java/org/apache/activemq/xbean/BrokerFactoryBean.java b/activemq-core/src/main/java/org/apache/activemq/xbean/BrokerFactoryBean.java index 8e1d7c6d63..8eaf05bc0e 100644 --- a/activemq-core/src/main/java/org/apache/activemq/xbean/BrokerFactoryBean.java +++ b/activemq-core/src/main/java/org/apache/activemq/xbean/BrokerFactoryBean.java @@ -51,6 +51,9 @@ public class BrokerFactoryBean implements FactoryBean, InitializingBean, Disposa private boolean start; private ResourceXmlApplicationContext context; private ApplicationContext parentContext; + + private boolean systemExitOnShutdown; + private int systemExitOnShutdownExitCode; public BrokerFactoryBean() { } @@ -101,6 +104,14 @@ public class BrokerFactoryBean implements FactoryBean, InitializingBean, Disposa if (broker == null) { throw new IllegalArgumentException("The configuration has no BrokerService instance for resource: " + config); } + + if( systemExitOnShutdown ) { + broker.addShutdownHook(new Runnable(){ + public void run() { + System.exit(systemExitOnShutdownExitCode); + } + }); + } if (start) { broker.start(); } @@ -135,4 +146,28 @@ public class BrokerFactoryBean implements FactoryBean, InitializingBean, Disposa this.start = start; } + public boolean isSystemExitOnStop() { + return systemExitOnShutdown; + } + + public void setSystemExitOnStop(boolean systemExitOnStop) { + this.systemExitOnShutdown = systemExitOnStop; + } + + public boolean isSystemExitOnShutdown() { + return systemExitOnShutdown; + } + + public void setSystemExitOnShutdown(boolean systemExitOnShutdown) { + this.systemExitOnShutdown = systemExitOnShutdown; + } + + public int getSystemExitOnShutdownExitCode() { + return systemExitOnShutdownExitCode; + } + + public void setSystemExitOnShutdownExitCode(int systemExitOnShutdownExitCode) { + this.systemExitOnShutdownExitCode = systemExitOnShutdownExitCode; + } + }