FELIX-836 Some fixes in asynchronicity of deactivation:
  - deactivate() is always asynchronous
  - reactivation() is always asynchronous
  - add a helper class supporting better loging of asynchronouse tasks

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@741567 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/AbstractComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/AbstractComponentManager.java
index 214f474..6ae1073 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/AbstractComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/AbstractComponentManager.java
@@ -92,7 +92,7 @@
      */
     public final void enable()
     {
-        getActivator().schedule( new Runnable()
+        getActivator().schedule( new ComponentActivatorTask("Enable", this)
         {
             public void run()
             {
@@ -135,7 +135,7 @@
      */
     public final void activate()
     {
-        getActivator().schedule( new Runnable()
+        getActivator().schedule( new ComponentActivatorTask("Activate", this)
         {
             public void run()
             {
@@ -153,43 +153,20 @@
     public final void reconfigure()
     {
         log( LogService.LOG_DEBUG, "Deactivating and Activating to reconfigure", m_componentMetadata, null );
-        reactivateAsynchronous();
+        reactivate();
     }
 
 
     /**
      * Cycles this component by deactivating it and - if still satisfied -
-     * activating it again.
-     * <p>
-     * This method immediately deactivates the component to prevent action
-     * with old configuration/references and schedules the reactivation for
-     * asynchronous execution.
-     */
-    public final void reactivate()
-    {
-        // synchronously deactivate and schedule activation asynchronously
-        deactivate();
-        
-        getActivator().schedule( new Runnable()
-        {
-            public void run()
-            {
-                activateInternal();
-            }
-        } );
-    }
-    
-    
-    /**
-     * Cycles this component by deactivating it and - if still satisfied -
      * activating it again asynchronously.
      * <p>
      * This method schedules the deactivation and reactivation for asynchronous
      * execution.
      */
-    public final void reactivateAsynchronous()
+    public final void reactivate()
     {
-        getActivator().schedule( new Runnable()
+        getActivator().schedule( new ComponentActivatorTask( "Reactivate", this )
         {
             public void run()
             {
@@ -203,40 +180,30 @@
     /**
      * Deactivates the component.
      * <p>
-     * This method unlike other state change methods immediately takes
-     * action and deactivates the component. The reason for this is, that this
-     * method is called when a required service is not available any more and
-     * hence the component cannot work. The exception to this is, that the
-     * deactivation is scheduled for asynchronous execution if the component
-     * is currently activating.
+     * Deactivation of the component happens when a service is unregistered
+     * (or modified). Since such a service change may take place while a bundle
+     * is being stopped and the bundle lock is held, we have to be careful and
+     * schedule the deactivation for asynchronous execution.
      * <p>
-     * We must not immediately deactivate while the component is activating
-     * because we might create a deadlock: If this method is called from the
-     * framework service event thread some locks may be held. If at the same
-     * time the activation tries to access referenced services the framework
-     * lock will be tried to be obtained. On the other hand the activation
-     * holds a lock on this instance and the deactivation tries to get that
-     * lock.
+     * The drawback is, that the user of the removed (or modified) service is
+     * still bound to the old service for a small amount of time and thus may
+     * run into issues. But weighing this against the deadlock possibility, it
+     * is more important to be deadlock save.
+     * <p>
+     * If services have a problem with this delayed deactivation, they should
+     * consider marking the reference as optional and dynamic and be prepared
+     * to the service not being present, since service bind and unbind will
+     * always be synchronous.
      */
     public final void deactivate()
     {
-        if ( getState() == STATE_ACTIVATING )
+        getActivator().schedule( new ComponentActivatorTask( "Deactivate", this )
         {
-            log( LogService.LOG_INFO,
-                "Asynchronously deactivating the component to prevent a deadlock while it is being activated",
-                m_componentMetadata, null );
-            getActivator().schedule( new Runnable()
+            public void run()
             {
-                public void run()
-                {
-                    deactivateInternal();
-                }
-            } );
-        }
-        else
-        {
-            deactivateInternal();
-        }
+                deactivateInternal();
+            }
+        } );
     }
 
 
@@ -248,7 +215,7 @@
      */
     public final void disable()
     {
-        getActivator().schedule( new Runnable()
+        getActivator().schedule( new ComponentActivatorTask("Disable", this)
         {
             public void run()
             {
@@ -831,6 +798,12 @@
     }
 
 
+    public String toString()
+    {
+        return "Component: " + getName() + " (" + getId() + ")";
+    }
+
+
     /**
      * Returns <code>true</code> if this instance has not been disposed off
      * yet and the BundleComponentActivator is still active. If the Bundle
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java b/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
index e5612a9..0a95731 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
@@ -447,7 +447,7 @@
      *
      * @param task The component task to execute
      */
-    void schedule( Runnable task )
+    void schedule( ComponentActivatorTask task )
     {
         if ( isActive() )
         {
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/ComponentActivatorTask.java b/scr/src/main/java/org/apache/felix/scr/impl/ComponentActivatorTask.java
new file mode 100644
index 0000000..f501a6a
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/ComponentActivatorTask.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scr.impl;
+
+
+/**
+ * The <code>ComponentActivatorTask</code> extends the <code>Runnable</code>
+ * interface with the functionality to have a meaningful {@link #toString()}
+ * implementation. This is mainly used when logging something around the task
+ * being run or scheduled.
+ */
+abstract class ComponentActivatorTask implements Runnable
+{
+
+    private final String taskName;
+    private final ComponentManager component;
+
+
+    protected ComponentActivatorTask( String taskName, ComponentManager component )
+    {
+        this.taskName = taskName;
+        this.component = component;
+    }
+
+
+    public String toString()
+    {
+        return taskName + " " + component;
+    }
+}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/ImmediateComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/ImmediateComponentManager.java
index 87583f4..649f8c9 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/ImmediateComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/ImmediateComponentManager.java
@@ -389,7 +389,7 @@
         {
             log( LogService.LOG_DEBUG, "Deactivating and Activating to reconfigure from configuration",
                 getComponentMetadata(), null );
-            reactivateAsynchronous();
+            reactivate();
         }
     }
 }