From: Ed Warnicke Date: Wed, 20 Nov 2013 16:07:25 +0000 (+0000) Subject: Merge "tests for empty leaf, namespace changing, multi simple node" X-Git-Tag: jenkins-controller-bulk-release-prepare-only-2-1~364 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=5da475147b19f8d9e601813da1e356f2c677d131;hp=f53e599d9ce7ae991e38e6d07172d1b34792cba8 Merge "tests for empty leaf, namespace changing, multi simple node" --- diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java index f93409f99e..84c2c6dd4d 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java @@ -275,6 +275,7 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe ModuleJMXRegistrator newModuleJMXRegistrator = baseJMXRegistrator .createModuleJMXRegistrator(); + OsgiRegistration osgiRegistration = null; if (entry.hasOldModule()) { ModuleInternalInfo oldInternalInfo = entry.getOldInternalInfo(); DynamicReadableWrapper oldReadableConfigBean = oldInternalInfo @@ -282,19 +283,21 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe currentConfig.remove(entry.getName()); // test if old instance == new instance - if (oldReadableConfigBean.getInstance().equals( - module.getInstance())) { + if (oldReadableConfigBean.getInstance().equals(module.getInstance())) { // reused old instance: // wrap in readable dynamic mbean reusedInstances.add(primaryReadOnlyON); + osgiRegistration = oldInternalInfo.getOsgiRegistration(); } else { // recreated instance: // it is responsibility of module to call the old instance - // we just need to unregister configbean recreatedInstances.add(primaryReadOnlyON); + + // close old osgi registration + oldInternalInfo.getOsgiRegistration().close(); } - // close old osgi registration in any case - oldInternalInfo.getOsgiRegistration().close(); + // close old module jmx registrator oldInternalInfo.getModuleJMXRegistrator().close(); } else { @@ -316,10 +319,10 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe } // register to OSGi - OsgiRegistration osgiRegistration = beanToOsgiServiceManager - .registerToOsgi(module.getClass(), - newReadableConfigBean.getInstance(), - entry.getName()); + if (osgiRegistration == null) { + osgiRegistration = beanToOsgiServiceManager.registerToOsgi(module.getClass(), + newReadableConfigBean.getInstance(), entry.getName()); + } RootRuntimeBeanRegistratorImpl runtimeBeanRegistrator = runtimeRegistrators .get(entry.getName()); diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ModuleInternalTransactionalInfo.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ModuleInternalTransactionalInfo.java index e71aef4c04..c4f40fbeeb 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ModuleInternalTransactionalInfo.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ModuleInternalTransactionalInfo.java @@ -36,6 +36,11 @@ public class ModuleInternalTransactionalInfo implements Identifiable + + org.opendaylight.controller + config-subsystem + 0.2.3-SNAPSHOT + + 4.0.0 + netty-config-api + ${project.artifactId} + bundle + + 3.0.4 + + + + + org.opendaylight.controller + config-api + + + com.google.guava + guava + + + io.netty + netty-transport + + + + + + org.apache.felix + maven-bundle-plugin + + + + org.opendaylight.controller.config.api.*, + io.netty.channel, + io.netty.util, + io.netty.util.concurrent + + + org.opendaylight.controller.config.yang.netty + + + + + + org.opendaylight.yangtools + yang-maven-plugin + + + + \ No newline at end of file diff --git a/opendaylight/config/netty-config-api/src/main/yang/netty.yang b/opendaylight/config/netty-config-api/src/main/yang/netty.yang new file mode 100644 index 0000000000..7f7a3ff4ce --- /dev/null +++ b/opendaylight/config/netty-config-api/src/main/yang/netty.yang @@ -0,0 +1,52 @@ +// vi: set smarttab et sw=4 tabstop=4: +module netty { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:netty"; + prefix "netty"; + + import config { prefix config; revision-date 2013-04-05; } + + organization "Cisco Systems, Inc."; + + contact "Milos Fabian "; + + description + "This module contains the base YANG definitions for + netty services. + + Copyright (c)2013 Cisco Systems, Inc. All rights reserved.; + + This program and the accompanying materials are made available + under the terms of the Eclipse Public License v1.0 which + accompanies this distribution, and is available at + http://www.eclipse.org/legal/epl-v10.html"; + + revision "2013-11-19" { + description + "Initial revision."; + } + + identity netty-threadgroup { + description + "Configuration wrapper around netty's threadgroup"; + + base "config:service-type"; + config:java-class "io.netty.channel.EventLoopGroup"; + } + + identity netty-event-executor { + description + "Configuration wrapper around netty's event executor"; + + base "config:service-type"; + config:java-class "io.netty.util.concurrent.EventExecutor"; + } + + identity netty-timer { + description + "Configuration wrapper around netty's timer"; + + base "config:service-type"; + config:java-class "io.netty.util.Timer"; + } +} \ No newline at end of file diff --git a/opendaylight/config/netty-event-executor-config/pom.xml b/opendaylight/config/netty-event-executor-config/pom.xml index a2ce94f340..3d5384d171 100644 --- a/opendaylight/config/netty-event-executor-config/pom.xml +++ b/opendaylight/config/netty-event-executor-config/pom.xml @@ -21,17 +21,13 @@ org.opendaylight.controller - threadpool-config-api + netty-config-api ${project.version} org.slf4j slf4j-api - - com.google.guava - guava - @@ -80,7 +76,7 @@ com.google.common.base, - org.opendaylight.controller.config.yang.threadpool, + org.opendaylight.controller.config.yang.netty, io.netty.util.concurrent, org.opendaylight.controller.config.api, org.opendaylight.controller.config.api.annotations, diff --git a/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java b/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java index 3707f016a2..aed3a0cc15 100644 --- a/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java +++ b/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java @@ -37,7 +37,6 @@ public final class GlobalEventExecutorModule extends @Override public void validate() { super.validate(); - // Add custom validation for module attributes here. } @Override diff --git a/opendaylight/config/netty-event-executor-config/src/main/yang/netty-event-executor.yang b/opendaylight/config/netty-event-executor-config/src/main/yang/netty-event-executor.yang index d45eccded8..16e5c07356 100644 --- a/opendaylight/config/netty-event-executor-config/src/main/yang/netty-event-executor.yang +++ b/opendaylight/config/netty-event-executor-config/src/main/yang/netty-event-executor.yang @@ -2,18 +2,18 @@ module netty-event-executor { yang-version 1; namespace "urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor"; - prefix "netty-t"; + prefix "netty-ee"; import config { prefix config; revision-date 2013-04-05; } - import threadpool { prefix th; revision-date 2013-04-09; } + import netty { prefix netty; revision-date 2013-11-19; } organization "Cisco Systems, Inc."; contact "Milos Fabian "; description - "This module contains the base YANG definitions for NS-OS - thread-related services. + "This module contains the base YANG definitions for + netty event executor implementation. Copyright (c)2013 Cisco Systems, Inc. All rights reserved.; @@ -29,7 +29,7 @@ module netty-event-executor { identity netty-global-event-executor { base config:module-type; - config:provided-service th:netty-event-executor; + config:provided-service netty:netty-event-executor; config:java-name-prefix GlobalEventExecutor; } @@ -39,6 +39,4 @@ module netty-event-executor { } } - - } diff --git a/opendaylight/config/netty-threadgroup-config/pom.xml b/opendaylight/config/netty-threadgroup-config/pom.xml index ef63fce2ce..8dc989e728 100644 --- a/opendaylight/config/netty-threadgroup-config/pom.xml +++ b/opendaylight/config/netty-threadgroup-config/pom.xml @@ -25,21 +25,14 @@ org.opendaylight.controller - threadpool-config-api + netty-config-api ${project.version} - org.slf4j slf4j-api - - - com.google.guava - guava - - junit @@ -82,7 +75,6 @@ org.apache.felix maven-bundle-plugin - 2.3.7 true @@ -92,7 +84,7 @@ com.google.common.base, io.netty.channel.nio, - org.opendaylight.controller.config.yang.threadpool, + org.opendaylight.controller.config.yang.netty, io.netty.util.concurrent, org.opendaylight.controller.config.api, org.opendaylight.controller.config.api.annotations, diff --git a/opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModule.java b/opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModule.java index fd6b216f53..9ceef3116a 100644 --- a/opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModule.java +++ b/opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModule.java @@ -9,9 +9,10 @@ */ package org.opendaylight.controller.config.yang.netty.threadgroup; -import com.google.common.base.Preconditions; import io.netty.channel.nio.NioEventLoopGroup; +import org.opendaylight.controller.config.api.JmxAttributeValidationException; + /** * */ @@ -28,7 +29,8 @@ public final class NettyThreadgroupModule extends org.opendaylight.controller.co @Override public void validate(){ if(getThreadCount()!=null) { - Preconditions.checkArgument(getThreadCount() > 0, "Thread count cannot be < 0"); + JmxAttributeValidationException.checkCondition(getThreadCount() > 0, "value must be greater than 0", + threadCountJmxAttribute); } } diff --git a/opendaylight/config/netty-threadgroup-config/src/main/yang/nsos-netty-threadgroup.yang b/opendaylight/config/netty-threadgroup-config/src/main/yang/netty-threadgroup.yang similarity index 83% rename from opendaylight/config/netty-threadgroup-config/src/main/yang/nsos-netty-threadgroup.yang rename to opendaylight/config/netty-threadgroup-config/src/main/yang/netty-threadgroup.yang index f13cf391bf..e648c5328a 100644 --- a/opendaylight/config/netty-threadgroup-config/src/main/yang/nsos-netty-threadgroup.yang +++ b/opendaylight/config/netty-threadgroup-config/src/main/yang/netty-threadgroup.yang @@ -1,19 +1,19 @@ // vi: set smarttab et sw=4 tabstop=4: -module nsos-threadpool { +module threadgroup { yang-version 1; namespace "urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup"; - prefix "netty-t"; + prefix "netty-th"; import config { prefix config; revision-date 2013-04-05; } - import threadpool { prefix th; revision-date 2013-04-09; } + import netty { prefix netty; revision-date 2013-11-19; } organization "Cisco Systems, Inc."; contact "Robert Varga "; description - "This module contains the base YANG definitions for NS-OS - thread-related services. + "This module contains the base YANG definitions for + netty threadgroup implementation. Copyright (c)2013 Cisco Systems, Inc. All rights reserved."; @@ -24,7 +24,7 @@ module nsos-threadpool { identity netty-threadgroup-fixed { base config:module-type; - config:provided-service th:netty-threadgroup; + config:provided-service netty:netty-threadgroup; config:java-name-prefix NettyThreadgroup; } diff --git a/opendaylight/config/netty-timer-config/pom.xml b/opendaylight/config/netty-timer-config/pom.xml new file mode 100644 index 0000000000..095e71fcf5 --- /dev/null +++ b/opendaylight/config/netty-timer-config/pom.xml @@ -0,0 +1,114 @@ + + + org.opendaylight.controller + config-subsystem + 0.2.3-SNAPSHOT + + 4.0.0 + netty-timer-config + Configuration Wrapper around netty's timer + bundle + ${project.artifactId} + + 3.0.4 + + + + + org.opendaylight.controller + config-api + + + org.opendaylight.controller + netty-config-api + ${project.version} + + + org.opendaylight.controller + threadpool-config-api + ${project.version} + + + org.slf4j + slf4j-api + + + + + junit + junit + test + + + org.opendaylight.controller + config-manager + test + test-jar + + + org.opendaylight.controller + config-manager + test + + + org.opendaylight.controller + config-util + test + + + org.opendaylight.bgpcep + mockito-configuration + test + + + org.opendaylight.controller + threadpool-config-impl + ${project.version} + test + + + + + + + + org.opendaylight.yangtools + yang-maven-plugin + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.groupId}.${project.artifactId} + + + + javax.management, + com.google.common.base, + org.opendaylight.controller.config.yang.netty, + org.opendaylight.controller.config.yang.threadpool, + io.netty.util, + org.opendaylight.controller.config.api, + org.opendaylight.controller.config.api.annotations, + org.opendaylight.controller.config.api.runtime, + org.opendaylight.controller.config.spi, + org.slf4j, + org.osgi.framework + + + + + + + + + + ${project.artifactId} + NETTY-TIMER-CONFIG Module site + ${basedir}/target/site/${project.artifactId} + + + \ No newline at end of file diff --git a/opendaylight/config/netty-timer-config/src/main/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModule.java b/opendaylight/config/netty-timer-config/src/main/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModule.java new file mode 100644 index 0000000000..cc78124680 --- /dev/null +++ b/opendaylight/config/netty-timer-config/src/main/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModule.java @@ -0,0 +1,99 @@ +/** + * Generated file + + * Generated from: yang module name: netty-event-executor yang module local name: netty-hashed-wheel-timer + * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + * Generated at: Tue Nov 19 12:49:59 CET 2013 + * + * Do not modify this file unless it is present under src/main directory + */ +package org.opendaylight.controller.config.yang.netty.timer; + +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timeout; +import io.netty.util.Timer; +import io.netty.util.TimerTask; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.opendaylight.controller.config.api.JmxAttributeValidationException; + +/** +* +*/ +public final class HashedWheelTimerModule extends + org.opendaylight.controller.config.yang.netty.timer.AbstractHashedWheelTimerModule { + + public HashedWheelTimerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public HashedWheelTimerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, + HashedWheelTimerModule oldModule, java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void validate() { + super.validate(); + if (getTickDuration() != null) { + JmxAttributeValidationException.checkCondition(getTickDuration() > 0, "value must be greater than 0", + tickDurationJmxAttribute); + } + if (getTicksPerWheel() != null) { + JmxAttributeValidationException.checkCondition(getTicksPerWheel() > 0, "value must be greater than 0", + ticksPerWheelJmxAttribute); + } + } + + @Override + public java.lang.AutoCloseable createInstance() { + TimeUnit unit = TimeUnit.MILLISECONDS; + if (getTickDuration() != null && getThreadFactoryDependency() == null && getTicksPerWheel() == null) { + return new HashedWheelTimerCloseable(new HashedWheelTimer(getTickDuration(), unit)); + } + if (getTickDuration() != null && getThreadFactoryDependency() == null && getTicksPerWheel() != null) { + return new HashedWheelTimerCloseable(new HashedWheelTimer(getTickDuration(), unit, getTicksPerWheel())); + } + if (getTickDuration() == null && getThreadFactoryDependency() != null && getTicksPerWheel() == null) { + return new HashedWheelTimerCloseable(new HashedWheelTimer(getThreadFactoryDependency())); + } + if (getTickDuration() != null && getThreadFactoryDependency() != null && getTicksPerWheel() == null) { + return new HashedWheelTimerCloseable(new HashedWheelTimer(getThreadFactoryDependency(), getTickDuration(), + unit)); + } + if (getTickDuration() != null && getThreadFactoryDependency() != null && getTicksPerWheel() != null) { + return new HashedWheelTimerCloseable(new HashedWheelTimer(getThreadFactoryDependency(), getTickDuration(), + unit, getTicksPerWheel())); + } + return new HashedWheelTimerCloseable(new HashedWheelTimer()); + } + + static final private class HashedWheelTimerCloseable implements AutoCloseable, Timer { + + private final Timer timer; + + public HashedWheelTimerCloseable(Timer timer) { + this.timer = timer; + } + + @Override + public void close() throws Exception { + stop(); + } + + @Override + public Timeout newTimeout(TimerTask task, long delay, TimeUnit unit) { + return this.timer.newTimeout(task, delay, unit); + } + + @Override + public Set stop() { + return this.timer.stop(); + } + + } +} diff --git a/opendaylight/config/netty-timer-config/src/main/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleFactory.java b/opendaylight/config/netty-timer-config/src/main/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleFactory.java new file mode 100644 index 0000000000..e291ab5465 --- /dev/null +++ b/opendaylight/config/netty-timer-config/src/main/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleFactory.java @@ -0,0 +1,18 @@ +/** + * Generated file + + * Generated from: yang module name: netty-event-executor yang module local name: netty-hashed-wheel-timer + * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + * Generated at: Tue Nov 19 12:49:59 CET 2013 + * + * Do not modify this file unless it is present under src/main directory + */ +package org.opendaylight.controller.config.yang.netty.timer; + +/** +* +*/ +public class HashedWheelTimerModuleFactory extends + org.opendaylight.controller.config.yang.netty.timer.AbstractHashedWheelTimerModuleFactory { + +} diff --git a/opendaylight/config/netty-timer-config/src/main/yang/netty-timer.yang b/opendaylight/config/netty-timer-config/src/main/yang/netty-timer.yang new file mode 100644 index 0000000000..b53b13f5a8 --- /dev/null +++ b/opendaylight/config/netty-timer-config/src/main/yang/netty-timer.yang @@ -0,0 +1,59 @@ +// vi: set smarttab et sw=4 tabstop=4: +module netty-timer { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:netty:timer"; + prefix "netty-timer"; + + import config { prefix config; revision-date 2013-04-05; } + import netty { prefix netty; revision-date 2013-11-19; } + import threadpool { prefix th; revision-date 2013-04-09; } + + organization "Cisco Systems, Inc."; + + contact "Milos Fabian "; + + description + "This module contains the base YANG definitions for + netty timer implementation. + + Copyright (c)2013 Cisco Systems, Inc. All rights reserved.; + + This program and the accompanying materials are made available + under the terms of the Eclipse Public License v1.0 which + accompanies this distribution, and is available at + http://www.eclipse.org/legal/epl-v10.html"; + + revision "2013-11-19" { + description + "Initial revision"; + } + + identity netty-hashed-wheel-timer { + base config:module-type; + config:provided-service netty:netty-timer; + config:java-name-prefix HashedWheelTimer; + } + + augment "/config:modules/config:module/config:configuration" { + case netty-hashed-wheel-timer { + when "/config:modules/config:module/config:type = 'netty-hashed-wheel-timer'"; + + leaf tick-duration { + type uint32; + } + + leaf ticks-per-wheel { + type uint16; + } + + container thread-factory { + uses config:service-ref { + refine type { + mandatory false; + config:required-identity th:threadfactory; + } + } + } + } + } +} \ No newline at end of file diff --git a/opendaylight/config/netty-timer-config/src/test/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleTest.java b/opendaylight/config/netty-timer-config/src/test/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleTest.java new file mode 100644 index 0000000000..8bc4d95d60 --- /dev/null +++ b/opendaylight/config/netty-timer-config/src/test/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleTest.java @@ -0,0 +1,131 @@ +package org.opendaylight.controller.config.yang.netty.timer; + +import javax.management.InstanceAlreadyExistsException; +import javax.management.InstanceNotFoundException; +import javax.management.ObjectName; + +import junit.framework.Assert; + +import org.junit.Before; +import org.junit.Test; +import org.opendaylight.controller.config.api.ConflictingVersionException; +import org.opendaylight.controller.config.api.ValidationException; +import org.opendaylight.controller.config.api.jmx.CommitStatus; +import org.opendaylight.controller.config.manager.impl.AbstractConfigTest; +import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; +import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; +import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleFactory; +import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleMXBean; + +public class HashedWheelTimerModuleTest extends AbstractConfigTest { + + private HashedWheelTimerModuleFactory factory; + private NamingThreadFactoryModuleFactory threadFactory; + private final String instanceName = "hashed-wheel-timer1"; + + @Before + public void setUp() { + factory = new HashedWheelTimerModuleFactory(); + threadFactory = new NamingThreadFactoryModuleFactory(); + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory, threadFactory)); + } + + public void testValidationExceptionTickDuration() throws InstanceAlreadyExistsException { + ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); + try { + createInstance(transaction, instanceName, 0L, 10, true); + transaction.validateConfig(); + Assert.fail(); + } catch (ValidationException e) { + Assert.assertTrue(e.getMessage().contains("TickDuration value must be greater than 0")); + } + } + + public void testValidationExceptionTicksPerWheel() throws InstanceAlreadyExistsException { + ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); + try { + createInstance(transaction, instanceName, 500L, 0, true); + transaction.validateConfig(); + Assert.fail(); + } catch (ValidationException e) { + Assert.assertTrue(e.getMessage().contains("TicksPerWheel value must be greater than 0")); + } + } + + @Test + public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException, + ConflictingVersionException { + ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); + + createInstance(transaction, instanceName, 500L, 10, true); + createInstance(transaction, instanceName + 1, null, null, false); + createInstance(transaction, instanceName + 2, 500L, 10, false); + createInstance(transaction, instanceName + 3, 500L, null, false); + transaction.validateConfig(); + CommitStatus status = transaction.commit(); + + assertBeanCount(4, factory.getImplementationName()); + assertStatus(status, 5, 0, 0); + } + + @Test + public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException, + ValidationException { + + ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); + createInstance(transaction, instanceName, 500L, 10, true); + + transaction.commit(); + + transaction = configRegistryClient.createTransaction(); + assertBeanCount(1, factory.getImplementationName()); + CommitStatus status = transaction.commit(); + + assertBeanCount(1, factory.getImplementationName()); + assertStatus(status, 0, 0, 2); + } + + @Test + public void testReconfigure() throws InstanceAlreadyExistsException, ConflictingVersionException, + ValidationException, InstanceNotFoundException { + + ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); + createInstance(transaction, instanceName, 500L, 10, true); + transaction.commit(); + + transaction = configRegistryClient.createTransaction(); + assertBeanCount(1, factory.getImplementationName()); + HashedWheelTimerModuleMXBean mxBean = transaction.newMBeanProxy( + transaction.lookupConfigBean(factory.getImplementationName(), instanceName), + HashedWheelTimerModuleMXBean.class); + mxBean.setTicksPerWheel(20); + CommitStatus status = transaction.commit(); + + assertBeanCount(1, factory.getImplementationName()); + assertStatus(status, 0, 1, 1); + } + + private ObjectName createInstance(ConfigTransactionJMXClient transaction, String instanceName, + final Long tickDuration, final Integer ticksPerWheel, final boolean hasThreadfactory) + throws InstanceAlreadyExistsException { + ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName); + HashedWheelTimerModuleMXBean mxBean = transaction + .newMBeanProxy(nameCreated, HashedWheelTimerModuleMXBean.class); + mxBean.setTickDuration(tickDuration); + mxBean.setTicksPerWheel(ticksPerWheel); + if (hasThreadfactory) { + mxBean.setThreadFactory(createThreadfactoryInstance(transaction, "thread-factory1", "th")); + } + return nameCreated; + } + + private ObjectName createThreadfactoryInstance(ConfigTransactionJMXClient transaction, String instanceName, + final String namePrefix) throws InstanceAlreadyExistsException { + ObjectName nameCreated = transaction.createModule(threadFactory.getImplementationName(), instanceName); + NamingThreadFactoryModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated, + NamingThreadFactoryModuleMXBean.class); + mxBean.setNamePrefix(namePrefix); + return nameCreated; + } + +} diff --git a/opendaylight/config/pom.xml b/opendaylight/config/pom.xml index 3f27ff1055..22be6f162b 100755 --- a/opendaylight/config/pom.xml +++ b/opendaylight/config/pom.xml @@ -30,9 +30,11 @@ yang-test logback-config threadpool-config-api + netty-config-api threadpool-config-impl netty-threadgroup-config netty-event-executor-config + netty-timer-config diff --git a/opendaylight/config/threadpool-config-api/pom.xml b/opendaylight/config/threadpool-config-api/pom.xml index cddfb64830..5c70ac7958 100644 --- a/opendaylight/config/threadpool-config-api/pom.xml +++ b/opendaylight/config/threadpool-config-api/pom.xml @@ -22,10 +22,6 @@ com.google.guava guava - - io.netty - netty-transport - @@ -38,8 +34,6 @@ org.opendaylight.controller.config.api.*, com.google.common.eventbus, - io.netty.channel, - io.netty.util.concurrent org.opendaylight.controller.config.threadpool, diff --git a/opendaylight/config/threadpool-config-api/src/main/yang/threadpool.yang b/opendaylight/config/threadpool-config-api/src/main/yang/threadpool.yang index 9c73711c17..8f3064822b 100644 --- a/opendaylight/config/threadpool-config-api/src/main/yang/threadpool.yang +++ b/opendaylight/config/threadpool-config-api/src/main/yang/threadpool.yang @@ -73,23 +73,4 @@ module threadpool { base "threadpool"; config:java-class "org.opendaylight.controller.config.threadpool.ScheduledThreadPool"; } - - - identity netty-threadgroup { - description - "Configuration wrapper around netty's threadgroup"; - - base "config:service-type"; - config:java-class "io.netty.channel.EventLoopGroup"; - } - - identity netty-event-executor { - description - "Configuration wrapper around netty's event executor"; - - base "config:service-type"; - config:java-class "io.netty.util.concurrent.EventExecutor"; - } - - } diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml index 75424ba1b6..74a133f913 100644 --- a/opendaylight/distribution/opendaylight/pom.xml +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -242,6 +242,11 @@ threadpool-config-api ${config.version} + + org.opendaylight.controller + netty-config-api + ${config.version} + org.opendaylight.controller threadpool-config-impl @@ -249,7 +254,7 @@ org.opendaylight.controller - netty-event-executor-config + netty-threadgroup-config ${config.version} @@ -257,6 +262,11 @@ netty-event-executor-config ${config.version} + + org.opendaylight.controller + netty-timer-config + ${config.version} + diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java index b3483a737a..b8113a0903 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java @@ -41,12 +41,12 @@ public class TransactionProvider implements AutoCloseable { @Override public synchronized void close() { for (ObjectName tx : allOpenedTransactions) { - if (isStillOpenTransaction(tx)) { - try { + try { + if (isStillOpenTransaction(tx)) { configRegistryClient.getConfigTransactionClient(tx).abortConfig(); - } catch (Exception e) { - logger.debug("Ignoring {} while closing transaction {}", e.toString(), tx, e); } + } catch (Exception e) { + logger.debug("Ignoring exception while closing transaction {}", tx, e); } } allOpenedTransactions.clear(); diff --git a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java index a20e00bcff..0d68e25f67 100644 --- a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java +++ b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java @@ -54,9 +54,9 @@ public class ConfigPersisterNotificationHandler implements NotificationListener, private static final Logger logger = LoggerFactory.getLogger(ConfigPersisterNotificationHandler.class); private final InetSocketAddress address; - private final NetconfClientDispatcher dispatcher; private final EventLoopGroup nettyThreadgroup; + private NetconfClientDispatcher netconfClientDispatcher; private NetconfClient netconfClient; private final Persister persister; @@ -81,7 +81,6 @@ public class ConfigPersisterNotificationHandler implements NotificationListener, this.timeout = timeout; this.nettyThreadgroup = new NioEventLoopGroup(); - this.dispatcher = new NetconfClientDispatcher(Optional.absent(), nettyThreadgroup, nettyThreadgroup); } public void init() throws InterruptedException { @@ -125,11 +124,12 @@ public class ConfigPersisterNotificationHandler implements NotificationListener, while (true) { attempt++; + netconfClientDispatcher = new NetconfClientDispatcher(Optional.absent(), nettyThreadgroup, nettyThreadgroup); try { - netconfClient = new NetconfClient(this.toString(), address, delay, dispatcher); - // TODO is this correct ex to catch ? + netconfClient = new NetconfClient(this.toString(), address, delay, netconfClientDispatcher); } catch (IllegalStateException e) { logger.debug("Netconf {} was not initialized or is not stable, attempt {}", address, attempt, e); + netconfClientDispatcher.close(); Thread.sleep(delay); continue; } @@ -148,11 +148,7 @@ public class ConfigPersisterNotificationHandler implements NotificationListener, logger.debug("Polling hello from netconf, attempt {}, capabilities {}", attempt, currentCapabilities); - try { - netconfClient.close(); - } catch (IOException e) { - throw new RuntimeException("Error closing temporary client " + netconfClient); - } + closeClientAndDispatcher(netconfClient, netconfClientDispatcher); Thread.sleep(delay); } @@ -162,6 +158,25 @@ public class ConfigPersisterNotificationHandler implements NotificationListener, } + private static void closeClientAndDispatcher(Closeable client, Closeable dispatcher) { + Exception fromClient = null; + try { + client.close(); + } catch (Exception e) { + fromClient = e; + } finally { + try { + dispatcher.close(); + } catch (Exception e) { + if (fromClient != null) { + e.addSuppressed(fromClient); + } + + throw new RuntimeException("Error closing temporary client ", e); + } + } + } + private boolean isSubset(Set currentCapabilities, Set expectedCaps) { for (String exCap : expectedCaps) { if (currentCapabilities.contains(exCap) == false) @@ -318,10 +333,18 @@ public class ConfigPersisterNotificationHandler implements NotificationListener, } } + if (netconfClientDispatcher != null) { + try { + netconfClientDispatcher.close(); + } catch (Exception e) { + logger.warn("Unable to close connection to netconf {}", netconfClientDispatcher, e); + } + } + try { nettyThreadgroup.shutdownGracefully(); } catch (Exception e) { - logger.warn("Unable to close netconf client thread group {}", dispatcher, e); + logger.warn("Unable to close netconf client thread group {}", netconfClientDispatcher, e); } // unregister from JMX diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcher.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcher.java index 6fc4da026f..62c2113056 100644 --- a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcher.java +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcher.java @@ -23,20 +23,27 @@ import org.opendaylight.protocol.framework.AbstractDispatcher; import org.opendaylight.protocol.framework.ReconnectStrategy; import org.opendaylight.protocol.framework.SessionListener; import org.opendaylight.protocol.framework.SessionListenerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; +import java.io.Closeable; import java.net.InetSocketAddress; -public class NetconfClientDispatcher extends AbstractDispatcher { +public class NetconfClientDispatcher extends AbstractDispatcher implements Closeable { + + private static final Logger logger = LoggerFactory.getLogger(NetconfClient.class); private final Optional maybeContext; private final NetconfClientSessionNegotiatorFactory negotatorFactory; + private final HashedWheelTimer timer; public NetconfClientDispatcher(final Optional maybeContext, EventLoopGroup bossGroup, EventLoopGroup workerGroup) { super(bossGroup, workerGroup); this.maybeContext = Preconditions.checkNotNull(maybeContext); - this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(new HashedWheelTimer()); + timer = new HashedWheelTimer(); + this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(timer); } public Future createClient(InetSocketAddress address, @@ -83,4 +90,12 @@ public class NetconfClientDispatcher extends AbstractDispatcher