You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2018/01/23 20:54:27 UTC

svn commit: r1822055 - in /felix/trunk/osgi-r7/configadmin/src: main/java/org/apache/felix/cm/impl/persistence/ test/java/org/apache/felix/cm/ test/java/org/apache/felix/cm/impl/

Author: cziegeler
Date: Tue Jan 23 20:54:27 2018
New Revision: 1822055

URL: http://svn.apache.org/viewvc?rev=1822055&view=rev
Log:
FELIX-5776 : Memory Leak by Config Admin. Adding basic test for factory configs

Modified:
    felix/trunk/osgi-r7/configadmin/src/main/java/org/apache/felix/cm/impl/persistence/CachingPersistenceManagerProxy.java
    felix/trunk/osgi-r7/configadmin/src/test/java/org/apache/felix/cm/MockNotCachablePersistenceManager.java
    felix/trunk/osgi-r7/configadmin/src/test/java/org/apache/felix/cm/impl/ConfigurationManagerTest.java

Modified: felix/trunk/osgi-r7/configadmin/src/main/java/org/apache/felix/cm/impl/persistence/CachingPersistenceManagerProxy.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/configadmin/src/main/java/org/apache/felix/cm/impl/persistence/CachingPersistenceManagerProxy.java?rev=1822055&r1=1822054&r2=1822055&view=diff
==============================================================================
--- felix/trunk/osgi-r7/configadmin/src/main/java/org/apache/felix/cm/impl/persistence/CachingPersistenceManagerProxy.java (original)
+++ felix/trunk/osgi-r7/configadmin/src/main/java/org/apache/felix/cm/impl/persistence/CachingPersistenceManagerProxy.java Tue Jan 23 20:54:27 2018
@@ -70,7 +70,7 @@ public class CachingPersistenceManagerPr
     public CachingPersistenceManagerProxy( final PersistenceManager pm )
     {
         this.pm = pm;
-        this.cache = new Hashtable<String, CaseInsensitiveDictionary>();
+        this.cache = new Hashtable<>();
     }
 
     @Override
