From bd82648aba7728f88e24324d14f9813960e8fa96 Mon Sep 17 00:00:00 2001 From: Siddharth Sharma Date: Fri, 2 Sep 2016 14:45:54 -0700 Subject: [PATCH] using CHM::computeIfAbsent. Refactored code to make use of CHM and avoid global locks --- .../camel/impl/DefaultCamelContext.java | 115 +++++++++--------- 1 file changed, 59 insertions(+), 56 deletions(-) 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 4391d57c0a06d..92935d97471bc 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 endpoints; private final AtomicInteger endpointKeyCounter = new AtomicInteger(); private final List endpointStrategies = new ArrayList(); - private final Map components = new HashMap(); + private final Map components = new ConcurrentHashMap(); private final Set routes = new LinkedHashSet(); private final List servicesToStop = new CopyOnWriteArrayList(); private final List startupListeners = new CopyOnWriteArrayList(); @@ -379,20 +379,22 @@ public Component hasComponent(String componentName) { 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 Component getComponent(String name, boolean autoCreateComponents) { } 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 getComponent(String name, Class componentType) { @@ -461,24 +468,22 @@ public Component resolveComponent(String name) { } 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 void setPackageScanClassResolver(PackageScanClassResolver packageScanClas } public List getComponentNames() { - synchronized (components) { - List answer = new ArrayList(); - for (String name : components.keySet()) { - answer.add(name); - } - return answer; + List answer = new ArrayList(); + for (String name : components.keySet()) { + answer.add(name); } + return answer; } public List getLanguageNames() {