Author: djencks
Date: Wed Mar  6 02:51:04 2013
New Revision: 1453150

URL: http://svn.apache.org/r1453150
Log:
FELIX-3891 wait a while for concurrent registration/unregistration requests to 
complete

Modified:
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/RegistrationManager.java
    
felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/manager/RegistrationManagerTest.java

Modified: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java?rev=1453150&r1=1453149&r2=1453150&view=diff
==============================================================================
--- 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
 (original)
+++ 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
 Wed Mar  6 02:51:04 2013
@@ -174,7 +174,7 @@ public abstract class AbstractComponentM
     {
         try
         {
-            if (!m_stateLock.tryLock( 
getActivator().getConfiguration().lockTimeout(), TimeUnit.MILLISECONDS ) )
+            if (!m_stateLock.tryLock( getLockTimeout(), TimeUnit.MILLISECONDS 
) )
             {
                dumpThreads();
                 throw new IllegalStateException( "Could not obtain lock" );
@@ -187,6 +187,11 @@ public abstract class AbstractComponentM
         }
     }
 
+    private long getLockTimeout()
+    {
+        return getActivator().getConfiguration().lockTimeout();
+    }
+
     final void releaseWriteLock( String source )
     {
         m_stateLock.unlock();
@@ -720,6 +725,12 @@ public abstract class AbstractComponentM
         {
             AbstractComponentManager.this.log(level, message, arguments, ex);
         }
+
+        @Override
+        long getTimeout()
+        {
+            return getLockTimeout();
+        }
         
     };
     

Modified: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/RegistrationManager.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/RegistrationManager.java?rev=1453150&r1=1453149&r2=1453150&view=diff
==============================================================================
--- 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/RegistrationManager.java
 (original)
+++ 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/RegistrationManager.java
 Wed Mar  6 02:51:04 2013
@@ -3,6 +3,8 @@ package org.apache.felix.scr.impl.manage
 import java.util.ArrayList;
 import java.util.Dictionary;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
@@ -11,9 +13,40 @@ import org.osgi.service.log.LogService;
 abstract class RegistrationManager<T>
 {
     enum RegState {unregistered, registered};
+    private static class RegStateWrapper 
+    {
+        private final CountDownLatch latch = new CountDownLatch(1);
+        private final RegState regState;
+        
+        RegStateWrapper( RegState regState )
+        {
+            this.regState = regState;
+        }
+        
+        public RegState getRegState()
+        {
+            return regState;
+        }
+        
+        public CountDownLatch getLatch()
+        {
+            return latch;
+        }
+        
+        public int hashCode()
+        {
+            return regState.hashCode();
+        }
+        
+        public boolean equals(Object other)
+        {
+            return other instanceof RegStateWrapper && regState == 
((RegStateWrapper)other).getRegState();
+        }
+        
+    }
     private final Lock registrationLock = new ReentrantLock();
     //Deque, ArrayDeque if we had java 6
-    private final List<RegState> opqueue = new ArrayList<RegState>();
+    private final List<RegStateWrapper> opqueue = new 
ArrayList<RegStateWrapper>();
 
     private volatile T m_serviceRegistration;
     /**
@@ -24,6 +57,7 @@ abstract class RegistrationManager<T>
      */
     boolean changeRegistration( RegState desired, String[] services )
     {
+        RegStateWrapper rsw = null;
         registrationLock.lock();
         try
         {
@@ -34,11 +68,13 @@ abstract class RegistrationManager<T>
                     return false; //already in desired state
                 }
             }
-            else if (opqueue.get( opqueue.size() - 1 ) == desired)
+            else if (opqueue.get( opqueue.size() - 1 ).getRegState() == 
desired)
             {
+                rsw = opqueue.get( opqueue.size() - 1 );
                 return false; //another thread will do our work.
             }
-            opqueue.add( desired );
+            rsw = new RegStateWrapper( desired );
+            opqueue.add( rsw );
             if (opqueue.size() > 1)
             {
                 return false; //some other thread will do it later
@@ -48,9 +84,9 @@ abstract class RegistrationManager<T>
             {
                 log( LogService.LOG_DEBUG, "registration change queue {0}", 
new Object[]
                         {opqueue}, null );
-                desired = opqueue.get( 0 );
+                RegStateWrapper next = opqueue.get( 0 );
                 T serviceRegistration = m_serviceRegistration;
-                if ( desired == RegState.unregistered)
+                if ( next.getRegState() == RegState.unregistered)
                 {
                     m_serviceRegistration = null;
                 }
@@ -58,7 +94,7 @@ abstract class RegistrationManager<T>
                 registrationLock.unlock();
                 try
                 {
-                    if (desired == RegState.registered)
+                    if (next.getRegState() == RegState.registered)
                     {
                         serviceRegistration = register(services );
 
@@ -81,10 +117,11 @@ abstract class RegistrationManager<T>
                 {
                     registrationLock.lock();
                     opqueue.remove(0);
-                    if ( desired == RegState.registered)
+                    if ( next.getRegState() == RegState.registered)
                     {
                         m_serviceRegistration = serviceRegistration;
                     }
+                    next.getLatch().countDown();
                 }
             }
             while (!opqueue.isEmpty());
@@ -93,6 +130,22 @@ abstract class RegistrationManager<T>
         finally
         {
             registrationLock.unlock();
+            if (rsw != null)
+            {
+                try
+                {
+                    if ( !rsw.getLatch().await( getTimeout(), 
TimeUnit.MILLISECONDS ))
+                    {
+                        log( LogService.LOG_ERROR, "Timeout waiting for reg 
change to complete {0}", new Object[]
+                                {rsw.getRegState()}, null);
+                    }
+                }
+                catch ( InterruptedException e )
+                {
+                    log( LogService.LOG_ERROR, "Interrupted exception waiting 
for reg change to complete {0}", new Object[]
+                            {rsw.getRegState()}, null);
+                }
+            }
         }
 
     }
@@ -103,6 +156,8 @@ abstract class RegistrationManager<T>
     
     abstract void log( int level, String message, Object[] arguments, 
Throwable ex );
     
+    abstract long getTimeout();
+    
     T getServiceRegistration()
     {
         return m_serviceRegistration;

Modified: 
felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/manager/RegistrationManagerTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/manager/RegistrationManagerTest.java?rev=1453150&r1=1453149&r2=1453150&view=diff
==============================================================================
--- 
felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/manager/RegistrationManagerTest.java
 (original)
+++ 
felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/manager/RegistrationManagerTest.java
 Wed Mar  6 02:51:04 2013
@@ -108,6 +108,13 @@ public class RegistrationManagerTest
             }
             
         }
+
+        @Override
+        long getTimeout()
+        {
+            // TODO Auto-generated method stub
+            return 10;
+        }
         
     }
 }


Reply via email to