Hello everyone;

I am experimenting the following: I need to use ConfigAdmin (trunk) for configuring my components. I also uses SCR (trunk). Because we have our own specific configuration database, I first populate CM during startup like this:

1) pre-load all configurations from our own database

2) and for each PID loaded from our own database, when then populate CM like this:

      populateCM(String PID, Dictionary c) {
         Configuration config = _cm.getConfiguration(PID, null);
         if (config.getBundleLocation() != null)
         {
           config.setBundleLocation(null);
         }
         config.update(c);
      }

3) Now, because we have our own persistence manager, I don't want to let CM store all configuration in the default CM PersistenceManager. So, I have noticed that CM has a nice feature -> we can provide our own PersistenceManager.

4) So, before SCR is started, I provide in the OSGi Registry my own PersistentManager: For now: this persistent manager is simple and just stores in
a map all CM configuration, like this:

-----------------------------------------------------------------------------------------
public class MapPersistenceManager implements PersistenceManager
{
private ConcurrentHashMap<String, Dictionary> _cmstore = new ConcurrentHashMap<String, Dictionary>();

 public void delete(String pid) throws IOException
 {
   _cmstore.remove(pid);
 }

 public boolean exists(String pid)
 {
   return _cmstore.containsKey(pid);
 }

 public Enumeration getDictionaries() throws IOException
 {
   return Collections.enumeration(_cmstore.values());
 }

 public Dictionary load(String pid) throws IOException
 {
   Dictionary d = _cmstore.get(pid);
   if (d == null) {
     d = new Hashtable();
   }
   return d;
 }

 public void store(String pid, Dictionary dic) throws IOException
 {
   _cmstore.put(pid, dic);
 }
}
-----------------------------------------------------------------------------------------

Notice that initially, I used a Map and I synchronized all my methods, but I then got the following exception:

java.util.ConcurrentModificationException
       at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
       at java.util.HashMap$ValueIterator.next(HashMap.java:822)
       at java.util.Collections$1.nextElement(Collections.java:3389)
at org.apache.felix.cm.impl.ConfigurationManager.listConfigurations(ConfigurationManager.java:518) at org.apache.felix.cm.impl.ConfigurationAdminImpl.listConfigurations(ConfigurationAdminImpl.java:124) at org.apache.felix.scr.impl.config.ConfigurationComponentRegistry.findConfigurations(ConfigurationComponentRegistry.java:248) at org.apache.felix.scr.impl.config.ConfigurationComponentRegistry.findFactoryConfigurations(ConfigurationComponentRegistry.java:240) at org.apache.felix.scr.impl.config.ConfigurationComponentRegistry.createComponentHolder(ConfigurationComponentRegistry.java:107) at org.apache.felix.scr.impl.BundleComponentActivator.loadDescriptor(BundleComponentActivator.java:243) at org.apache.felix.scr.impl.BundleComponentActivator.initialize(BundleComponentActivator.java:146) at org.apache.felix.scr.impl.BundleComponentActivator.<init>(BundleComponentActivator.java:110) at org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:233) at org.apache.felix.scr.impl.Activator.bundleChanged(Activator.java:169) at org.apache.felix.framework.util.EventDispatcher.invokeBundleListenerCallback(EventDispatcher.java:800) at org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:728) at org.apache.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:610)
       at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:3576)
       at org.apache.felix.framework.Felix.startBundle(Felix.java:1650)
       at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:915)
at com.alcatel.as.service.bundleinstaller.impl.BundleInstallerImpl$DeployedBundle.start(BundleInstallerImpl.java:1133) at com.alcatel.as.service.bundleinstaller.impl.BundleInstallerImpl.startBundles(BundleInstallerImpl.java:776) at com.alcatel.as.service.bundleinstaller.impl.BundleInstallerImpl.doScan(BundleInstallerImpl.java:664) at com.alcatel.as.service.bundleinstaller.impl.BundleInstallerImpl$1.run(BundleInstallerImpl.java:164)

So, I guess here that CM may concurrently invoke both getDictionaries() and store(String pid, Dictionary dic) methods, and while enumerating the Enum returned by the getDictionaries() method, I then get the exception above ? In any case, I replaced replaced my Map with a ConcurrentHashMap and I don't have the exception anymore.

