Pierre De Rop created FELIX-5114:
------------------------------------

             Summary: Schedule configuration update in Component executor 
synchronously
                 Key: FELIX-5114
                 URL: https://issues.apache.org/jira/browse/FELIX-5114
             Project: Felix
          Issue Type: Improvement
          Components: Dependency Manager
    Affects Versions:   org.apache.felix.dependencymanager-r5
            Reporter: Pierre De Rop
            Assignee: Pierre De Rop
            Priority: Minor
             Fix For: org.apache.felix.dependencymanager-r6


Currently, all external events are handled through the Component queue 
(Executor). This allows to provide a nice thread model, where no 
synchronization is required inside DM, and also the user benefits from this 
because, because all component lifecycle callbacks and all dependency 
injections are also performed using the internal Component queue. So, in some 
situation, this model make life easier for the developer.

But there is an exception to all this: the Configuration Dependency is 
currently handled from the Configuration Admin dispatcher thread, in other 
words, a component update callback can be called while a component "bind" 
method is called from another thread (if a service dependency is injected 
dynamically from another thread).

We do this because Configuration Admin requires to throw a 
ConfigurationException from the update thread, in case there is a configuration 
error.

The intent of this issue is simply to stay synchronous (we still throw a 
ConfigurationException from the CM update thread), but instead of calling the 
component "updated" callback from the CM thread, we schedule the update 
callback through the Component internal queue, and we wait for the update 
callback to be executed (using a simple Callbable associated with a FutureTask.

This trick will allow to call the component "updated" callback safely, and 
return any configuration errors to the CM update thread.

So, basically, instead of doing this in the ConfigurationDependencyImpl.updated 
callback

{code}
        try {
            invokeUpdated(settings); // either the callback instance or the 
component instances, if available.
        } catch (ConfigurationException e) {
            logConfigurationException(e);
            throw e;
        }
{code}

then schedule the update invocation in the component executor and wait for the 
result like this:

{code}
        Callable<ConfigurationException> result = new 
Callable<ConfigurationException>() {
            @Override
            public ConfigurationException call() throws Exception {
                try {
                    invokeUpdated(settings); // either the callback instance or 
the component instances, if available.
                } catch (ConfigurationException e) {
                    return e;
                }
                return null;
            }            
        };
        FutureTask<ConfigurationException> ft = new FutureTask<>(result);
        m_component.getExecutor().execute(ft);
        
        try {
            ConfigurationException confError = ft.get(UPDATE_MAXWAIT, 
TimeUnit.MILLISECONDS);
            if (confError != null) {
                logConfigurationException(confError);
                throw confError;
            }
          }

        catch (Throwable error) {
            logConfigurationException(error);
            throw new ConfigurationException(null, "Could not handle 
configuration update", error);
        }
{code}




--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to