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