Author: jbonofre
Date: Fri Feb 18 09:19:23 2011
New Revision: 1071929
URL: http://svn.apache.org/viewvc?rev=1071929&view=rev
Log:
[SM-2025] Introduce a timeout management in deployment operations.
Modified:
servicemix/smx3/trunk/core/servicemix-core/src/main/java/org/apache/servicemix/jbi/framework/ComponentRegistry.java
servicemix/smx3/trunk/core/servicemix-core/src/main/java/org/apache/servicemix/jbi/framework/ServiceUnitLifeCycle.java
Modified:
servicemix/smx3/trunk/core/servicemix-core/src/main/java/org/apache/servicemix/jbi/framework/ComponentRegistry.java
URL:
http://svn.apache.org/viewvc/servicemix/smx3/trunk/core/servicemix-core/src/main/java/org/apache/servicemix/jbi/framework/ComponentRegistry.java?rev=1071929&r1=1071928&r2=1071929&view=diff
==============================================================================
---
servicemix/smx3/trunk/core/servicemix-core/src/main/java/org/apache/servicemix/jbi/framework/ComponentRegistry.java
(original)
+++
servicemix/smx3/trunk/core/servicemix-core/src/main/java/org/apache/servicemix/jbi/framework/ComponentRegistry.java
Fri Feb 18 09:19:23 2011
@@ -35,11 +35,11 @@ import org.apache.commons.logging.LogFac
* @version $Revision$
*/
public class ComponentRegistry {
-
+
+ private final Log log = LogFactory.getLog(ComponentRegistry.class);
private final Map<ComponentNameSpace, ComponentMBeanImpl> idMap = new
LinkedHashMap<ComponentNameSpace, ComponentMBeanImpl>();
private boolean runningStateInitialized;
private Registry registry;
- private final Log log = LogFactory.getLog(ComponentRegistry.class);
protected ComponentRegistry(Registry reg) {
this.registry = reg;
Modified:
servicemix/smx3/trunk/core/servicemix-core/src/main/java/org/apache/servicemix/jbi/framework/ServiceUnitLifeCycle.java
URL:
http://svn.apache.org/viewvc/servicemix/smx3/trunk/core/servicemix-core/src/main/java/org/apache/servicemix/jbi/framework/ServiceUnitLifeCycle.java?rev=1071929&r1=1071928&r2=1071929&view=diff
==============================================================================
---
servicemix/smx3/trunk/core/servicemix-core/src/main/java/org/apache/servicemix/jbi/framework/ServiceUnitLifeCycle.java
(original)
+++
servicemix/smx3/trunk/core/servicemix-core/src/main/java/org/apache/servicemix/jbi/framework/ServiceUnitLifeCycle.java
Fri Feb 18 09:19:23 2011
@@ -19,6 +19,7 @@ package org.apache.servicemix.jbi.framew
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
+import java.util.concurrent.Callable;
import javax.jbi.component.ServiceUnitManager;
import javax.jbi.management.DeploymentException;
@@ -40,6 +41,16 @@ import org.apache.servicemix.jbi.managem
public class ServiceUnitLifeCycle implements ServiceUnitMBean,
MBeanInfoProvider {
+ /**
+ * Default timeout for deployment operation.
+ */
+ private static final long DEFAULT_DEPLOYMENT_OPERATION_TIMEOUT = 2 * 60 *
1000;
+
+ /**
+ * Name of the system property that contains deployment operation timeout.
+ */
+ private static final String DEPLOYMENT_OPERATION_TIMEOUT_PROPERTY =
"org.apache.servicemix.deployment.timeout";
+
private static final Log LOG =
LogFactory.getLog(ServiceUnitLifeCycle.class);
private ServiceUnit serviceUnit;
@@ -71,76 +82,159 @@ public class ServiceUnitLifeCycle implem
}
/**
+ * Deployment operation executor that supports timeout.
+ */
+ private class TimedOutExecutor {
+
+ private final ClassLoader classLoader;
+ private final String name;
+ private final Callable<?> task;
+ private Exception fault;
+
+ /**
+ * Constructor.
+ *
+ * @param classLoader the class loader to use for task execution.
+ * @param name Name of this executor. Used for error reporting
purposes.
+ * @param task Task to execute. Return value of task is not used.
+ */
+ public TimedOutExecutor(ClassLoader classLoader, String name,
Callable<?> task) {
+ this.classLoader = classLoader;
+ this.name = name;
+ this.task = task;
+ }
+
+ private class Worker implements Runnable {
+
+ public void run() {
+ try {
+ task.call();
+ } catch (Exception e) {
+ fault = e;
+ }
+ }
+ }
+
+ /**
+ * Executes task respecting timeout.
+ *
+ * @param timeout Timeout for task execution in milliseconds.
+ * @throws DeploymentException If task throws an exception, current
thread is interrupted or timeout expires.
+ */
+ public void execute(long timeout) throws DeploymentException {
+ Thread worker = new Thread(new Worker(), "AsyncDeployer for " +
name);
+ worker.setContextClassLoader(classLoader);
+ worker.start();
+ try {
+ worker.join(timeout);
+ if (worker.isAlive()) {
+ worker.interrupt();
+ throw new DeploymentException("Timeout expired while
waiting for async operation " + name);
+ } else {
+ if (fault != null) {
+ throw new DeploymentException("Error while executing
async operation " + name, fault);
+ }
+ }
+ } catch (InterruptedException interruptedException) {
+ Thread.currentThread().interrupt();
+ throw new DeploymentException("Interrupted while waiting for
async operation " + name, interruptedException);
+ }
+ }
+ }
+
+ /**
+ * Returns effective deployment operation timeout.
+ *
+ * @return Timeout in milliseconds.
+ */
+ private long getDeploymentTimeout() {
+ String propertyValue =
System.getProperty(DEPLOYMENT_OPERATION_TIMEOUT_PROPERTY);
+ if (propertyValue == null) {
+ return DEFAULT_DEPLOYMENT_OPERATION_TIMEOUT;
+ }
+ try {
+ return Long.parseLong(propertyValue);
+ } catch (NumberFormatException numberFormatException) {
+ LOG.warn("Wrong value for system property" +
DEPLOYMENT_OPERATION_TIMEOUT_PROPERTY, numberFormatException);
+ return DEFAULT_DEPLOYMENT_OPERATION_TIMEOUT;
+ }
+ }
+
+ /**
* Initialize the service unit.
+ *
* @throws DeploymentException
*/
public void init() throws DeploymentException {
LOG.info("Initializing service unit: " + getName());
checkComponentStarted("init");
- ServiceUnitManager sum = getServiceUnitManager();
- File path = getServiceUnitRootPath();
- ClassLoader cl = Thread.currentThread().getContextClassLoader();
- try {
-
Thread.currentThread().setContextClassLoader(getComponentClassLoader());
- sum.init(getName(), path.getAbsolutePath());
- } finally {
- Thread.currentThread().setContextClassLoader(cl);
- }
+ final ServiceUnitManager sum = getServiceUnitManager();
+ final File path = getServiceUnitRootPath();
+ new TimedOutExecutor(getComponentClassLoader(), "init " + getName(),
+ new Callable<Object>() {
+ public Object call() throws Exception {
+ sum.init(getName(), path.getAbsolutePath());
+ return null;
+ }
+ }).execute(getDeploymentTimeout());
currentState = STOPPED;
}
/**
* Start the service unit.
+ *
* @throws DeploymentException
*/
public void start() throws DeploymentException {
LOG.info("Starting service unit: " + getName());
checkComponentStarted("start");
- ServiceUnitManager sum = getServiceUnitManager();
- ClassLoader cl = Thread.currentThread().getContextClassLoader();
- try {
-
Thread.currentThread().setContextClassLoader(getComponentClassLoader());
- sum.start(getName());
- } finally {
- Thread.currentThread().setContextClassLoader(cl);
- }
+ final ServiceUnitManager sum = getServiceUnitManager();
+ new TimedOutExecutor(getComponentClassLoader(), "start " + getName(),
+ new Callable<Object>() {
+ public Object call() throws Exception {
+ sum.start(getName());
+ return null;
+ }
+ }).execute(getDeploymentTimeout());
currentState = STARTED;
}
/**
* Stop the service unit. This suspends current messaging activities.
+ *
* @throws DeploymentException
*/
public void stop() throws DeploymentException {
LOG.info("Stopping service unit: " + getName());
checkComponentStarted("stop");
- ServiceUnitManager sum = getServiceUnitManager();
- ClassLoader cl = Thread.currentThread().getContextClassLoader();
- try {
-
Thread.currentThread().setContextClassLoader(getComponentClassLoader());
- sum.stop(getName());
- } finally {
- Thread.currentThread().setContextClassLoader(cl);
- }
+ final ServiceUnitManager sum = getServiceUnitManager();
+ new TimedOutExecutor(getComponentClassLoader(), "stop " + getName(),
+ new Callable<Object>() {
+ public Object call() throws Exception {
+ sum.stop(getName());
+ return null;
+ }
+ }).execute(getDeploymentTimeout());
currentState = STOPPED;
}
/**
* Shut down the service unit.
* This releases resources, preparatory to uninstallation.
+ *
* @throws DeploymentException
*/
public void shutDown() throws DeploymentException {
LOG.info("Shutting down service unit: " + getName());
checkComponentStartedOrStopped("shutDown");
- ServiceUnitManager sum = getServiceUnitManager();
- ClassLoader cl = Thread.currentThread().getContextClassLoader();
- try {
-
Thread.currentThread().setContextClassLoader(getComponentClassLoader());
- sum.shutDown(getName());
- } finally {
- Thread.currentThread().setContextClassLoader(cl);
- }
+ final ServiceUnitManager sum = getServiceUnitManager();
+ new TimedOutExecutor(getComponentClassLoader(), "shutdown " +
getName(),
+ new Callable<Object>() {
+ public Object call() throws Exception {
+ sum.shutDown(getName());
+ return null;
+ }
+ }).execute(getDeploymentTimeout());
currentState = SHUTDOWN;
}