Skip to content

Commit

Permalink
FELIX-5974 : Prototype scope references are not released on deactivat…
Browse files Browse the repository at this point in the history
…ion. Applied patch from Tim Ward

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1845660 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
cziegeler committed Nov 3, 2018
1 parent b5367f5 commit efdbeeb
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ public class ComponentServiceObjectsHelper

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;
Expand All @@ -65,7 +63,6 @@ public void cleanup()
{
cso.deactivate();
}
prototypeInstances.clear();
}

public ComponentServiceObjects getServiceObjects(final ServiceReference<?> ref)
Expand Down Expand Up @@ -97,24 +94,11 @@ public void closeServiceObjects(final ServiceReference<?> ref) {
}
cso.close();
}
prototypeInstances.remove(ref);
}

public <T> T getPrototypeRefInstance(final ServiceReference<T> ref, ServiceObjects<T> serviceObjects)
public <T> T getPrototypeRefInstance(final ServiceReference<T> ref)
{
T service = (T) prototypeInstances.get(ref);
if ( service == null )
{
service = serviceObjects.getService();
T oldService = (T)prototypeInstances.putIfAbsent(ref, service);
if ( oldService != null )
{
// another thread created the instance already
serviceObjects.ungetService(service);
service = oldService;
}
}
return service;
return (T) getServiceObjects(ref).getService();
}

private static final class ComponentServiceObjectsImpl implements ComponentServiceObjects
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1681,7 +1681,9 @@ void close(ComponentContextImpl<S> componentContext, EdgeInfo edgeInfo)
{
invokeUnbindMethod(componentContext, boundRef, trackingCount.get(), edgeInfo);
}


boundRef.unsetServiceObject(componentContext);

}
latch.countDown();
}
Expand Down Expand Up @@ -2320,9 +2322,9 @@ RefPair<S, T> newRefPair(ServiceReference<T> serviceReference)
}
if (m_componentManager.getComponentMetadata().getServiceScope() == Scope.singleton)
{
return new SinglePrototypeRefPair<>(m_componentManager.getBundleContext(), serviceReference);
return new SinglePrototypeRefPair<>(serviceReference);
}
return new MultiplePrototypeRefPair<>(m_componentManager.getBundleContext(), serviceReference);
return new MultiplePrototypeRefPair<>(serviceReference);
}

private void deactivateComponentManager()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
package org.apache.felix.scr.impl.manager;

import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceObjects;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogService;

Expand All @@ -34,19 +34,11 @@
*/
public class MultiplePrototypeRefPair<S, T> extends RefPair<S, T>
{
private final ServiceObjects<T> serviceObjects;
private final ConcurrentMap<ComponentContextImpl<S>, T> instances = new ConcurrentHashMap<>();

public MultiplePrototypeRefPair( BundleContext context, ServiceReference<T> ref )
public MultiplePrototypeRefPair( ServiceReference<T> ref )
{
super(ref);
this.serviceObjects = context.getServiceObjects(ref);
}

@Override
public ServiceObjects<T> getServiceObjects()
{
return serviceObjects;
}

@Override
Expand All @@ -58,30 +50,28 @@ public T getServiceObject(ComponentContextImpl<S> key)
@Override
public boolean setServiceObject(ComponentContextImpl<S> key, T serviceObject)
{
return instances.putIfAbsent(key, serviceObject) == null;
return instances.putIfAbsent( key, serviceObject ) == null;
}

@Override
public T unsetServiceObject(ComponentContextImpl<S> key)
{
if ( key == null )
{
try
final Iterator<Entry<ComponentContextImpl<S>, T>> iter = instances.entrySet().iterator();
while ( iter.hasNext() )
{
final Iterator<T> iter = instances.values().iterator();
while ( iter.hasNext() )
{
this.serviceObjects.ungetService(iter.next());
}
}
catch (final IllegalStateException ise)
{
// ignore
}
Entry<ComponentContextImpl<S>, T> e = iter.next();
doUngetService( e.getKey(), e.getValue() );
}
instances.clear();
return null ;
}
return instances.remove(key);
T service = instances.remove( key );
if(service != null) {
doUngetService( key, service );
}
return service;
}

@Override
Expand All @@ -93,7 +83,7 @@ public String toString()
@Override
public boolean getServiceObject(ComponentContextImpl<S> key, BundleContext context)
{
final T service = key.getComponentServiceObjectsHelper().getPrototypeRefInstance(this.getRef(), serviceObjects);
final T service = key.getComponentServiceObjectsHelper().getPrototypeRefInstance(this.getRef());
if ( service == null )
{
setFailed();
Expand All @@ -105,8 +95,19 @@ public boolean getServiceObject(ComponentContextImpl<S> key, BundleContext conte
if (!setServiceObject(key, service))
{
// Another thread got the service before, so unget our
serviceObjects.ungetService( service );
doUngetService( key, service );
}
return true;
}

private void doUngetService(ComponentContextImpl<S> key, final T service) {
try
{
key.getComponentServiceObjectsHelper().getServiceObjects(getRef()).ungetService( service );
}
catch ( final IllegalStateException ise )
{
// ignore
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,6 @@ public ServiceReference<T> getRef()
return ref;
}

public ServiceObjects<T> getServiceObjects()
{
return null;
}

public abstract boolean getServiceObject( ComponentContextImpl<S> key, BundleContext context );

public abstract T getServiceObject(ComponentContextImpl<S> key);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
package org.apache.felix.scr.impl.manager;

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceObjects;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogService;

Expand All @@ -30,18 +29,9 @@
*/
public class SinglePrototypeRefPair<S, T> extends SingleRefPair<S, T>
{
private final ServiceObjects<T> serviceObjects;

public SinglePrototypeRefPair( BundleContext context, ServiceReference<T> ref )
public SinglePrototypeRefPair( ServiceReference<T> ref )
{
super(ref);
this.serviceObjects = context.getServiceObjects(ref);
}

@Override
public ServiceObjects<T> getServiceObjects()
{
return serviceObjects;
}

@Override
Expand All @@ -53,7 +43,7 @@ public String toString()
@Override
public boolean getServiceObject(ComponentContextImpl<S> key, BundleContext context)
{
final T service = key.getComponentServiceObjectsHelper().getPrototypeRefInstance(this.getRef(), serviceObjects);
final T service = key.getComponentServiceObjectsHelper().getPrototypeRefInstance(this.getRef());
if ( service == null )
{
setFailed();
Expand All @@ -65,9 +55,31 @@ public boolean getServiceObject(ComponentContextImpl<S> key, BundleContext conte
if (!setServiceObject(key, service))
{
// Another thread got the service before, so unget our
serviceObjects.ungetService( 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);
}
catch (final IllegalStateException ise)
{
// ignore
}
}

}

0 comments on commit efdbeeb

Please sign in to comment.