You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by tj...@apache.org on 2019/02/05 16:23:06 UTC

svn commit: r1853021 - in /felix/trunk/scr/src/main/java/org/apache/felix/scr/impl: helper/ manager/

Author: tjwatson
Date: Tue Feb  5 16:23:06 2019
New Revision: 1853021

URL: http://svn.apache.org/viewvc?rev=1853021&view=rev
Log:
FELIX-6044 - Fixes for maintaining correct reference usage

 - unget non-prototype service refs
 - avoid creating multiple prototype instances for same component

Modified:
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ComponentServiceObjectsHelper.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/MultiplePrototypeRefPair.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/RefPair.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SinglePrototypeRefPair.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleRefPair.java

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ComponentServiceObjectsHelper.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ComponentServiceObjectsHelper.java?rev=1853021&r1=1853020&r2=1853021&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ComponentServiceObjectsHelper.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ComponentServiceObjectsHelper.java Tue Feb  5 16:23:06 2019
@@ -41,6 +41,8 @@ public class ComponentServiceObjectsHelp
 
     private final List<ComponentServiceObjectsImpl> closedServices = new ArrayList<ComponentServiceObjectsImpl>();
 
+    private final ConcurrentMap<ServiceReference<?>, Object> prototypeInstances = new ConcurrentHashMap<ServiceReference<?>, Object>();
+
     public ComponentServiceObjectsHelper(final BundleContext bundleContext)
     {
         this.bundleContext = bundleContext;
@@ -63,6 +65,7 @@ public class ComponentServiceObjectsHelp
         {
         	cso.deactivate();
         }
+        prototypeInstances.clear();
     }
 
     public ComponentServiceObjects getServiceObjects(final ServiceReference<?> ref)
@@ -98,7 +101,19 @@ public class ComponentServiceObjectsHelp
 
     public <T> T getPrototypeRefInstance(final ServiceReference<T> ref)
     {
-    	return (T) getServiceObjects(ref).getService();
+    	T service = (T) prototypeInstances.get(ref);
+    	if ( service == null )
+    	{
+    		service = (T) getServiceObjects(ref).getService();
+    		T oldService = (T)prototypeInstances.putIfAbsent(ref, service);
+    		if ( oldService != null )
+    		{
+    			// another thread created the instance already
+    			getServiceObjects(ref).ungetService(service);
+    			service = oldService;
+    		}
+    	}
+    	return service;
     }
 
     private static final class ComponentServiceObjectsImpl implements ComponentServiceObjects

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=1853021&r1=1853020&r2=1853021&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 Tue Feb  5 16:23:06 2019
@@ -223,15 +223,7 @@ public class DependencyManager<S, T> imp
 
         protected void ungetService(RefPair<S, T> ref)
         {
-            Object service = ref.unsetServiceObject(null);
-            if (service != null)
-            {
-                BundleContext bundleContext = m_componentManager.getBundleContext();
-                if (bundleContext != null)
-                {
-                    bundleContext.ungetService(ref.getRef());
-                }
-            }
+            ref.ungetServiceObjects(m_componentManager.getBundleContext());
         }
 
         protected void tracked(int trackingCount)
@@ -1690,7 +1682,7 @@ public class DependencyManager<S, T> imp
                 invokeUnbindMethod(componentContext, boundRef, trackingCount.get(), edgeInfo);
             }
             
-            boundRef.unsetServiceObject(componentContext);
+            boundRef.ungetServiceObject(componentContext);
             
         }
         latch.countDown();

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/MultiplePrototypeRefPair.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/MultiplePrototypeRefPair.java?rev=1853021&r1=1853020&r2=1853021&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/MultiplePrototypeRefPair.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/MultiplePrototypeRefPair.java Tue Feb  5 16:23:06 2019
@@ -54,7 +54,7 @@ public class MultiplePrototypeRefPair<S,
     }
 
     @Override