5) Now, with the ConcurrentHashMap version, I start my Felix. I have a demo appli which is something like the well known Dictionary OSGi demo: I have a SpellChecker and an EnglishDictionary.

The EnglishDictionary SCR descriptor is defined like this:
-------------------------------------------------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"; >
<scr:component name="englishdico" modified="updated" configuration-policy="require" immediate="true">
   <service>
     <provide interface="com.alcatel_lucent.dictionary.DictionaryService"/>
   </service>
   <property name="Language" value="en"/>
<implementation class="com.alcatel_lucent.dictionary.english.EnglishDictionary" />
 </scr:component>
</components>
-------------------------------------------------------------------------------------------------------------------------------------------

As you see, my EnglishDictionary component has a configuration-policy="require", meaning that the PID "englishdico"
must be available before activating the englishdico component.

6) But, during startup, I don't know if it's a race condition issue or not, but the englishdico component is not activated and I have the following log:

2009-11-27 08:44:01,305 SCR Component Actor INFO osgi config/ca - [englishdico] Missing required configuration, cannot activate

what I don't understand is that I have this log, but before the log, I see that the ConfigurationComponentRegistry.configurationEvent() method has been called with the proper "englishdico" PID So, I have modified the ConfigurationComponentRegistry.configurationEvent method in order to add more logs:

-------------------------------------------------------------------------------------------------------------------------------------------
   public void configurationEvent( ConfigurationEvent event )
   {
       final String pid = event.getPid();
       final String factoryPid = event.getFactoryPid();
Activator.log( LogService.LOG_DEBUG, null, "Received Configuration Event pid=" + event.getPid() + "/type=" + event.getType(),
                      null );

       final ComponentHolder cm;
       if ( factoryPid == null )
       {
           cm = getComponent( pid );
       }
       else
       {
           cm = getComponent( factoryPid );
       }

       if (cm == null) {
Activator.log( LogService.LOG_WARNING, null, "Component Holder is null for pid= " + event.getPid(),
                        null );
         return;
       }
if (cm.getComponentMetadata().isConfigurationIgnored()) { Activator.log( LogService.LOG_WARNING, null, "Component Holder ignores configuration for pid= " + event.getPid(),
                        null );
         return;
       }
-------------------------------------------------------------------------------------------------------------------------------------------

7) So, I start Felix, and then I have the following logs (SCR seems to catch the "englishdico" PID but it deos nothing, because the getComponent(pid) method returned null:

2009-11-27 08:44:00,630 ProxyAppReporter-FastCacheListener DEBUG osgi config/ca - [138] Scheduling task Update: pid=englishdico 2009-11-27 08:44:00,630 Configuration Updater (Update: pid=englishdico) DEBUG osgi config/ca - [138] Running task Update: pid=englishdico 2009-11-27 08:44:00,630 Configuration Updater (Update: pid=englishdico) DEBUG osgi config/ca - [138] Updating configuration englishdico to modification #2 2009-11-27 08:44:00,631 Configuration Updater (Update: pid=englishdico) DEBUG osgi config/ca - [138] Scheduling task Fire ConfigurationEvent: pid=englishdico 2009-11-27 08:44:00,631 Configuration Updater (Fire ConfigurationEvent: pid=englishdico) DEBUG osgi config/ca - [138] Running task Fire ConfigurationEvent: pid=englishdico 2009-11-27 08:44:00,631 Configuration Updater (Fire ConfigurationEvent: pid=englishdico) DEBUG osgi config/ca - Received Configuration Event pid=englishdico/type=1 2009-11-27 08:44:00,631 Configuration Updater (Fire ConfigurationEvent: pid=englishdico) WARN osgi config/ca - Component Holder is null for pid= englishdico

8) Therefore, next, I see that my "englishdico" is not activated:

