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() );
             }
         }
     }