You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pd...@apache.org on 2015/11/22 22:49:00 UTC

svn commit: r1715707 - in /felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm: context/ComponentContext.java context/packageinfo impl/ComponentImpl.java impl/ConfigurationDependencyImpl.java impl/FilterComponent.java

Author: pderop
Date: Sun Nov 22 21:49:00 2015
New Revision: 1715707

URL: http://svn.apache.org/viewvc?rev=1715707&view=rev
Log:
FELIX-5114: Schedule configuration update in Component executor synchronously.
The getExecutor method is now exposed from the ComponentContext interface. Hence, the version for the 
org.apache.felix.dm.context has been bumped to 4.1.0 version.

Modified:
    felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/context/ComponentContext.java
    felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/context/packageinfo
    felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java
    felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ConfigurationDependencyImpl.java
    felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FilterComponent.java

Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/context/ComponentContext.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/context/ComponentContext.java?rev=1715707&r1=1715706&r2=1715707&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/context/ComponentContext.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/context/ComponentContext.java Sun Nov 22 21:49:00 2015
@@ -27,6 +27,8 @@ import org.apache.felix.dm.Logger;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 
+import aQute.bnd.annotation.ProviderType;
+
 /**
  * This interface is the entry point to the Component implementation context.
  * It is used by all DependencyManager Dependency implementations.
@@ -34,8 +36,17 @@ import org.osgi.framework.BundleContext;
  * @see DependencyContext interface
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
+@ProviderType
 public interface ComponentContext extends Component {
     /**
+     * Returns the Component Executor gate that can be used to ensure proper component event serialization.
+     * When you schedule a task in the component executor, your task is executed safely and you do not need
+     * to managed synchronization (other external events, like service dependency events) will be queued
+     * until your task has been executed). 
+     */
+    public Executor getExecutor();    
+    
+    /**
      * Returns the logger which can be used by the DependencyManager Dependencies implementations.
      */
     public Logger getLogger();

Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/context/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/context/packageinfo?rev=1715707&r1=1715706&r2=1715707&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/context/packageinfo (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/context/packageinfo Sun Nov 22 21:49:00 2015
@@ -1 +1 @@
-version 4.0.0
+version 4.1.0

Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java?rev=1715707&r1=1715706&r2=1715707&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java Sun Nov 22 21:49:00 2015
@@ -341,6 +341,11 @@ public class ComponentImpl implements Co
     }
 
     @Override
+    public Executor getExecutor() {
+        return m_executor;
+    }
+
+    @Override
     public Component setDebug(String debugKey) {
         // Force debug level in our logger
         m_logger.setEnabledLevel(LogService.LOG_DEBUG);
@@ -1607,8 +1612,4 @@ public class ComponentImpl implements Co
             result.append(")");
         }
     }
-    
-    private Executor getExecutor() {
-        return m_executor;
-    }
 }

Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ConfigurationDependencyImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ConfigurationDependencyImpl.java?rev=1715707&r1=1715706&r2=1715707&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ConfigurationDependencyImpl.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ConfigurationDependencyImpl.java Sun Nov 22 21:49:00 2015
@@ -21,6 +21,11 @@ package org.apache.felix.dm.impl;
 import java.lang.reflect.InvocationTargetException;
 import java.util.Dictionary;
 import java.util.Properties;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.felix.dm.Component;
@@ -52,6 +57,7 @@ public class ConfigurationDependencyImpl
 	private final Logger m_logger;
 	private final BundleContext m_context;
 	private boolean m_needsInstance = true;
+	private final static int UPDATE_MAXWAIT = 30000; // max time to wait until a component has handled a configuration change event.
 
     public ConfigurationDependencyImpl() {
         this(null, null);
@@ -188,7 +194,7 @@ public class ConfigurationDependencyImpl
     
     @SuppressWarnings({"unchecked", "rawtypes"})
     @Override
-    public void updated(Dictionary settings) throws ConfigurationException {
+    public void updated(final Dictionary settings) throws ConfigurationException {
     	m_updateInvokedCache.set(false);
         Dictionary<String, Object> oldSettings = null;
         synchronized (this) {
@@ -203,11 +209,46 @@ public class ConfigurationDependencyImpl
         // If this is initial settings, or a configuration update, we handle it synchronously.
         // We'll conclude that the dependency is available only if invoking updated did not cause
         // any ConfigurationException.
+        // However, we still want to schedule the event in the component executor, to make sure that the
+        // callback is invoked safely. So, we use a Callable and a FutureTask that allows to handle the 
+        // configuration update through the component executor. We still wait for the result because
+        // in case of any configuration error, we have to return it from the current thread.
+        
+        Callable<ConfigurationException> result = new Callable<ConfigurationException>() {
+            @Override
+            public ConfigurationException call() throws Exception {
+                try {
+                    invokeUpdated(settings); // either the callback instance or the component instances, if available.
+                } catch (ConfigurationException e) {
+                    return e;
+                }
+                return null;
+            }            
+        };
+        
+        // Schedule the configuration update in the component executor. In Normal case, the task is immediately executed.
+        // But in a highly concurrent system, and if the component is being reconfigured, the component may be currently busy
+        // (handling a service dependency event for example), so the task will be enqueued in the component executor, and
+        // we'll wait for the task execution by using a FutureTask:
+        
+        FutureTask<ConfigurationException> ft = new FutureTask<>(result);
+        m_component.getExecutor().execute(ft);
+        
         try {
-            invokeUpdated(settings); // either the callback instance or the component instances, if available.
-        } catch (ConfigurationException e) {
-            logConfigurationException(e);
-            throw e;
+            ConfigurationException confError = ft.get(UPDATE_MAXWAIT, TimeUnit.MILLISECONDS);
+            if (confError != null) {
+                throw confError; // will be logged by the Configuration Admin service;
+            }
+          }
+
+        catch (ExecutionException error) {
+            throw new ConfigurationException(null, "Configuration update error, unexpected exception.", error);
+        } catch (InterruptedException error) {
+            // will be logged by the Configuration Admin service;
+            throw new ConfigurationException(null, "Configuration update interrupted.", error);
+        } catch (TimeoutException error) {
+            // will be logged by the Configuration Admin service;
+            throw new ConfigurationException(null, "Component did not handle configuration update timely.", error);
         }
         
         // At this point, we have accepted the configuration.

Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FilterComponent.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FilterComponent.java?rev=1715707&r1=1715706&r2=1715707&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FilterComponent.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FilterComponent.java Sun Nov 22 21:49:00 2015
@@ -67,6 +67,11 @@ public class FilterComponent implements
     }
     
     @Override
+    public Executor getExecutor() {
+        return m_component.getExecutor();
+    }
+
+    @Override
     public String toString() {
         return m_component.toString();
     }