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


Reply via email to