You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by cu...@apache.org on 2012/07/21 15:49:06 UTC

svn commit: r1364094 - in /aries/trunk/blueprint: blueprint-cm/src/main/java/org/apache/aries/blueprint/compendium/cm/CmManagedServiceFactory.java blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/TestConfigAdmin.java

Author: cumminsh
Date: Sat Jul 21 13:49:05 2012
New Revision: 1364094

URL: http://svn.apache.org/viewvc?rev=1364094&view=rev
Log:
[ARIES-584] Go synchronized through most of the updated() method on the service factory to make sure we don't risk two services with the same pid, and a bit of extra testing

Modified:
    aries/trunk/blueprint/blueprint-cm/src/main/java/org/apache/aries/blueprint/compendium/cm/CmManagedServiceFactory.java
    aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/TestConfigAdmin.java

Modified: aries/trunk/blueprint/blueprint-cm/src/main/java/org/apache/aries/blueprint/compendium/cm/CmManagedServiceFactory.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-cm/src/main/java/org/apache/aries/blueprint/compendium/cm/CmManagedServiceFactory.java?rev=1364094&r1=1364093&r2=1364094&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-cm/src/main/java/org/apache/aries/blueprint/compendium/cm/CmManagedServiceFactory.java (original)
+++ aries/trunk/blueprint/blueprint-cm/src/main/java/org/apache/aries/blueprint/compendium/cm/CmManagedServiceFactory.java Sat Jul 21 13:49:05 2012
@@ -76,8 +76,8 @@ public class CmManagedServiceFactory {
     private final Object lock = new Object();
 
     private ServiceRegistration registration;
-    private Map<String, ServiceRegistration> pids = new ConcurrentHashMap<String, ServiceRegistration>();
-    private Map<ServiceRegistration, Object> services = new ConcurrentHashMap<ServiceRegistration, Object>();
+    private final Map<String, ServiceRegistration> pids = new ConcurrentHashMap<String, ServiceRegistration>();
+    private final Map<ServiceRegistration, Object> services = new ConcurrentHashMap<ServiceRegistration, Object>();
 
     public void init() throws Exception {
         LOGGER.debug("Initializing CmManagedServiceFactory for factoryPid={}", factoryPid);
@@ -170,33 +170,46 @@ public class CmManagedServiceFactory {
     }
     
     protected void updated(String pid, Dictionary props) {
-        LOGGER.debug("Updated configuration {} with props {}", pid, props);
-        ServiceRegistration reg = pids.get(pid);
-        if (reg == null) {      
+      LOGGER.debug("Updated configuration {} with props {}", pid, props);
+
+      Hashtable regProps = null;
+      Object component = null;
+
+      // This method might be multithreaded, so synchronize checking and
+      // creating the service
+      final ServiceRegistration existingReg;
+      synchronized (pids) {
+         existingReg = pids.get(pid);
+         if (existingReg == null) {
             updateComponentProperties(props);
 
-            Object component = blueprintContainer.getComponentInstance(managedComponentName);
-            
-            //  TODO: call listeners, etc...
-                    
-            Hashtable regProps = getRegistrationProperties(pid);            
+            component = blueprintContainer.getComponentInstance(managedComponentName);
+
+            // TODO: call listeners, etc...
+
+            regProps = getRegistrationProperties(pid);
             CmProperties cm = findServiceProcessor();
             if (cm != null) {
-                if ("".equals(cm.getPersistentId())) {
-                    JavaUtils.copy(regProps, props);
-                }
-                cm.updateProperties(new PropertiesUpdater(pid), regProps);
+               if ("".equals(cm.getPersistentId())) {
+                  JavaUtils.copy(regProps, props);
+               }
+               cm.updateProperties(new PropertiesUpdater(pid), regProps);
             }
-            
+
             Set<String> classes = getClasses(component);
             String[] classArray = classes.toArray(new String[classes.size()]);
-            reg = blueprintContainer.getBundleContext().registerService(classArray, component, regProps);
+            ServiceRegistration reg = blueprintContainer.getBundleContext().registerService(classArray, component, regProps);
+
+            LOGGER.debug("Service {} registered with interfaces {} and properties {}", new Object[] { component, classes, regProps });
 
-            LOGGER.debug("Service {} registered with interfaces {} and properties {}", new Object [] { component, classes, regProps });
-            
             services.put(reg, component);
             pids.put(pid, reg);
-            
+         }
+        } // end of synchronization
+        
+        // If we just registered a service, do the slower stuff outside the synchronized block
+        if (existingReg == null)
+        {
             if (listeners != null) {
                 for (ServiceListener listener : listeners) {
                     listener.register(component, regProps);
@@ -207,7 +220,7 @@ public class CmManagedServiceFactory {
             
             CmProperties cm = findServiceProcessor();
             if (cm != null && "".equals(cm.getPersistentId())) {
-                Dictionary regProps = getRegistrationProperties(pid);    
+                regProps = getRegistrationProperties(pid);    
                 JavaUtils.copy(regProps, props);
                 cm.updated(regProps);
             }

Modified: aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/TestConfigAdmin.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/TestConfigAdmin.java?rev=1364094&r1=1364093&r2=1364094&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/TestConfigAdmin.java (original)
+++ aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/TestConfigAdmin.java Sat Jul 21 13:49:05 2012
@@ -31,6 +31,7 @@ import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.JUnit4TestRunner;
 import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
 import org.osgi.service.blueprint.container.BlueprintContainer;
 import org.osgi.service.cm.Configuration;
 import org.osgi.service.cm.ConfigurationAdmin;
@@ -145,21 +146,29 @@ public class TestConfigAdmin extends Abs
 
     @Test
     public void testManagedServiceFactory() throws Exception {
+
         ConfigurationAdmin ca = context().getService(ConfigurationAdmin.class);
         Configuration cf = ca.createFactoryConfiguration("blueprint-sample-managed-service-factory", null);
         Hashtable<String,String> props = new Hashtable<String,String>();
         props.put("a", "5");
         props.put("currency", "PLN");
         cf.update(props);
-
+        
         Bundle bundle = context().getBundleByName("org.apache.aries.blueprint.sample");
         assertNotNull(bundle);
         bundle.start();
-
+        
         BlueprintContainer blueprintContainer = Helper.getBlueprintContainerForBundle(context(), "org.apache.aries.blueprint.sample");
         assertNotNull(blueprintContainer);
+        
+        // Make sure only one service is registered
+        // Ask the service registry, not the container, since the container might have got it wrong :)
+        ServiceReference[] refs = context().getAllServiceReferences(Foo.class.getName(), "(service.pid=blueprint-sample-managed-service-factory.*)");
+        
+        assertNotNull("No services were registered for the managed service factory", refs);
+        assertEquals("Multiple services were registered for the same pid.", 1, refs.length);
+        
 
-        Thread.sleep(5000);
     }
 
     @org.ops4j.pax.exam.junit.Configuration