Merge "tests for empty leaf, namespace changing, multi simple node"
authorEd Warnicke <eaw@cisco.com>
Wed, 20 Nov 2013 16:07:25 +0000 (16:07 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 20 Nov 2013 16:07:25 +0000 (16:07 +0000)
24 files changed:
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ModuleInternalTransactionalInfo.java
opendaylight/config/netty-config-api/pom.xml [new file with mode: 0644]
opendaylight/config/netty-config-api/src/main/yang/netty.yang [new file with mode: 0644]
opendaylight/config/netty-event-executor-config/pom.xml
opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java
opendaylight/config/netty-event-executor-config/src/main/yang/netty-event-executor.yang
opendaylight/config/netty-threadgroup-config/pom.xml
opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModule.java
opendaylight/config/netty-threadgroup-config/src/main/yang/netty-threadgroup.yang [moved from opendaylight/config/netty-threadgroup-config/src/main/yang/nsos-netty-threadgroup.yang with 83% similarity]
opendaylight/config/netty-timer-config/pom.xml [new file with mode: 0644]
opendaylight/config/netty-timer-config/src/main/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModule.java [new file with mode: 0644]
opendaylight/config/netty-timer-config/src/main/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleFactory.java [new file with mode: 0644]
opendaylight/config/netty-timer-config/src/main/yang/netty-timer.yang [new file with mode: 0644]
opendaylight/config/netty-timer-config/src/test/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleTest.java [new file with mode: 0644]
opendaylight/config/pom.xml
opendaylight/config/threadpool-config-api/pom.xml
opendaylight/config/threadpool-config-api/src/main/yang/threadpool.yang
opendaylight/distribution/opendaylight/pom.xml
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcher.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java

index f93409f99ed21d980316df9c85a2bf144f061f3f..84c2c6dd4dd46b57372d1fbf14a46f43ed225181 100644 (file)
@@ -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());
index e71aef4c04cd3b90d5bc4cf8002aa52b8a4d2da9..c4f40fbeeb42a6c05e08a6213fc2d928d2a912da 100644 (file)
@@ -36,6 +36,11 @@ public class ModuleInternalTransactionalInfo implements Identifiable<ModuleIdent
         this.transactionModuleJMXRegistration = transactionModuleJMXRegistration;
     }
 
+
+    /**
+     * Use {@link #getIdentifier()} instead.
+     */
+    @Deprecated
     public ModuleIdentifier getName() {
         return name;
     }
@@ -56,7 +61,7 @@ public class ModuleInternalTransactionalInfo implements Identifiable<ModuleIdent
                 maybeOldInternalInfo.getOrderingIdx());
     }
 
-    @Deprecated
+
     public Module getModule() {
         return module;
     }
diff --git a/opendaylight/config/netty-config-api/pom.xml b/opendaylight/config/netty-config-api/pom.xml
new file mode 100644 (file)
index 0000000..9a2fe37
--- /dev/null
@@ -0,0 +1,54 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>config-subsystem</artifactId>
+    <version>0.2.3-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>netty-config-api</artifactId>
+     <name>${project.artifactId}</name>
+   <packaging>bundle</packaging>
+   <prerequisites>
+      <maven>3.0.4</maven>
+   </prerequisites>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-transport</artifactId>
+        </dependency>
+    </dependencies>
+   <build>
+      <plugins>
+         <plugin>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>maven-bundle-plugin</artifactId>
+            <configuration>
+               <instructions>
+                  <Import-Package>
+                     org.opendaylight.controller.config.api.*,
+                     io.netty.channel,
+                     io.netty.util,
+                     io.netty.util.concurrent
+                  </Import-Package>
+                  <Export-Package>
+                     org.opendaylight.controller.config.yang.netty
+                  </Export-Package>
+               </instructions>
+            </configuration>
+         </plugin>
+         <plugin>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-maven-plugin</artifactId>
+         </plugin>
+      </plugins>
+   </build>
+</project>
\ 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 (file)
index 0000000..7f7a3ff
--- /dev/null
@@ -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 <milfabia@cisco.com>";
+
+    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
index a2ce94f340f073cfc447a46c5e971776bbe44fe9..3d5384d171774d053ca01ee39ca1a9e3c784401f 100644 (file)
       </dependency>
       <dependency>
          <groupId>org.opendaylight.controller</groupId>