@@ -125,7 +125,7 @@ public class CachingPersistenceManagerPr
     /**
      * Returns an <code>Enumeration</code> of <code>Dictionary</code> objects
      * representing the configurations stored in the underlying persistence
-     * managers. The dictionaries returned are garanteed to contain the
+     * managers. The dictionaries returned are guaranteed to contain the
      * <code>service.pid</code> property.
      * <p>
      * Note, that each call to this method will return new dictionary objects.
@@ -178,7 +178,7 @@ public class CachingPersistenceManagerPr
             }
 
             // Deep copy the configuration to avoid any threading issue
-            final List<Dictionary> configs = new ArrayList<Dictionary>();
+            final List<Dictionary> configs = new ArrayList<>();
             for (final Dictionary d : cache.values())
             {
                 if ( d.get( Constants.SERVICE_PID ) != null && ( filter == null || filter.matches( d ) ) )

Modified: felix/trunk/osgi-r7/configadmin/src/test/java/org/apache/felix/cm/MockNotCachablePersistenceManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/configadmin/src/test/java/org/apache/felix/cm/MockNotCachablePersistenceManager.java?rev=1822055&r1=1822054&r2=1822055&view=diff
==============================================================================
--- felix/trunk/osgi-r7/configadmin/src/test/java/org/apache/felix/cm/MockNotCachablePersistenceManager.java (original)
+++ felix/trunk/osgi-r7/configadmin/src/test/java/org/apache/felix/cm/MockNotCachablePersistenceManager.java Tue Jan 23 20:54:27 2018
@@ -30,30 +30,38 @@ import java.util.Map;
 public class MockNotCachablePersistenceManager implements NotCachablePersistenceManager
 {
 
-    private final Map configs = new HashMap();
+    private final Map<String, Dictionary> configs = new HashMap<String, Dictionary>();
 
+    public Map<String, Dictionary> getStored()
+    {
+        return configs;
+    }
 
+    @Override
     public void delete( String pid )
     {
         configs.remove( pid );
     }
 
 
+    @Override
     public boolean exists( String pid )
     {
         return configs.containsKey( pid );
     }
 
 
+    @Override
     public Enumeration getDictionaries()
     {
         return Collections.enumeration( configs.values() );
     }
 
 
+    @Override
     public Dictionary load( String pid ) throws IOException
     {
-        Dictionary config = ( Dictionary ) configs.get( pid );
+        Dictionary config = configs.get( pid );
         if ( config != null )
         {
             return config;
@@ -63,6 +71,7 @@ public class MockNotCachablePersistenceM
     }
 
 
+    @Override
     public void store( String pid, Dictionary properties )
     {
         configs.put( pid, properties );

Modified: felix/trunk/osgi-r7/configadmin/src/test/java/org/apache/felix/cm/impl/ConfigurationManagerTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/configadmin/src/test/java/org/apache/felix/cm/impl/ConfigurationManagerTest.java?rev=1822055&r1=1822054&r2=1822055&view=diff
==============================================================================
--- felix/trunk/osgi-r7/configadmin/src/test/java/org/apache/felix/cm/impl/ConfigurationManagerTest.java (original)
+++ felix/trunk/osgi-r7/configadmin/src/test/java/org/apache/felix/cm/impl/ConfigurationManagerTest.java Tue Jan 23 20:54:27 2018
@@ -38,6 +38,7 @@ import org.apache.felix.cm.MockLogServic
 import org.apache.felix.cm.MockNotCachablePersistenceManager;
 import org.apache.felix.cm.MockPersistenceManager;
 import org.apache.felix.cm.PersistenceManager;
+import org.apache.felix.cm.impl.helper.ManagedServiceFactoryTracker;
 import org.apache.felix.cm.impl.persistence.CachingPersistenceManagerProxy;
 import org.apache.felix.cm.impl.persistence.PersistenceManagerProxy;
 import org.junit.After;
@@ -83,7 +84,7 @@ public class ConfigurationManagerTest
         String pid = "testDefaultPersistenceManager";
 
         PersistenceManager pm =new MockPersistenceManager();
-        Dictionary<String, Object> dictionary = new Hashtable<String, Object>();
+        Dictionary<String, Object> dictionary = new Hashtable<>();
         dictionary.put( "property1", "value1" );
         dictionary.put( Constants.SERVICE_PID, pid );
         pm.store( pid, dictionary );
@@ -95,7 +96,7 @@ public class ConfigurationManagerTest
         assertEquals(1, conf.length);
         assertEquals(2, conf[0].getProperties(true).size());
 
-        dictionary = new Hashtable<String, Object>();
+        dictionary = new Hashtable<>();
         dictionary.put( "property1", "value2" );
         pid = "testDefaultPersistenceManager";
         dictionary.put( Constants.SERVICE_PID, pid );
@@ -113,7 +114,7 @@ public class ConfigurationManagerTest
     {
         String pid = "testDefaultPersistenceManager";
         PersistenceManager pm = new MockNotCachablePersistenceManager();
-        Dictionary<String, Object> dictionary = new Hashtable<String, Object>();
+        Dictionary<String, Object> dictionary = new Hashtable<>();
         dictionary.put( "property1", "value1" );
         dictionary.put( Constants.SERVICE_PID, pid );
         pm.store( pid, dictionary );
@@ -125,7 +126,7 @@ public class ConfigurationManagerTest
         assertEquals(1, conf.length);
         assertEquals(2, conf[0].getProperties(true).size());
 
-        dictionary = new Hashtable<String, Object>();
+        dictionary = new Hashtable<>();
         dictionary.put("property1", "valueNotCached");
         pid = "testDefaultPersistenceManager";
         dictionary.put( Constants.SERVICE_PID, pid );
@@ -274,7 +275,7 @@ public class ConfigurationManagerTest
 
     @Test public void testEventsStartingBundle() throws Exception
     {
-        final Set<String> result = new HashSet<String>();
+        final Set<String> result = new HashSet<>();
 
         SynchronousConfigurationListener syncListener1 = new SynchronousConfigurationListener()
         {
@@ -338,7 +339,7 @@ public class ConfigurationManagerTest
         utField.setAccessible( true );
         utField.set( configMgr, new UpdateThread( null, "Test updater" ));
 
-        Dictionary<String, Object> props = new Hashtable<String, Object>();
+        Dictionary<String, Object> props = new Hashtable<>();
         props.put( Constants.SERVICE_PID, "org.acme.testpid" );
         ConfigurationImpl config = new ConfigurationImpl( configMgr, new MockPersistenceManager(), props );
         configMgr.updated( config, true );
@@ -347,6 +348,60 @@ public class ConfigurationManagerTest
                 2, result.size());
     }
 
+    public void test_factoryConfigurationCleanup() throws Exception
+    {
+        MockNotCachablePersistenceManager pm = new MockNotCachablePersistenceManager();
+        ConfigurationManager configMgr = new ConfigurationManager(new CachingPersistenceManagerProxy(pm), null);
+
+        final Field bcField = configMgr.getClass().getDeclaredField("bundleContext");
+        bcField.setAccessible(true);
+        bcField.set(configMgr, new MockBundleContext());
+        setServiceTrackerField( configMgr, "persistenceManagerTracker" );
+        setServiceTrackerField( configMgr, "logTracker" );
+        setServiceTrackerField( configMgr, "configurationListenerTracker" );
+        setServiceTrackerField( configMgr, "syncConfigurationListenerTracker" );
+
+        final Field mstField = configMgr.getClass().getDeclaredField("managedServiceFactoryTracker");
+        mstField.setAccessible(true);
+        mstField.set( configMgr, new ManagedServiceFactoryTracker(configMgr) {
+
+            @Override
+            public void open() {
+            }
+        });
+        final Field utField = configMgr.getClass().getDeclaredField( "updateThread" );
+        utField.setAccessible( true );
+        utField.set( configMgr, new UpdateThread( null, "Test updater" ) {
+
+            @Override
+            void schedule(Runnable update) {
+                update.run();
+            }
+        });
+
+        final String factoryPid = "my.factory";
+        final Dictionary<String, Object> props = new Hashtable<>();
+        props.put("hello", "world");
+
+        final ConfigurationImpl c1 = configMgr.createFactoryConfiguration(factoryPid, null);
+        c1.update(props);
+        final ConfigurationImpl c2 = configMgr.createFactoryConfiguration(factoryPid, null);
+        c2.update(props);
+        final ConfigurationImpl c3 = configMgr.createFactoryConfiguration(factoryPid, null);
+        c3.update(props);
+
+        assertEquals(4, pm.getStored().size());
+
+        c1.delete();
+        assertEquals(3, pm.getStored().size());
+
+        c2.delete();
+        assertEquals(2, pm.getStored().size());
+
+        c3.delete();
+        assertEquals(0, pm.getStored().size());
+    }
+
     private void assertNoLog( ConfigurationManager configMgr, int level, String message, Throwable t )
     {
         try
@@ -419,7 +474,7 @@ public class ConfigurationManagerTest
     private static ServiceReference[] setServiceTrackerField( ConfigurationManager configMgr,
             String fieldName, Object ... services ) throws Exception
     {
-        final Map<ServiceReference, Object> refMap = new HashMap<ServiceReference, Object>();
+        final Map<ServiceReference, Object> refMap = new HashMap<>();
         for ( Object svc : services )
         {
             ServiceReference sref = Mockito.mock( ServiceReference.class );