You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by dj...@apache.org on 2012/10/13 18:15:17 UTC

svn commit: r1397886 - in /felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager: AbstractComponentManager.java ComponentFactoryImpl.java DependencyManager.java ImmediateComponentManager.java

Author: djencks
Date: Sat Oct 13 16:15:16 2012
New Revision: 1397886

URL: http://svn.apache.org/viewvc?rev=1397886&view=rev
Log:
FELIX-3680 change target filter safely.  Target filter is still set too often and size recomputed when filter does not change

Modified:
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java?rev=1397886&r1=1397885&r2=1397886&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java Sat Oct 13 16:15:16 2012
@@ -1057,6 +1057,15 @@ public abstract class AbstractComponentM
         }
     }
 
+    protected void updateTargets(Dictionary properties)
+    {
+        for (Object o: m_dependencyManagers)
+        {
+            DependencyManager dependencyManager = ( DependencyManager ) o;
+            dependencyManager.setTargetFilter( properties );
+        }
+    }
+
     protected boolean verifyDependencyManagers( Dictionary properties )
     {
         // indicates whether all dependencies are satisfied
@@ -1068,7 +1077,7 @@ public abstract class AbstractComponentM
             DependencyManager dm = ( DependencyManager ) it.next();
 
             // ensure the target filter is correctly set
-            dm.setTargetFilter( properties );
+//            dm.setTargetFilter( properties );
 
             if ( !dm.hasGetPermission() )
             {

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java?rev=1397886&r1=1397885&r2=1397886&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java Sat Oct 13 16:15:16 2012
@@ -103,10 +103,11 @@ public class ComponentFactoryImpl extend
         try
         {
             cm.setFactoryProperties( dictionary );
-            cm.reconfigure( m_configuration );
-
-            // enable and activate immediately
+            // enable
             cm.enableInternal();
+            //configure the properties
+            cm.reconfigure( m_configuration );
+            //activate immediately
             cm.activateInternal();
 
             instance = cm.getComponentInstance();

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java?rev=1397886&r1=1397885&r2=1397886&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java Sat Oct 13 16:15:16 2012
@@ -296,6 +296,7 @@ public class DependencyManager implement
                 synchronized ( changes )
                 {
                     changes.remove( ref );
+                    changes.notify();
                 }
             }
             if ( release )
@@ -619,49 +620,14 @@ public class DependencyManager implement
      */
     void enable() throws InvalidSyntaxException
     {
-        // setup the target filter from component descriptor
-        setTargetFilter( m_dependencyMetadata.getTarget() );
-
         if ( hasGetPermission() )
         {
-            // register the service listener
-            String filterString = "(" + Constants.OBJECTCLASS + "=" + m_dependencyMetadata.getInterface() + ")";
-            m_componentManager.getActivator().getBundleContext().addServiceListener( this, filterString );
-
-            synchronized ( enableLock )
-            {
-                // get the current number of registered services available
-                ServiceReference refs[] = getFrameworkServiceReferences();
-                synchronized ( added )
-                {
-                    if (refs != null)
-                    {
-                        for (ServiceReference ref: refs)
-                        {
-                            added.remove( ref );
-                        }
-                    }
-                }
-                synchronized ( removed )
-                {
-                    if (refs != null)
-                    {
-                        for (ServiceReference ref: refs)
-                        {
-                            if (!removed.contains( ref ))
-                            {
-                                removed.remove( ref );
-                            }
-                        }
-                    }
-                }
-                m_size.set( ( refs == null ) ? 0 : refs.length);
-            }
-
+            // setup the target filter from component descriptor
+            setTargetFilter( m_dependencyMetadata.getTarget() );
 
             m_componentManager.log( LogService.LOG_DEBUG,
-                "Registered for service events, currently {0} service(s) match the filter", new Object[]
-                    { new Integer( m_size.get() ) }, null );
+                    "Registered for service events, currently {0} service(s) match the filter", new Object[]
+                    {new Integer( m_size.get() )}, null );
         }
         else
         {
@@ -1483,7 +1449,15 @@ public class DependencyManager implement
      */
     void setTargetFilter( Dictionary properties )
     {
-        setTargetFilter( ( String ) properties.get( m_dependencyMetadata.getTargetPropertyName() ) );
+        try
+        {
+            setTargetFilter( ( String ) properties.get( m_dependencyMetadata.getTargetPropertyName() ) );
+        }
+        catch ( InvalidSyntaxException e )
+        {
+            // this should not occur.  The only choice would be if the filter for the object class was invalid,
+            // but we already set this once when we enabled.
+        }
     }
 
 
@@ -1497,85 +1471,134 @@ public class DependencyManager implement
      * @param target The new target filter to be set. This may be
      *      <code>null</code> if no target filtering is to be used.
      */
-    private void setTargetFilter( String target )
+    private void setTargetFilter( String target ) throws InvalidSyntaxException
     {
         m_componentManager.checkLocked();
         // do nothing if target filter does not change
         if ( ( m_target == null && target == null ) || ( m_target != null && m_target.equals( target ) ) )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "No change in target property for dependency {0}", new Object[]
-                { m_dependencyMetadata.getName() }, null );
-            return;
+                    {m_dependencyMetadata.getName()}, null );
         }
-
-        m_target = target;
-        if ( target != null )
+        else
         {
-            m_componentManager.log( LogService.LOG_DEBUG, "Setting target property for dependency {0} to {1}", new Object[]
-                { m_dependencyMetadata.getName(), target }, null );
-            try
+            m_target = target;
+
+            m_componentManager.getActivator().getBundleContext().removeServiceListener( this );
+            //compute the new target filter while we wait for other threads to complete.
+            if ( target != null )
             {
-                m_targetFilter = m_componentManager.getActivator().getBundleContext().createFilter( target );
+                m_componentManager.log( LogService.LOG_DEBUG, "Setting target property for dependency {0} to {1}", new Object[]
+                        {m_dependencyMetadata.getName(), target}, null );
+                try
+                {
+                    m_targetFilter = m_componentManager.getActivator().getBundleContext().createFilter( target );
+                }
+                catch ( InvalidSyntaxException ise )
+                {
+                    m_componentManager.log( LogService.LOG_ERROR, "Invalid syntax in target property for dependency {0} to {1}", new Object[]
+                            {m_dependencyMetadata.getName(), target}, null );
+                    // log
+                    m_targetFilter = null;
+                }
             }
-            catch ( InvalidSyntaxException ise )
+            else
             {
-                m_componentManager.log( LogService.LOG_ERROR, "Invalid syntax in target property for dependency {0} to {1}", new Object[]
-                    { m_dependencyMetadata.getName(), target }, null );
-                // log
+                m_componentManager.log( LogService.LOG_DEBUG, "Clearing target property for dependency {0}", new Object[]
+                        {m_dependencyMetadata.getName()}, null );
                 m_targetFilter = null;
             }
         }
-        else
+        //wait for events to finish processing
+        synchronized ( added )
         {
-            m_componentManager.log( LogService.LOG_DEBUG, "Clearing target property for dependency {0}", new Object[]
-                { m_dependencyMetadata.getName() }, null );
-            m_targetFilter = null;
+            while ( !added.isEmpty() )
+            {
+                try
+                {
+                    added.wait();
+                }
+                catch ( InterruptedException e )
+                {
+                    //??
+                }
+            }
+        }
+        synchronized ( removed )
+        {
+            while ( !removed.isEmpty() )
+            {
+                try
+                {
+                    removed.wait();
+                }
+                catch ( InterruptedException e )
+                {
+                    //??
+                }
+            }
         }
 
-        if ( m_componentManager.getDependencyMap() != null )
+        //we are now done processing all the events received before we removed the listener.
+        ServiceReference[] boundRefs = getBoundServiceReferences();
+        if ( boundRefs != null && m_targetFilter != null )
         {
-            //component is active, we need to check what might have changed.
-            // check for services to be removed
-            if ( m_targetFilter != null )
+            for ( ServiceReference boundRef : boundRefs )
             {
-                ServiceReference[] refs = getBoundServiceReferences();
-                if ( refs != null )
+                if ( !m_targetFilter.match( boundRef ) )
                 {
-                    for ( int i = 0; i < refs.length; i++ )
-                    {
-                        if ( !m_targetFilter.match( refs[i] ) )
-                        {
-                            // might want to do this asynchronously ??
-                            serviceRemoved( refs[i] );
-                        }
-                    }
+                    serviceRemoved( boundRef );
                 }
             }
         }
+        boolean active = m_componentManager.getDependencyMap() != null;
+        // register the service listener
+        String filterString = "(" + Constants.OBJECTCLASS + "=" + m_dependencyMetadata.getInterface() + ")";
+        m_componentManager.getActivator().getBundleContext().addServiceListener( this, filterString );
+        Collection<ServiceReference> toAdd = new ArrayList<ServiceReference>();
 
-        // check for new services to be added and set the number of
-        // matching services
-        ServiceReference[] refs = getFrameworkServiceReferences();
-        if ( refs != null )
+        synchronized ( enableLock )
         {
-            if ( m_componentManager.getDependencyMap() != null )
+            // get the current number of registered services available
+            ServiceReference refs[] = getFrameworkServiceReferences();
+            if ( refs != null )
             {
-                for ( int i = 0; i < refs.length; i++ )
+                synchronized ( added )
+                {
+                    for ( ServiceReference ref : refs )
+                    {
+                        added.remove( ref );
+                    }
+                }
+                synchronized ( removed )
                 {
-                    if ( getBoundService( refs[i] ) == null )
+                    for ( ServiceReference ref : refs )
                     {
-                        // might want to do this asynchronously ??
-                        serviceAdded( refs[i] );
+                        if ( !removed.contains( ref ) )
+                        {
+                            removed.remove( ref );
+                        }
+                    }
+                }
+                if ( active )
+                {
+                    for ( ServiceReference ref : refs )
+                    {
+                        if ( getBoundService( ref ) == null )
+                        {
+                            toAdd.add( ref );
+                        }
                     }
                 }
             }
-            m_size.set( refs.length );
+            m_size.set( ( refs == null ) ? 0 : refs.length );
         }
-        else
+
+        for ( ServiceReference ref : toAdd )
         {
-            // no services currently match the filter
-            m_size.set( 0 );
+            serviceAdded( ref );
         }
+
     }
 
 

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java?rev=1397886&r1=1397885&r2=1397886&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java Sat Oct 13 16:15:16 2012
@@ -464,6 +464,8 @@ public class ImmediateComponentManager e
         // clear the current properties to force using the configuration data
         m_properties = null;
 
+        updateTargets( getProperties() );
+
         // unsatisfied component and non-ignored configuration may change targets
         // to satisfy references
         if ( getState() == STATE_UNSATISFIED && configuration != null