-         <artifactId>threadpool-config-api</artifactId>
+         <artifactId>netty-config-api</artifactId>
          <version>${project.version}</version>
       </dependency>
       <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId>
       </dependency>
-      <dependency>
-         <groupId>com.google.guava</groupId>
-         <artifactId>guava</artifactId>
-      </dependency>
 
       <!--test dependencies -->
       <dependency>
@@ -80,7 +76,7 @@
                   </Export-Package>
                   <Import-Package>
                      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,
index d45eccded8f7fd6b5c20c3f68f67898e559815a5..16e5c07356df97c6af8baf2f6e7eb80ac7d123f4 100644 (file)
@@ -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 <milfabia@cisco.com>";
 
     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 {
 
         }
     }
-
-
 }
index ef63fce2ce66126f329d72eeb94aa0e69d33eb23..8dc989e7283751c1a91b4e57d789046724b1f5b3 100644 (file)
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
-            <artifactId>threadpool-config-api</artifactId>
+            <artifactId>netty-config-api</artifactId>
             <version>${project.version}</version>
         </dependency>
-
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
 
-
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-        </dependency>
-
         <!--test dependencies -->
         <dependency>
             <groupId>junit</groupId>
@@ -82,7 +75,6 @@
             <plugin>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
-                <version>2.3.7</version>
                 <extensions>true</extensions>
                 <configuration>
                     <instructions>
@@ -92,7 +84,7 @@
                         <Import-Package>
                             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,
index fd6b216f53fa50c9cb956710d565140383bbf515..9ceef3116ac5603219c019eb2fd21d340e23dcca 100644 (file)
@@ -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);
         }
     }
 
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 f13cf391bf3dbd042853dc65df2ef6a652150435..e648c5328a71349f9261efa82f8c8ef02a798a58 100644 (file)
@@ -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 <rovarga@cisco.com>";
 
     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 (file)