-    public T unsetServiceObject(ComponentContextImpl<S> key)
+    public T ungetServiceObject(ComponentContextImpl<S> key)
     {
     	if ( key == null )
     	{
@@ -75,6 +75,11 @@ public class MultiplePrototypeRefPair<S,
     }
 
     @Override
+    public void ungetServiceObjects(BundleContext bundleContext) {
+        ungetServiceObject(null);
+    }
+
+    @Override
     public String toString()
     {
         return "[MultiplePrototypeRefPair: ref: [" + getRef() + "] has service: [" + !instances.isEmpty() + "]]";
@@ -83,7 +88,7 @@ public class MultiplePrototypeRefPair<S,
     @Override
     public boolean getServiceObject(ComponentContextImpl<S> key, BundleContext context)
     {
-    	final T service = key.getComponentServiceObjectsHelper().getPrototypeRefInstance(this.getRef());
+        final T service = key.getComponentServiceObjectsHelper().getPrototypeRefInstance(this.getRef());
         if ( service == null )
         {
             setFailed();

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/RefPair.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/RefPair.java?rev=1853021&r1=1853020&r2=1853021&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/RefPair.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/RefPair.java Tue Feb  5 16:23:06 2019
@@ -50,7 +50,8 @@ public abstract class RefPair<S, T>
 
     public abstract boolean setServiceObject( ComponentContextImpl<S> key, T serviceObject );
 
-    public abstract T unsetServiceObject(ComponentContextImpl<S> key);
+    public abstract void ungetServiceObjects(BundleContext context);
+    public abstract T ungetServiceObject(ComponentContextImpl<S> key);
 
     public void setFailed( )
     {

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java?rev=1853021&r1=1853020&r2=1853021&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java Tue Feb  5 16:23:06 2019
@@ -161,7 +161,6 @@ public class SingleComponentManager<S> e
         {
             m_useCount.set( 0 );
             disposeImplementationObject( m_componentContext, reason );
-            m_componentContext.cleanup();
             m_componentContext = null;
             getLogger().log( LogService.LOG_DEBUG, "Unset and deconfigured implementation object for component in deleteComponent for reason {0}", null, REASONS[ reason ] );
             clearServiceProperties();
@@ -417,7 +416,7 @@ public class SingleComponentManager<S> e
                 md.close( componentContext, componentContext.getEdgeInfo( md ) );
             }
         }
-
+        componentContext.cleanup();
     }
 
     @Override

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SinglePrototypeRefPair.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SinglePrototypeRefPair.java?rev=1853021&r1=1853020&r2=1853021&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SinglePrototypeRefPair.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SinglePrototypeRefPair.java Tue Feb  5 16:23:06 2019
@@ -20,6 +20,8 @@
 
 package org.apache.felix.scr.impl.manager;
 
+import java.util.concurrent.atomic.AtomicReference;
+
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.log.LogService;
@@ -27,14 +29,56 @@ import org.osgi.service.log.LogService;
 /**
  * @version $Rev$ $Date$
  */
-public class SinglePrototypeRefPair<S, T> extends SingleRefPair<S, T>
+public class SinglePrototypeRefPair<S, T> extends RefPair<S, T>
 {
+    class SingleKeyService {
+        final ComponentContextImpl<S> key;
+        final T serviceObject;
+        SingleKeyService(ComponentContextImpl<S> key, T serviceObject) {
+            this.key = key;
+            this.serviceObject = serviceObject;
+        }
+    }
+    protected AtomicReference<SingleKeyService> serviceObjectRef = new AtomicReference<>();
+
     public SinglePrototypeRefPair( ServiceReference<T> ref )
     {
         super(ref);
     }
 
     @Override
+    public T getServiceObject(ComponentContextImpl<S> key)
+    {
+        SingleKeyService service = serviceObjectRef.get();
+        return service == null ? null : service.serviceObject;
+    }
+
+    @Override
+    public boolean setServiceObject(ComponentContextImpl<S> key, T serviceObject)
+    {
+        return serviceObjectRef.compareAndSet(null, new SingleKeyService(key, serviceObject ));
+    }
+
+    @Override
+    public T ungetServiceObject(ComponentContextImpl<S> key)
+    {
+        SingleKeyService service = serviceObjectRef.getAndSet(null);
+        if (service != null) {
+            if (key == null) {
+                key = service.key;
+            }
+            doUngetService(key, service.serviceObject);
+            return service.serviceObject;
+        }
+		return null;
+    }
+
+    @Override
+    public void ungetServiceObjects(BundleContext bundleContext) {
+        ungetServiceObject(null);
+    }
+
+    @Override
     public String toString()
     {
         return "[SinglePrototypeRefPair: ref: [" + getRef() + "] service: [" + getServiceObject(null) + "]]";
@@ -49,37 +93,25 @@ public class SinglePrototypeRefPair<S, T
             setFailed();
             key.getLogger().log(
                  LogService.LOG_WARNING,
-                 "Could not get service from serviceobjects for ref {0}",null, getRef() );
+                 "Could not get service from serviceobjects for ref {0}", null, getRef() );
             return false;
         }
         if (!setServiceObject(key, service))
         {
             // Another thread got the service before, so unget our
-        	doUngetService(key, service);
+        	doUngetService( key, service );
         }
         return true;
     }
 
-    @Override
-    public T unsetServiceObject(ComponentContextImpl<S> key)
-    {
-    	final T service = super.unsetServiceObject(key);
-    	if ( service != null )
-    	{
-			doUngetService(key, service);
-    	}
-    	return null ;
-    }
-
 	private void doUngetService(ComponentContextImpl<S> key, final T service) {
 		try 
 		{
-			key.getComponentServiceObjectsHelper().getServiceObjects(getRef()).ungetService(service);
+			key.getComponentServiceObjectsHelper().getServiceObjects(getRef()).ungetService( service );
 		}
-		catch (final IllegalStateException ise)
+		catch ( final IllegalStateException ise )
 		{
 			// ignore
 		}
 	}
-    
 }

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleRefPair.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleRefPair.java?rev=1853021&r1=1853020&r2=1853021&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleRefPair.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleRefPair.java Tue Feb  5 16:23:06 2019
@@ -31,7 +31,7 @@ import org.osgi.service.log.LogService;
  */
 public class SingleRefPair<S, T> extends RefPair<S, T>
 {
-    private AtomicReference<T> serviceObjectRef = new AtomicReference<>();
+    protected AtomicReference<T> serviceObjectRef = new AtomicReference<>();
 
     public SingleRefPair( ServiceReference<T> ref )
     {
@@ -56,9 +56,22 @@ public class SingleRefPair<S, T> extends
     }
 
     @Override
-    public T unsetServiceObject(ComponentContextImpl<S> key)
+    public T ungetServiceObject(ComponentContextImpl<S> key) {
+        // null operation for singleRefPair
+        return null;
+    }
+
+    @Override
+    public void ungetServiceObjects(BundleContext bundleContext)
     {
-        return serviceObjectRef.getAndSet( null );
+        T service = serviceObjectRef.getAndSet( null );
+        if (service != null)
+        {
+            if (bundleContext != null)
+            {
+                bundleContext.ungetService(getRef());
+            }
+        }
     }
 
     @Override