2009-11-27 08:44:00,632 ProxyAppReporter-FastCacheListener DEBUG osgi config/ca - [138] UpdateConfiguration(englishdico) scheduled 2009-11-27 08:44:01,301 ProxyAppReporter-FastCacheListener DEBUG osgi config/ca - [englishdico] Component englishdico created: DS=1, implementation=com.alcatel_lucent.dictionary.english.EnglishDictionary, immediate=true, default-enabled=true, factory=null, configuration-policy=require, activate=activate, deactivate=deactivate, modified=updated 2009-11-27 08:44:01,301 ProxyAppReporter-FastCacheListener DEBUG osgi config/ca - [englishdico] Component englishdico Services: servicefactory=false, services=[com.alcatel_lucent.dictionary.DictionaryService] 2009-11-27 08:44:01,302 ProxyAppReporter-FastCacheListener DEBUG osgi config/ca - [englishdico] Component englishdico Properties: {Language=en} 2009-11-27 08:44:01,304 ProxyAppReporter-FastCacheListener DEBUG osgi config/ca - [englishdico] State transition : Disabled -> Enabling 2009-11-27 08:44:01,304 ProxyAppReporter-FastCacheListener DEBUG osgi config/ca - [englishdico] State transition : Enabling -> Unsatisfied 2009-11-27 08:44:01,304 ProxyAppReporter-FastCacheListener DEBUG osgi config/ca - [englishdico] Component enabled 2009-11-27 08:44:01,305 ProxyAppReporter-FastCacheListener DEBUG osgi config/ca - Adding task [Enable Component: englishdico (10)] as #1 in the queue 2009-11-27 08:44:01,305 SCR Component Actor INFO osgi config/ca - Running task: Enable Component: englishdico (10) 2009-11-27 08:44:01,305 SCR Component Actor DEBUG osgi config/ca - [englishdico] State transition : Unsatisfied -> Activating 2009-11-27 08:44:01,305 SCR Component Actor DEBUG osgi config/ca - [englishdico] Activating component 2009-11-27 08:44:01,305 SCR Component Actor INFO osgi config/ca - [englishdico] Missing required configuration, cannot activate

And my englishdico is not activated because the PID is missing for my englishdico component, but this is not the case (see step 7)

9) If I somehow re-update the "englishdico" by invoking my method populateCM("englishdico", dictionary) ... then my englishdico is finally properly activated:

2009-11-27 08:44:28,439 ProxyAppReporter-FastCacheListener DEBUG osgi config/ca - [138] Scheduling task Update: pid=englishdico 2009-11-27 08:44:28,440 Configuration Updater (Update: pid=englishdico) DEBUG osgi config/ca - [138] Running task Update: pid=englishdico 2009-11-27 08:44:28,440 Configuration Updater (Update: pid=englishdico) DEBUG osgi config/ca - [138] Updating configuration englishdico to modification #3 2009-11-27 08:44:28,440 Configuration Updater (Update: pid=englishdico) DEBUG osgi config/ca - [138] Scheduling task Fire ConfigurationEvent: pid=englishdico 2009-11-27 08:44:28,440 Configuration Updater (Fire ConfigurationEvent: pid=englishdico) DEBUG osgi config/ca - [138] Running task Fire ConfigurationEvent: pid=englishdico 2009-11-27 08:44:28,440 Configuration Updater (Fire ConfigurationEvent: pid=englishdico) DEBUG osgi config/ca - Received Configuration Event pid=englishdico/type=1 2009-11-27 08:44:28,442 Configuration Updater (Fire ConfigurationEvent: pid=englishdico) DEBUG osgi config/ca - [englishdico] State transition : Unsatisfied -> Activating 2009-11-27 08:44:28,443 Configuration Updater (Fire ConfigurationEvent: pid=englishdico) DEBUG osgi config/ca - [englishdico] Activating component 2009-11-27 08:44:28,446 Configuration Updater (Fire ConfigurationEvent: pid=englishdico) DEBUG osgi config/ca - [englishdico] getting activate: activate 2009-11-27 08:44:28,446 Configuration Updater (Fire ConfigurationEvent: pid=englishdico) DEBUG osgi config/ca - [englishdico] invoking activate: activate

So, my question is:

1) Is there a problem with my "MapPersistenceManager" implementation: Am I doing something very bad here ?
      2) Or is there a race condition in SCR ?

thanks for your help;
/pierre


--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

Reply via email to