index 0000000..095e71f
--- /dev/null
@@ -0,0 +1,114 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+   <parent>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>config-subsystem</artifactId>
+      <version>0.2.3-SNAPSHOT</version>
+   </parent>
+   <modelVersion>4.0.0</modelVersion>
+   <artifactId>netty-timer-config</artifactId>
+   <description>Configuration Wrapper around netty's timer</description>
+   <packaging>bundle</packaging>
+   <name>${project.artifactId}</name>
+   <prerequisites>
+      <maven>3.0.4</maven>
+   </prerequisites>
+
+   <dependencies>
+      <dependency>
+         <groupId>org.opendaylight.controller</groupId>
+         <artifactId>config-api</artifactId>
+      </dependency>
+      <dependency>
+         <groupId>org.opendaylight.controller</groupId>
+         <artifactId>netty-config-api</artifactId>
+         <version>${project.version}</version>
+      </dependency>
+      <dependency>
+         <groupId>org.opendaylight.controller</groupId>
+         <artifactId>threadpool-config-api</artifactId>
+         <version>${project.version}</version>
+      </dependency>
+      <dependency>
+         <groupId>org.slf4j</groupId>
+         <artifactId>slf4j-api</artifactId>
+      </dependency>
+
+      <!--test dependencies -->
+      <dependency>
+         <groupId>junit</groupId>
+         <artifactId>junit</artifactId>
+         <scope>test</scope>
+      </dependency>
+      <dependency>
+         <groupId>org.opendaylight.controller</groupId>
+         <artifactId>config-manager</artifactId>
+         <scope>test</scope>
+         <type>test-jar</type>
+      </dependency>
+      <dependency>
+         <groupId>org.opendaylight.controller</groupId>
+         <artifactId>config-manager</artifactId>
+         <scope>test</scope>
+      </dependency>
+      <dependency>
+         <groupId>org.opendaylight.controller</groupId>
+         <artifactId>config-util</artifactId>
+         <scope>test</scope>
+      </dependency>
+      <dependency>
+         <groupId>org.opendaylight.bgpcep</groupId>
+         <artifactId>mockito-configuration</artifactId>
+         <scope>test</scope>
+      </dependency>
+      <dependency>
+         <groupId>org.opendaylight.controller</groupId>
+         <artifactId>threadpool-config-impl</artifactId>
+         <version>${project.version}</version>
+         <scope>test</scope>
+      </dependency>
+
+   </dependencies>
+
+   <build>
+      <plugins>
+         <plugin>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-maven-plugin</artifactId>
+         </plugin>
+         <plugin>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>maven-bundle-plugin</artifactId>
+            <extensions>true</extensions>
+            <configuration>
+               <instructions>
+                  <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                  <Export-Package>
+                  </Export-Package>
+                  <Import-Package>
+                     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
+                  </Import-Package>
+               </instructions>
+            </configuration>
+         </plugin>
+      </plugins>
+   </build>
+
+   <distributionManagement>
+      <site>
+         <id>${project.artifactId}</id>
+         <name>NETTY-TIMER-CONFIG Module site</name>
+         <url>${basedir}/target/site/${project.artifactId}</url>
+      </site>
+   </distributionManagement>
+</project>
\ 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 (file)
index 0000000..cc78124
--- /dev/null
@@ -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<Timeout> 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 (file)
index 0000000..e291ab5
--- /dev/null
@@ -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 (file)
index 0000000..b53b13f
--- /dev/null
@@ -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 <milfabia@cisco.com>";
+
+    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 (file)
index 0000000..8bc4d95
--- /dev/null
@@ -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;
+    }
+
+}
index 3f27ff1055882d1352e27f7208d4571919f06e71..22be6f162b23239cf4952ec6283ae0094d3e0e74 100755 (executable)
         <module>yang-test</module>
         <module>logback-config</module>
         <module>threadpool-config-api</module>
+        <module>netty-config-api</module>
         <module>threadpool-config-impl</module>
         <module>netty-threadgroup-config</module>
         <module>netty-event-executor-config</module>
+        <module>netty-timer-config</module>
     </modules>
 
     <profiles>
index cddfb6483099d3e8e4e5127484866d102ef86e2c..5c70ac7958fdd4a9af2803879bb598c2d2bee11f 100644 (file)
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
         </dependency>
-        <dependency>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-transport</artifactId>
-        </dependency>
     </dependencies>
 
    <build>
@@ -38,8 +34,6 @@
                   <Import-Package>
                      org.opendaylight.controller.config.api.*,
                      com.google.common.eventbus,
-                     io.netty.channel,
-                     io.netty.util.concurrent
                   </Import-Package>
                   <Export-Package>
                      org.opendaylight.controller.config.threadpool,
index 9c73711c17bf98e0547b87674be96fd6451a64f1..8f3064822be319dfee6fd7c7061c8bee14db268f 100644 (file)
@@ -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";
-    }
-
-
 }
index 75424ba1b6d6611a107a57499d9dd0ef5ed61938..74a133f9139261d9741183337034b4c9c791b4f5 100644 (file)
               <artifactId>threadpool-config-api</artifactId>
               <version>${config.version}</version>
           </dependency>
+          <dependency>
+              <groupId>org.opendaylight.controller</groupId>
+              <artifactId>netty-config-api</artifactId>
+              <version>${config.version}</version>
+          </dependency>
           <dependency>
               <groupId>org.opendaylight.controller</groupId>
               <artifactId>threadpool-config-impl</artifactId>
           </dependency>
           <dependency>
               <groupId>org.opendaylight.controller</groupId>
