Repository: camel Updated Branches: refs/heads/master d1b2dc3ed -> 3ee311ab8
using CHM::computeIfAbsent. Refactored code to make use of CHM and avoid global locks Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/dfb49605 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/dfb49605 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/dfb49605 Branch: refs/heads/master Commit: dfb49605d9e1979edc80aca12e8c760902e9a9a5 Parents: d1b2dc3 Author: Siddharth Sharma <siddharth.sha...@jobvite-inc.com> Authored: Fri Sep 2 14:45:54 2016 -0700 Committer: Claus Ibsen <davscl...@apache.org> Committed: Mon Sep 5 08:44:03 2016 +0200 ---------------------------------------------------------------------- .../apache/camel/impl/DefaultCamelContext.java | 115 ++++++++++--------- 1 file changed, 59 insertions(+), 56 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/dfb49605/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java index 4391d57..92935d9 100644 --- a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java +++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java @@ -190,7 +190,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon private EndpointRegistry<EndpointKey> endpoints; private final AtomicInteger endpointKeyCounter = new AtomicInteger(); private final List<EndpointStrategy> endpointStrategies = new ArrayList<EndpointStrategy>(); - private final Map<String, Component> components = new HashMap<String, Component>(); + private final Map<String, Component> components = new ConcurrentHashMap<String, Component>(); private final Set<Route> routes = new LinkedHashSet<Route>(); private final List<Service> servicesToStop = new CopyOnWriteArrayList<Service>(); private final List<StartupListener> startupListeners = new CopyOnWriteArrayList<StartupListener>(); @@ -379,20 +379,22 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon public void addComponent(String componentName, final Component component) { ObjectHelper.notNull(component, "component"); - synchronized (components) { - if (components.containsKey(componentName)) { - throw new IllegalArgumentException("Cannot add component as its already previously added: " + componentName); - } - component.setCamelContext(this); - components.put(componentName, component); - for (LifecycleStrategy strategy : lifecycleStrategies) { - strategy.onComponentAdd(componentName, component); - } + component.setCamelContext(this); + Component oldValue = components.putIfAbsent(componentName, component); + if (oldValue != null) { + throw new IllegalArgumentException("Cannot add component as its already previously added: " + componentName); + } + postInitComponent(componentName, component); + } - // keep reference to properties component up to date - if (component instanceof PropertiesComponent && "properties".equals(componentName)) { - propertiesComponent = (PropertiesComponent) component; - } + private void postInitComponent(String componentName, final Component component) { + for (LifecycleStrategy strategy : lifecycleStrategies) { + strategy.onComponentAdd(componentName, component); + } + + // keep reference to properties component up to date + if (component instanceof PropertiesComponent && "properties".equals(componentName)) { + propertiesComponent = (PropertiesComponent) component; } } @@ -405,32 +407,37 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon } public Component getComponent(String name, boolean autoCreateComponents, boolean autoStart) { - // synchronize the look up and auto create so that 2 threads can't - // concurrently auto create the same component. - synchronized (components) { - Component component = components.get(name); - if (component == null && autoCreateComponents) { - try { - if (log.isDebugEnabled()) { - log.debug("Using ComponentResolver: {} to resolve component with name: {}", getComponentResolver(), name); - } - component = getComponentResolver().resolveComponent(name, this); - if (component != null) { - addComponent(name, component); - if (autoStart && (isStarted() || isStarting())) { - // If the component is looked up after the context is started, lets start it up. - if (component instanceof Service) { - startService((Service)component); - } + // CAMEL-10269 : Atomic operation to get/create a component. Avoid global locks. + return components.computeIfAbsent(name, comp -> initComponent(name, autoCreateComponents, autoStart)); + } + + /* + * CAMEL-10269 + * Function to initialize a component and auto start. Returns null if the autoCreateComponents is disabled + */ + private Component initComponent(String name, boolean autoCreateComponents, boolean autoStart) { + Component component = null; + if(autoCreateComponents) { + try { + if (log.isDebugEnabled()) { + log.debug("Using ComponentResolver: {} to resolve component with name: {}", getComponentResolver(), name); + } + component = getComponentResolver().resolveComponent(name, this); + if (component != null) { + component.setCamelContext(this); + postInitComponent(name, component); + if (autoStart && (isStarted() || isStarting())) { + // If the component is looked up after the context is started, lets start it up. + if (component instanceof Service) { + startService((Service)component); } } - } catch (Exception e) { - throw new RuntimeCamelException("Cannot auto create component: " + name, e); } + } catch (Exception e) { + throw new RuntimeCamelException("Cannot auto create component: " + name, e); } - log.trace("getComponent({}) -> {}", name, component); - return component; } + return component; } public <T extends Component> T getComponent(String name, Class<T> componentType) { @@ -461,24 +468,22 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon } public Component removeComponent(String componentName) { - synchronized (components) { - Component oldComponent = components.remove(componentName); - if (oldComponent != null) { - try { - stopServices(oldComponent); - } catch (Exception e) { - log.warn("Error stopping component " + oldComponent + ". This exception will be ignored.", e); - } - for (LifecycleStrategy strategy : lifecycleStrategies) { - strategy.onComponentRemove(componentName, oldComponent); - } + Component oldComponent = components.remove(componentName); + if (oldComponent != null) { + try { + stopServices(oldComponent); + } catch (Exception e) { + log.warn("Error stopping component " + oldComponent + ". This exception will be ignored.", e); } - // keep reference to properties component up to date - if (oldComponent != null && "properties".equals(componentName)) { - propertiesComponent = null; + for (LifecycleStrategy strategy : lifecycleStrategies) { + strategy.onComponentRemove(componentName, oldComponent); } - return oldComponent; } + // keep reference to properties component up to date + if (oldComponent != null && "properties".equals(componentName)) { + propertiesComponent = null; + } + return oldComponent; } // Endpoint Management Methods @@ -3917,13 +3922,11 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon } public List<String> getComponentNames() { - synchronized (components) { - List<String> answer = new ArrayList<String>(); - for (String name : components.keySet()) { - answer.add(name); - } - return answer; + List<String> answer = new ArrayList<String>(); + for (String name : components.keySet()) { + answer.add(name); } + return answer; } public List<String> getLanguageNames() {