FELIX-2370 For the delayed component manager replace set of using bundles by a simple counter and a simple lock; The set of bundles is not used and thus just overhead. For the service factory manager, synchronize access to the map. Additionally make two fields final in the AbstractComponentManager.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@949401 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
index 3a33e50..588d035 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
@@ -58,10 +58,10 @@
private volatile State m_state;
// The metadata
- private ComponentMetadata m_componentMetadata;
+ private final ComponentMetadata m_componentMetadata;
// The dependency managers that manage every dependency
- private List m_dependencyManagers;
+ private final List m_dependencyManagers;
// A reference to the BundleComponentActivator
private BundleComponentActivator m_activator;
@@ -85,7 +85,7 @@
m_componentId = ( activator != null ) ? activator.registerComponentId( this ) : -1;
m_state = Disabled.getInstance();
- loadDependencyManagers( metadata );
+ m_dependencyManagers = loadDependencyManagers( metadata );
// dump component details
if ( isLogEnabled( LogService.LOG_DEBUG ) )
@@ -546,9 +546,9 @@
}
- private void loadDependencyManagers( ComponentMetadata metadata )
+ private List loadDependencyManagers( ComponentMetadata metadata )
{
- List depMgrList = new ArrayList();
+ List depMgrList = new ArrayList(metadata.getDependencies().size());
// If this component has got dependencies, create dependency managers for each one of them.
if ( metadata.getDependencies().size() != 0 )
@@ -565,7 +565,7 @@
}
}
- m_dependencyManagers = depMgrList;
+ return depMgrList;
}
private void enableDependencyManagers() throws InvalidSyntaxException
@@ -1123,6 +1123,10 @@
return dcm.getInstance();
}
+ // log that the delayed component cannot be created (we don't
+ // know why at this moment; this should already have been logged)
+ dcm.log( LogService.LOG_ERROR, "Failed creating the component instance; see log for reason", null );
+
// component could not really be created. This may be temporary
// so we stay in the registered state but ensure the component
// instance is deleted
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/DelayedComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/DelayedComponentManager.java
index ab35ad2..ba8a1a8 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/DelayedComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/DelayedComponentManager.java
@@ -19,9 +19,6 @@
package org.apache.felix.scr.impl.manager;
-import java.util.HashSet;
-import java.util.Set;
-
import org.apache.felix.scr.impl.BundleComponentActivator;
import org.apache.felix.scr.impl.config.ComponentHolder;
import org.apache.felix.scr.impl.metadata.ComponentMetadata;
@@ -37,7 +34,9 @@
{
// keep the using bundles as reference "counters" for instance deactivation
- private final Set m_usingBundles = new HashSet();
+ private final Object m_useCountLock;
+ private int m_useCount;
+
/**
* @param activator
@@ -47,6 +46,8 @@
ComponentMetadata metadata )
{
super( activator, componentHolder, metadata );
+ this.m_useCountLock = new Object();
+ this.m_useCount = 0;
}
@@ -67,7 +68,7 @@
}
// ensure the refence set is also clear
- m_usingBundles.clear();
+ m_useCount = 0;
}
@@ -81,8 +82,11 @@
public synchronized Object getService( Bundle bundle, ServiceRegistration sr )
{
- m_usingBundles.add(bundle);
- return state().getService( this );
+ synchronized ( m_useCountLock )
+ {
+ m_useCount++;
+ return state().getService( this );
+ }
}
@@ -94,10 +98,21 @@
public void ungetService( Bundle bundle, ServiceRegistration sr, Object service )
{
- m_usingBundles.remove( bundle );
- if ( m_usingBundles.isEmpty() )
+ synchronized ( m_useCountLock )
{
- state().ungetService( this );
+ // the framework should not call ungetService more than it calls
+ // calls getService. Still, we want to be sure to not go below zero
+ if ( m_useCount > 0 )
+ {
+ m_useCount--;
+
+ // unget the service instance if no bundle is using it
+ // any longer
+ if ( m_useCount == 0 )
+ {
+ state().ungetService( this );
+ }
+ }
}
}
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
index 340f160..9243aca 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
@@ -108,20 +108,24 @@
if ( service != null )
{
serviceContext.setImplementationObject( service );
- serviceContexts.put( service, serviceContext );
- // if this is the first use of this component, switch to ACTIVE state
- if ( getState() == STATE_REGISTERED )
+ synchronized ( serviceContexts )
{
- synchronized ( this )
+ serviceContexts.put( service, serviceContext );
+
+ // if this is the first use of this component, switch to ACTIVE state
+ if ( getState() == STATE_REGISTERED )
{
- if ( getState() == STATE_REGISTERED )
- {
- changeState( Active.getInstance() );
- }
+ changeState( Active.getInstance() );
}
}
}
+ else
+ {
+ // log that the service factory component cannot be created (we don't
+ // know why at this moment; this should already have been logged)
+ log( LogService.LOG_ERROR, "Failed creating the component instance; see log for reason", null );
+ }
return service;
}
@@ -137,21 +141,20 @@
// When the ungetServiceMethod is called, the implementation object must be deactivated
// private ComponentContext and implementation instances
- ComponentContext serviceContext = ( ComponentContext ) serviceContexts.remove( service );
+ final ComponentContext serviceContext;
+ synchronized ( serviceContexts )
+ {
+ serviceContext = ( ComponentContext ) serviceContexts.remove( service );
+ }
+
disposeImplementationObject( service, serviceContext, ComponentConstants.DEACTIVATION_REASON_DISPOSED );
// if this was the last use of the component, go back to REGISTERED state
- if ( serviceContexts.isEmpty() )
+ synchronized ( serviceContexts )
{
- if ( getState() == STATE_ACTIVE )
+ if ( serviceContexts.isEmpty() && getState() == STATE_ACTIVE )
{
- synchronized ( this )
- {
- if ( getState() == STATE_ACTIVE )
- {
- changeState( Registered.getInstance() );
- }
- }
+ changeState( Registered.getInstance() );
}
}
}