-              <artifactId>netty-event-executor-config</artifactId>
+              <artifactId>netty-threadgroup-config</artifactId>
               <version>${config.version}</version>
           </dependency>
           <dependency>
               <artifactId>netty-event-executor-config</artifactId>
               <version>${config.version}</version>
           </dependency>
+          <dependency>
+              <groupId>org.opendaylight.controller</groupId>
+              <artifactId>netty-timer-config</artifactId>
+              <version>${config.version}</version>
+          </dependency>
 
 
           <!-- toaster example I'm pretty sure we should trim -->
index b3483a737a5d66653b0441faba5592909ddd519f..b8113a090313d270c4b1a391777d0d6e2e7d759e 100644 (file)
@@ -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();
index a20e00bcffcc114ab9849b821898280bc743b4b2..0d68e25f67071b1505b2ab4a54e836e6cfe78e2d 100644 (file)
@@ -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.<SSLContext>absent(), nettyThreadgroup, nettyThreadgroup);
     }
 
     public void init() throws InterruptedException {
@@ -125,11 +124,12 @@ public class ConfigPersisterNotificationHandler implements NotificationListener,
         while (true) {
             attempt++;
 
+            netconfClientDispatcher = new NetconfClientDispatcher(Optional.<SSLContext>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<String> currentCapabilities, Set<String> 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
index 6fc4da026f38acc3add7538f3c172e2c6ee01a0f..62c2113056afa1611300fce0c363ce293314fb49 100644 (file)
@@ -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<NetconfClientSession, NetconfClientSessionListener> {
+public class NetconfClientDispatcher extends AbstractDispatcher<NetconfClientSession, NetconfClientSessionListener> implements Closeable {
+
+    private static final Logger logger = LoggerFactory.getLogger(NetconfClient.class);
 
     private final Optional<SSLContext> maybeContext;
     private final NetconfClientSessionNegotiatorFactory negotatorFactory;
+    private final HashedWheelTimer timer;
 
     public NetconfClientDispatcher(final Optional<SSLContext> 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<NetconfClientSession> createClient(InetSocketAddress address,
@@ -83,4 +90,12 @@ public class NetconfClientDispatcher extends AbstractDispatcher<NetconfClientSes
         }
     }
 
+    @Override
+    public void close() {
+        try {
+            timer.stop();
+        } catch (Exception e) {
+            logger.debug("Ignoring exception while closing {}", timer, e);
+        }
+    }
 }
index 1a4888ba93b69081ab0d584a1730c7b74d84ed37..890bbe728804e469f0d2989253e6815ec1b85d06 100644 (file)
@@ -37,6 +37,7 @@ public class NetconfImplActivator implements BundleActivator {
     private DefaultCommitNotificationProducer commitNot;
     private NetconfServerDispatcher dispatch;
     private NioEventLoopGroup eventLoopGroup;
+    private HashedWheelTimer timer;
 
     @Override
     public void start(final BundleContext context) throws Exception {
@@ -50,8 +51,9 @@ public class NetconfImplActivator implements BundleActivator {
         factoriesTracker.open();
 
         SessionIdProvider idProvider = new SessionIdProvider();
+        timer = new HashedWheelTimer();
         NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
-                new HashedWheelTimer(), factoriesListener, idProvider);
+                timer, factoriesListener, idProvider);
 
         commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
 
@@ -88,5 +90,6 @@ public class NetconfImplActivator implements BundleActivator {
 
         commitNot.close();
         eventLoopGroup.shutdownGracefully();
+        timer.stop();
     }
 }
index 403ba3d0fc090ea06e9ce73c4ff4acc2b7fc32c5..5f6e046929b4a5183f3e4cce1932db9f61c538bd 100644 (file)
@@ -134,6 +134,7 @@ public class NetconfITTest extends AbstractConfigTest {
     public void tearDown() throws Exception {
         commitNot.close();
         nettyThreadgroup.shutdownGracefully();
+        clientDispatcher.close();
     }
 
     private void loadMessages() throws IOException, SAXException, ParserConfigurationException {