Merge "Fix checkstyle warnings in logback-config"
authorTony Tkacik <ttkacik@cisco.com>
Wed, 3 Dec 2014 09:26:42 +0000 (09:26 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 3 Dec 2014 09:26:42 +0000 (09:26 +0000)
125 files changed:
features/extras/pom.xml [new file with mode: 0644]
features/extras/src/main/resources/features.xml [new file with mode: 0644]
features/flow/pom.xml
features/flow/src/main/resources/features.xml
features/pom.xml
opendaylight/commons/opendaylight/pom.xml
opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyModuleTest.java
opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java
opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/test/TwoInterfacesExportTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/test/SimpleConfigurationTest.java
opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java
opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/ImmediateEventExecutorModuleTest.java
opendaylight/distribution/opendaylight-karaf/pom.xml
opendaylight/md-sal/pom.xml
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleActor.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleRoleChangeListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/TestDriver.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/KeyValue.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/RegisterListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/SetNotifiers.java [new file with mode: 0644]
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImpl.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ConfigParams.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/DefaultConfigParamsImpl.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLog.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogEntry.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogImplEntry.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractLeader.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/SnapshotTracker.java [new file with mode: 0644]
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshot.java
opendaylight/md-sal/sal-akka-raft/src/main/resources/application.conf
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImplTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/MockRaftActorContext.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/FollowerTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/SnapshotTrackerTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/utils/MessageCollectorActor.java
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RegisterRoleChangeListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RegisterRoleChangeListenerReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RoleChangeNotification.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RoleChangeNotifier.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RoleChanged.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/raft/protobuff/client/messages/CompositeModificationPayload.java
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/raft/protobuff/client/messages/Payload.java
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/cluster/raft/InstallSnapshotMessages.java
opendaylight/md-sal/sal-clustering-commons/src/main/resources/InstallSnapshot.proto
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/TestModel.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DatastoreContext.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStats.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStatsMXBean.java
opendaylight/md-sal/sal-distributed-datastore/src/main/yang/distributed-datastore-provider.yang
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/CompositeModificationPayloadTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/RoleChangeNotifierTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/MessageCollectorActor.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/programs/appendentries/Client.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/BucketStore.java
opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistryTest.java
opendaylight/md-sal/statistics-manager-config/pom.xml [new file with mode: 0644]
opendaylight/md-sal/statistics-manager-config/src/main/resources/initial/30-statistics-manager.xml [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/pom.xml
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/config/yang/md/sal/statistics_manager/StatisticsManagerModule.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/config/yang/md/sal/statistics_manager/StatisticsManagerModuleFactory.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManager.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerActivator.java [deleted file]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitQueue.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatisticsManagerConfig.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatisticsManagerImpl.java
opendaylight/md-sal/statistics-manager/src/main/yang/statistics-manager.yang [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerProvider.java [deleted file]
opendaylight/md-sal/statistics-manager/src/test/java/test/mock/FlowStatisticsTest.java [deleted file]
opendaylight/md-sal/statistics-manager/src/test/java/test/mock/GroupStatisticsTest.java [deleted file]
opendaylight/md-sal/statistics-manager/src/test/java/test/mock/MeterStatisticsTest.java [deleted file]
opendaylight/md-sal/statistics-manager/src/test/java/test/mock/NodeRegistrationTest.java
opendaylight/md-sal/statistics-manager/src/test/java/test/mock/PortStatisticsTest.java [deleted file]
opendaylight/md-sal/statistics-manager/src/test/java/test/mock/QueueStatisticsTest.java [deleted file]
opendaylight/md-sal/statistics-manager/src/test/java/test/mock/StatCollectorTest.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/test/java/test/mock/TableStatisticsTest.java [deleted file]
opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightFlowStatisticsServiceMock.java
opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightFlowTableStatisticsServiceMock.java
opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightGroupStatisticsServiceMock.java
opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightMeterStatisticsServiceMock.java
opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightPortStatisticsServiceMock.java
opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightQueueStatisticsServiceMock.java
opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/ProviderContextMock.java [deleted file]
opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/StatisticsManagerTest.java
opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/TestUtils.java
opendaylight/netconf/netconf-tcp/src/main/java/org/opendaylight/controller/netconf/tcp/netty/ProxyServerHandler.java
opendaylight/netconf/netconf-tcp/src/main/java/org/opendaylight/controller/netconf/tcp/osgi/NetconfTCPActivator.java
opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/Main.java
opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java
opendaylight/netconf/netconf-usermanager/src/main/java/org/opendaylight/controller/netconf/auth/usermanager/AuthProviderImpl.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/NetconfUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/MissingNameSpaceException.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/UnexpectedElementException.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/UnexpectedNamespaceException.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessage.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessageAdditionalHeader.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageHeader.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/SendErrorExceptionUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/HardcodedNamespaceResolver.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XMLNetconfUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfValidator.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/NetconfUtilTest.java
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/mapping/AbstractLastNetconfOperationTest.java
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperationTest.java
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/mapping/AbstractSingletonNetconfOperationTest.java
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessageAdditionalHeaderTest.java
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessageTest.java
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageHeaderTest.java
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtilTest.java
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/SendErrorExceptionUtilTest.java
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtilTest.java
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/XmlFileLoader.java
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/xml/XmlElementTest.java
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/startExi.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/stopExi.xml

diff --git a/features/extras/pom.xml b/features/extras/pom.xml
new file mode 100644 (file)
index 0000000..20089c7
--- /dev/null
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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
+-->
+
+<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">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>commons.opendaylight</artifactId>
+        <version>1.5.0-SNAPSHOT</version>
+        <relativePath>../../opendaylight/commons/opendaylight</relativePath>
+    </parent>
+    <artifactId>features-extras</artifactId>
+    <groupId>org.opendaylight.controller</groupId>
+    <packaging>jar</packaging>
+    <properties>
+        <features.file>features.xml</features.file>
+        <!-- Optional TODO: Move these properties to your parent pom and possibly
+              DependencyManagement section of your parent pom -->
+        <branding.version>1.1.0-SNAPSHOT</branding.version>
+        <karaf.resources.version>1.5.0-SNAPSHOT</karaf.resources.version>
+        <karaf.version>3.0.1</karaf.version>
+        <feature.test.version>0.7.0-SNAPSHOT</feature.test.version>
+        <karaf.empty.version>1.5.0-SNAPSHOT</karaf.empty.version>
+        <surefire.version>2.16</surefire.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.jolokia</groupId>
+            <artifactId>jolokia-osgi</artifactId>
+            <version>${jolokia.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>features-test</artifactId>
+            <version>${feature.test.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <!-- dependency for opendaylight-karaf-empty for use by testing -->
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>opendaylight-karaf-empty</artifactId>
+            <version>${karaf.empty.version}</version>
+            <type>zip</type>
+        </dependency>
+    </dependencies>
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>filter</id>
+                        <phase>generate-resources</phase>
+                        <goals>
+                            <goal>resources</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>attach-artifacts</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>attach-artifact</goal>
+                        </goals>
+                        <configuration>
+                            <artifacts>
+                                <artifact>
+                                    <file>${project.build.directory}/classes/${features.file}</file>
+                                    <type>xml</type>
+                                    <classifier>features</classifier>
+                                </artifact>
+                            </artifacts>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>${surefire.version}</version>
+                <configuration>
+                    <systemPropertyVariables>
+                        <karaf.distro.groupId>org.opendaylight.controller</karaf.distro.groupId>
+                        <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId>
+                        <karaf.distro.version>${karaf.empty.version}</karaf.distro.version>
+                    </systemPropertyVariables>
+                    <dependenciesToScan>
+                        <dependency>org.opendaylight.yangtools:features-test</dependency>
+                    </dependenciesToScan>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <scm>
+        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+        <tag>HEAD</tag>
+        <url>https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=summary</url>
+    </scm>
+</project>
diff --git a/features/extras/src/main/resources/features.xml b/features/extras/src/main/resources/features.xml
new file mode 100644 (file)
index 0000000..e7423ea
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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
+-->
+
+<!--
+
+ This feature file is intended to contain only third party features that cannot be accommodated in any
+ other feature file. This is a good place to add features like jolokia which no other feature depends on
+ but which provides a utility.
+-->
+<features name="odl-extras-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+    <feature name='odl-extras-all' version='${project.version}' description='OpenDaylight :: Extras :: All'>
+        <feature version="${project.version}">odl-jolokia</feature>
+    </feature>
+    <feature name="odl-jolokia" version="${project.version}" description="Jolokia JMX/HTTP bridge">
+        <feature>http</feature>
+        <bundle>mvn:org.jolokia/jolokia-osgi/${jolokia.version}</bundle>
+    </feature>
+</features>
index ab30b0b61fd11ca2dcc25f45b2843582eba7b330..53b45d28103e5ea02df441083748616341147e2e 100644 (file)
       <classifier>features</classifier>
       <type>xml</type>
     </dependency>
+
+  <dependency>
+      <groupId>org.opendaylight.controller.md</groupId>
+      <artifactId>statistics-manager-config</artifactId>
+      <version>${mdsal.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+  </dependency>
+
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-flow-base</artifactId>
index 05404586309e24af131236d14b83c4c2d6bcb1b0..cf54e8b44636a14be38da5a43efdd95e45fdc59f 100644 (file)
@@ -21,6 +21,7 @@
         <bundle>mvn:org.opendaylight.controller.md/inventory-manager/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.controller.md/forwardingrules-manager/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/liblldp/${sal.version}</bundle>
+        <configfile finalname="${config.configfile.directory}/${config.statistics.manager.configfile}">mvn:org.opendaylight.controller.md/statistics-manager-config/${mdsal.version}/xml/config</configfile>
     </feature>
 
 </features>
index ba938c6a6fb7d88ad143f0639186df04d928ff73..8be9f552f820589125c1641efc8096e5fa78eb0b 100644 (file)
@@ -23,5 +23,6 @@
     <module>akka</module>
     <module>netconf-connector</module>
     <module>restconf</module>
+    <module>extras</module>
   </modules>
-</project>
\ No newline at end of file
+</project>
index b2585adb04908ab7a3ba69419bb45374ff13ef1c..1030be5699c6895bebf5815f22aee86c5b939e81 100644 (file)
@@ -87,6 +87,7 @@
     <controllermanager.northbound.version>0.1.0-SNAPSHOT</controllermanager.northbound.version>
     <devices.web.version>0.5.0-SNAPSHOT</devices.web.version>
     <dummy-console.version>1.2.0-SNAPSHOT</dummy-console.version>
+    <config.statistics.manager.configfile>30-statistics-manager.xml</config.statistics.manager.configfile>
     <eclipse.persistence.version>2.5.0</eclipse.persistence.version>
     <eclipse.jdt.core.compiler.batch.version>3.8.0.I20120518-2145</eclipse.jdt.core.compiler.batch.version>
     <!-- enforcer version -->
index 1148c6bebe5f381d825be0003c6904b3b3e12153..77589ed81dbaaa602199282661194cd63f2b143f 100644 (file)
@@ -76,7 +76,7 @@ public class NeverReconnectStrategyModuleTest extends AbstractConfigTest {
         createInstance();
         final ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
         assertBeanCount(1, FACTORY_NAME);
-        final NeverReconnectStrategyFactoryModuleMXBean mxBean = transaction.newMBeanProxy(
+        final NeverReconnectStrategyFactoryModuleMXBean mxBean = transaction.newMXBeanProxy(
                 transaction.lookupConfigBean(FACTORY_NAME, INSTANCE_NAME), NeverReconnectStrategyFactoryModuleMXBean.class);
         mxBean.setTimeout(200);
         final CommitStatus status = transaction.commit();
@@ -98,7 +98,7 @@ public class NeverReconnectStrategyModuleTest extends AbstractConfigTest {
     private static ObjectName createInstance(final ConfigTransactionJMXClient transaction, final Integer timeout)
             throws InstanceAlreadyExistsException {
         final ObjectName nameCreated = transaction.createModule(FACTORY_NAME, INSTANCE_NAME);
-        final NeverReconnectStrategyFactoryModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated,
+        final NeverReconnectStrategyFactoryModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated,
                 NeverReconnectStrategyFactoryModuleMXBean.class);
         mxBean.setTimeout(timeout);
         mxBean.setExecutor(GlobalEventExecutorUtil.create(transaction));
index cfdf3bff28729e5f80a4c9811316eb04e2b1bcc6..7e3ed5b2dea9d3b25c11e05fbad40a79872b20c1 100644 (file)
@@ -75,7 +75,7 @@ public class ReconnectImmediatelyStrategyModuleTest extends AbstractConfigTest {
         createInstance();
         final ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
         assertBeanCount(1, FACTORY_NAME);
-        final ReconnectImmediatelyStrategyFactoryModuleMXBean mxBean = transaction.newMBeanProxy(
+        final ReconnectImmediatelyStrategyFactoryModuleMXBean mxBean = transaction.newMXBeanProxy(
                 transaction.lookupConfigBean(FACTORY_NAME, INSTANCE_NAME),
                 ReconnectImmediatelyStrategyFactoryModuleMXBean.class);
         mxBean.setReconnectTimeout(200);
@@ -97,7 +97,7 @@ public class ReconnectImmediatelyStrategyModuleTest extends AbstractConfigTest {
     private static ObjectName createInstance(final ConfigTransactionJMXClient transaction, final Integer timeout)
             throws InstanceAlreadyExistsException {
         final ObjectName nameCreated = transaction.createModule(FACTORY_NAME, INSTANCE_NAME);
-        final ReconnectImmediatelyStrategyFactoryModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated,
+        final ReconnectImmediatelyStrategyFactoryModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated,
                 ReconnectImmediatelyStrategyFactoryModuleMXBean.class);
         mxBean.setReconnectTimeout(timeout);
         mxBean.setReconnectExecutor(GlobalEventExecutorUtil.create(transaction));
index 1c068a98e748e76e0404fc5b71c87d97e839f75d..ec8a9d6f29c7e66fd148b4510ea28e0c38240071 100644 (file)
@@ -117,7 +117,7 @@ public class TimedReconnectStrategyModuleTest extends AbstractConfigTest {
         createInstance();
         final ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
         assertBeanCount(1, FACTORY_NAME);
-        final TimedReconnectStrategyFactoryModuleMXBean mxBean = transaction.newMBeanProxy(
+        final TimedReconnectStrategyFactoryModuleMXBean mxBean = transaction.newMXBeanProxy(
                 transaction.lookupConfigBean(FACTORY_NAME, INSTANCE_NAME), TimedReconnectStrategyFactoryModuleMXBean.class);
         assertEquals(mxBean.getMinSleep(), new Long(100));
         mxBean.setMinSleep(200L);
@@ -149,7 +149,7 @@ public class TimedReconnectStrategyModuleTest extends AbstractConfigTest {
             final Integer connectTime, final Long minSleep, final BigDecimal sleepFactor, final Long maxSleep,
             final Long maxAttempts, final Long deadline) throws InstanceAlreadyExistsException {
         final ObjectName nameCreated = transaction.createModule(FACTORY_NAME, instanceName);
-        final TimedReconnectStrategyFactoryModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated,
+        final TimedReconnectStrategyFactoryModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated,
                 TimedReconnectStrategyFactoryModuleMXBean.class);
         mxBean.setConnectTime(connectTime);
         mxBean.setDeadline(deadline);
index 598e6bffee1820b92864b9afec75832779720341..fd8c8d1df0c7b1b250b0454f91c36b12d0cd1f25 100644 (file)
@@ -108,7 +108,7 @@ public class DependentWiringTest extends AbstractParallelAPSPTest {
 
         // test reported apsp number of threads
         TestingParallelAPSPConfigMXBean parallelAPSPRuntimeProxy = configRegistryClient
-                .newMBeanProxy(apspON, TestingParallelAPSPConfigMXBean.class);
+                .newMXBeanProxy(apspON, TestingParallelAPSPConfigMXBean.class);
         assertEquals(
                 (Integer) TestingParallelAPSPImpl.MINIMAL_NUMBER_OF_THREADS,
                 parallelAPSPRuntimeProxy.getMaxNumberOfThreads());
index fcefd06e4da41f73c50b97d0b1e08ccfc324a3cc..0e6a54fdc9b1b9cee4d74fda75fa8154db8a9866 100644 (file)
@@ -15,10 +15,11 @@ import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import javax.annotation.Nullable;
-import javax.management.DynamicMBean;
 import javax.management.InstanceAlreadyExistsException;
 import javax.management.InstanceNotFoundException;
+import javax.management.IntrospectionException;
 import javax.management.ObjectName;
+import javax.management.ReflectionException;
 import org.junit.Test;
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
@@ -37,20 +38,17 @@ public class TwoInterfacesExportTest extends AbstractScheduledTest {
 
     private void assertExists(@Nullable final ConfigTransactionJMXClient transaction,
             final String moduleName, final String instanceName)
-            throws InstanceNotFoundException {
+            throws InstanceNotFoundException, IntrospectionException, ReflectionException {
         if (transaction != null) {
             transaction.lookupConfigBean(moduleName, instanceName);
             // make a dummy call
-            configRegistryClient.newMBeanProxy(
-                    ObjectNameUtil.createTransactionModuleON(
-                            transaction.getTransactionName(), moduleName,
-                            instanceName), DynamicMBean.class).getMBeanInfo();
+            platformMBeanServer.getMBeanInfo(ObjectNameUtil.createTransactionModuleON(
+                    transaction.getTransactionName(), moduleName, instanceName));
         } else {
             configRegistryClient.lookupConfigBean(moduleName, instanceName);
             // make a dummy call
-            configRegistryClient.newMBeanProxy(
-                    ObjectNameUtil.createReadOnlyModuleON(moduleName,
-                            instanceName), DynamicMBean.class).getMBeanInfo();
+            platformMBeanServer.getMBeanInfo(ObjectNameUtil.createReadOnlyModuleON(moduleName,
+                    instanceName));
         }
     }
 
@@ -173,7 +171,7 @@ public class TwoInterfacesExportTest extends AbstractScheduledTest {
 
         ObjectName apspName = transaction.createModule(
                 TestingParallelAPSPModuleFactory.NAME, "apsp1");
-        TestingParallelAPSPConfigMXBean apspProxy = transaction.newMBeanProxy(
+        TestingParallelAPSPConfigMXBean apspProxy = transaction.newMXBeanProxy(
                 apspName, TestingParallelAPSPConfigMXBean.class);
         apspProxy.setThreadPool(scheduledName);
         apspProxy.setSomeParam("someParam");
@@ -190,7 +188,7 @@ public class TwoInterfacesExportTest extends AbstractScheduledTest {
 
         ObjectName apspName = transaction.createModule(
                 TestingParallelAPSPModuleFactory.NAME, "apsp1");
-        TestingParallelAPSPConfigMXBean apspProxy = transaction.newMBeanProxy(
+        TestingParallelAPSPConfigMXBean apspProxy = transaction.newMXBeanProxy(
                 apspName, TestingParallelAPSPConfigMXBean.class);
         apspProxy.setThreadPool(ObjectNameUtil.createReadOnlyModuleON(
                 TestingScheduledThreadPoolModuleFactory.NAME, scheduled1));
index 4ed10036f78e0262442a9986ef14aabbb85db42d..c20d3bfc04090bafbc1b4406c03453c7c353f225 100644 (file)
@@ -212,11 +212,9 @@ public class SimpleConfigurationTest extends AbstractConfigTest {
         ObjectName fixed1name = firstCommit();
 
         // 2, check that configuration was copied to platform
-        DynamicMBean dynamicMBean = configRegistryClient.newMBeanProxy(
-                ObjectNameUtil.withoutTransactionName(fixed1name),
-                DynamicMBean.class);
-        dynamicMBean.getMBeanInfo();
-        assertEquals(numberOfThreads, dynamicMBean.getAttribute("ThreadCount"));
+        ObjectName on = ObjectNameUtil.withoutTransactionName(fixed1name);
+        platformMBeanServer.getMBeanInfo(on);
+        assertEquals(numberOfThreads, platformMBeanServer.getAttribute(on, "ThreadCount"));
 
         // 3, shutdown fixed1 in new transaction
         assertFalse(TestingFixedThreadPool.allExecutors.get(0).isShutdown());
@@ -249,10 +247,10 @@ public class SimpleConfigurationTest extends AbstractConfigTest {
 
         // dynamic config should be removed from platform
         try {
-            dynamicMBean.getMBeanInfo();
+            platformMBeanServer.getMBeanInfo(on);
             fail();
         } catch (Exception e) {
-            assertTrue(e.getCause() instanceof InstanceNotFoundException);
+            assertTrue(e instanceof InstanceNotFoundException);
         }
     }
 
index e89d82a28fd6b3f8876e89724d254691bf90fad3..cb4217c2a43b5840a391a65895188279ed00a236 100644 (file)
@@ -79,7 +79,7 @@ public class GlobalEventExecutorModuleTest extends AbstractConfigTest {
     private ObjectName createInstance(ConfigTransactionJMXClient transaction, String instanceName)
             throws InstanceAlreadyExistsException {
         ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);
-        transaction.newMBeanProxy(nameCreated, GlobalEventExecutorModuleMXBean.class);
+        transaction.newMXBeanProxy(nameCreated, GlobalEventExecutorModuleMXBean.class);
         return nameCreated;
     }
 
index 54c87604a433298824fc33ae12a6dc11732dfa92..d280bcac585a76c6c8915d699466e2c2cefbdb91 100644 (file)
@@ -64,7 +64,7 @@ public class ImmediateEventExecutorModuleTest extends AbstractConfigTest {
     private ObjectName createInstance(ConfigTransactionJMXClient transaction, String instanceName)
             throws InstanceAlreadyExistsException {
         ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);
-        transaction.newMBeanProxy(nameCreated, ImmediateEventExecutorModuleMXBean.class);
+        transaction.newMXBeanProxy(nameCreated, ImmediateEventExecutorModuleMXBean.class);
         return nameCreated;
     }
 
index e44b569759d3b611d35fa730778ca7a16d565a00..f4ca2217cead1947d1f43db90461b2e0a6db7925 100644 (file)
       <type>xml</type>
       <scope>runtime</scope>
     </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>features-extras</artifactId>
+          <version>${project.version}</version>
+          <classifier>features</classifier>
+          <type>xml</type>
+          <scope>runtime</scope>
+      </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>features-flow</artifactId>
index 38756f29060f486fb31198e796045a0eb8a629ee..d21f16c4782a8ba0eac0389fabccaf7e58728a02 100644 (file)
@@ -51,6 +51,7 @@
 
     <module>inventory-manager</module>
     <module>statistics-manager</module>
+    <module>statistics-manager-config</module>
     <module>topology-manager</module>
     <module>forwardingrules-manager</module>
     <module>topology-lldp-discovery</module>
index 6dfa4afd6b6951a351790d0fb87679b40d19dc90..6c65021d86158b22483ada73704f68ba9f83d84c 100644 (file)
@@ -25,6 +25,7 @@ import org.opendaylight.controller.cluster.example.messages.KeyValue;
 import org.opendaylight.controller.cluster.example.messages.KeyValueSaved;
 import org.opendaylight.controller.cluster.example.messages.PrintRole;
 import org.opendaylight.controller.cluster.example.messages.PrintState;
+import org.opendaylight.controller.cluster.notifications.RoleChangeNotifier;
 import org.opendaylight.controller.cluster.raft.ConfigParams;
 import org.opendaylight.controller.cluster.raft.RaftActor;
 import org.opendaylight.controller.cluster.raft.RaftState;
@@ -37,22 +38,23 @@ import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payloa
  */
 public class ExampleActor extends RaftActor {
 
-    private final Map<String, String> state = new HashMap<>();
+    private final Map<String, String> state = new HashMap();
     private final DataPersistenceProvider dataPersistenceProvider;
 
     private long persistIdentifier = 1;
+    private Optional<ActorRef> roleChangeNotifier;
 
 
-    public ExampleActor(final String id, final Map<String, String> peerAddresses,
-        final Optional<ConfigParams> configParams) {
+    public ExampleActor(String id, Map<String, String> peerAddresses,
+        Optional<ConfigParams> configParams) {
         super(id, peerAddresses, configParams);
         this.dataPersistenceProvider = new PersistentDataProvider();
+        roleChangeNotifier = createRoleChangeNotifier(id);
     }
 
     public static Props props(final String id, final Map<String, String> peerAddresses,
         final Optional<ConfigParams> configParams){
         return Props.create(new Creator<ExampleActor>(){
-            private static final long serialVersionUID = 1L;
 
             @Override public ExampleActor create() throws Exception {
                 return new ExampleActor(id, peerAddresses, configParams);
@@ -60,7 +62,7 @@ public class ExampleActor extends RaftActor {
         });
     }
 
-    @Override public void onReceiveCommand(final Object message) throws Exception{
+    @Override public void onReceiveCommand(Object message) throws Exception{
         if(message instanceof KeyValue){
             if(isLeader()) {
                 String persistId = Long.toString(persistIdentifier++);
@@ -82,9 +84,11 @@ public class ExampleActor extends RaftActor {
                 String followers = "";
                 if (getRaftState() == RaftState.Leader || getRaftState() == RaftState.IsolatedLeader) {
                     followers = ((Leader)this.getCurrentBehavior()).printFollowerStates();
-                    LOG.debug("{} = {}, Peers={}, followers={}", getId(), getRaftState(), getPeers(), followers);
+                    LOG.debug("{} = {}, Peers={}, followers={}", getId(), getRaftState(),
+                        getRaftActorContext().getPeerAddresses().keySet(), followers);
                 } else {
-                    LOG.debug("{} = {}, Peers={}", getId(), getRaftState(), getPeers());
+                    LOG.debug("{} = {}, Peers={}", getId(), getRaftState(),
+                        getRaftActorContext().getPeerAddresses().keySet());
                 }
 
 
@@ -95,6 +99,23 @@ public class ExampleActor extends RaftActor {
         }
     }
 
+    protected String getReplicatedLogState() {
+        return "snapshotIndex=" + getRaftActorContext().getReplicatedLog().getSnapshotIndex()
+            + ", snapshotTerm=" + getRaftActorContext().getReplicatedLog().getSnapshotTerm()
+            + ", im-mem journal size=" + getRaftActorContext().getReplicatedLog().size();
+    }
+
+    public Optional<ActorRef> createRoleChangeNotifier(String actorId) {
+        ActorRef exampleRoleChangeNotifier = this.getContext().actorOf(
+            RoleChangeNotifier.getProps(actorId), actorId + "-notifier");
+        return Optional.<ActorRef>of(exampleRoleChangeNotifier);
+    }
+
+    @Override
+    protected Optional<ActorRef> getRoleChangeNotifier() {
+        return roleChangeNotifier;
+    }
+
     @Override protected void applyState(final ActorRef clientActor, final String identifier,
         final Object data) {
         if(data instanceof KeyValue){
@@ -116,19 +137,19 @@ public class ExampleActor extends RaftActor {
         getSelf().tell(new CaptureSnapshotReply(bs), null);
     }
 
-    @Override protected void applySnapshot(final ByteString snapshot) {
+    @Override protected void applySnapshot(ByteString snapshot) {
         state.clear();
         try {
-            state.putAll((Map<String, String>) toObject(snapshot));
+            state.putAll((HashMap) toObject(snapshot));
         } catch (Exception e) {
            LOG.error(e, "Exception in applying snapshot");
         }
         if(LOG.isDebugEnabled()) {
-            LOG.debug("Snapshot applied to state : {}", ((Map<?, ?>) state).size());
+            LOG.debug("Snapshot applied to state : {}", ((HashMap) state).size());
         }
     }
 
-    private ByteString fromObject(final Object snapshot) throws Exception {
+    private ByteString fromObject(Object snapshot) throws Exception {
         ByteArrayOutputStream b = null;
         ObjectOutputStream o = null;
         try {
@@ -148,7 +169,7 @@ public class ExampleActor extends RaftActor {
         }
     }
 
-    private Object toObject(final ByteString bs) throws ClassNotFoundException, IOException {
+    private Object toObject(ByteString bs) throws ClassNotFoundException, IOException {
         Object obj = null;
         ByteArrayInputStream bis = null;
         ObjectInputStream ois = null;
@@ -176,7 +197,7 @@ public class ExampleActor extends RaftActor {
         return dataPersistenceProvider;
     }
 
-    @Override public void onReceiveRecover(final Object message)throws Exception {
+    @Override public void onReceiveRecover(Object message)throws Exception {
         super.onReceiveRecover(message);
     }
 
@@ -185,11 +206,11 @@ public class ExampleActor extends RaftActor {
     }
 
     @Override
-    protected void startLogRecoveryBatch(final int maxBatchSize) {
+    protected void startLogRecoveryBatch(int maxBatchSize) {
     }
 
     @Override
-    protected void appendRecoveredLogEntry(final Payload data) {
+    protected void appendRecoveredLogEntry(Payload data) {
     }
 
     @Override
@@ -201,6 +222,6 @@ public class ExampleActor extends RaftActor {
     }
 
     @Override
-    protected void applyRecoverySnapshot(final ByteString snapshot) {
+    protected void applyRecoverySnapshot(ByteString snapshot) {
     }
 }
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleRoleChangeListener.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleRoleChangeListener.java
new file mode 100644 (file)
index 0000000..c0ee095
--- /dev/null
@@ -0,0 +1,146 @@
+package org.opendaylight.controller.cluster.example;
+
+import akka.actor.Actor;
+import akka.actor.ActorRef;
+import akka.actor.Cancellable;
+import akka.actor.Props;
+import akka.japi.Creator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import org.opendaylight.controller.cluster.common.actor.AbstractUntypedActor;
+import org.opendaylight.controller.cluster.example.messages.RegisterListener;
+import org.opendaylight.controller.cluster.notifications.RegisterRoleChangeListener;
+import org.opendaylight.controller.cluster.notifications.RegisterRoleChangeListenerReply;
+import org.opendaylight.controller.cluster.notifications.RoleChangeNotification;
+import scala.concurrent.Await;
+import scala.concurrent.duration.FiniteDuration;
+
+/**
+ * This is a sample implementation of a Role Change Listener which is an actor, which registers itself to the ClusterRoleChangeNotifier
+ * <p/>
+ * The Role Change listener receives a SetNotifiers message with the notifiers to register itself with.
+ * <p/>
+ * It kicks of a scheduler which sents registration messages to the notifiers, till it gets a RegisterRoleChangeListenerReply
+ * <p/>
+ * If all the notifiers have been regsitered with, then it cancels the scheduler.
+ * It starts the scheduler again when it receives a new registration
+ *
+ */
+public class ExampleRoleChangeListener extends AbstractUntypedActor implements AutoCloseable{
+    // the akka url should be set to the notifiers actor-system and domain.
+    private static final String NOTIFIER_AKKA_URL = "akka.tcp://raft-test@127.0.0.1:2550/user/";
+
+    private Map<String, Boolean> notifierRegistrationStatus = new HashMap<>();
+    private Cancellable registrationSchedule = null;
+    private static final FiniteDuration duration = new FiniteDuration(100, TimeUnit.MILLISECONDS);
+    private static final FiniteDuration schedulerDuration = new FiniteDuration(1, TimeUnit.SECONDS);
+    private final String memberName;
+    private static final String[] shardsToMonitor = new String[] {"example"};
+
+    public ExampleRoleChangeListener(String memberName) {
+        super();
+        scheduleRegistrationListener(schedulerDuration);
+        this.memberName = memberName;
+        populateRegistry(memberName);
+    }
+
+    public static Props getProps(final String memberName) {
+        return Props.create(new Creator<Actor>() {
+            @Override
+            public Actor create() throws Exception {
+                return new ExampleRoleChangeListener(memberName);
+            }
+        });
+    }
+
+    @Override
+    protected void handleReceive(Object message) throws Exception {
+        if (message instanceof RegisterListener) {
+            // called by the scheduler at intervals to register any unregistered notifiers
+            sendRegistrationRequests();
+
+        } else if (message instanceof RegisterRoleChangeListenerReply) {
+            // called by the Notifier
+            handleRegisterRoleChangeListenerReply(getSender().path().toString());
+
+        } else if (message instanceof RoleChangeNotification) {
+            // called by the Notifier
+            RoleChangeNotification notification = (RoleChangeNotification) message;
+
+            LOG.info("Role Change Notification received for member:{}, old role:{}, new role:{}",
+                notification.getMemberId(), notification.getOldRole(), notification.getNewRole());
+
+            // the apps dependent on such notifications can be called here
+            //TODO: add implementation here
+
+        }
+    }
+
+    private void scheduleRegistrationListener(FiniteDuration interval) {
+        LOG.debug("--->scheduleRegistrationListener called.");
+        registrationSchedule = getContext().system().scheduler().schedule(
+            interval, interval, getSelf(), new RegisterListener(),
+            getContext().system().dispatcher(), getSelf());
+
+    }
+
+    private void populateRegistry(String memberName) {
+
+        for (String shard: shardsToMonitor) {
+            String notifier =(new StringBuilder()).append(NOTIFIER_AKKA_URL).append(memberName)
+                .append("/").append(memberName).append("-notifier").toString();
+
+            if (!notifierRegistrationStatus.containsKey(notifier)) {
+                notifierRegistrationStatus.put(notifier, false);
+            }
+        }
+
+        if (!registrationSchedule.isCancelled()) {
+            scheduleRegistrationListener(schedulerDuration);
+        }
+    }
+
+    private void sendRegistrationRequests() {
+        for (Map.Entry<String, Boolean> entry : notifierRegistrationStatus.entrySet()) {
+            if (!entry.getValue()) {
+                try {
+                    LOG.debug("{} registering with {}", getSelf().path().toString(), entry.getKey());
+                    ActorRef notifier = Await.result(
+                        getContext().actorSelection(entry.getKey()).resolveOne(duration), duration);
+
+                    notifier.tell(new RegisterRoleChangeListener(), getSelf());
+
+                } catch (Exception e) {
+                    LOG.error("ERROR!! Unable to send registration request to notifier {}", entry.getKey());
+                }
+            }
+        }
+    }
+
+    private void handleRegisterRoleChangeListenerReply(String senderId) {
+        if (notifierRegistrationStatus.containsKey(senderId)) {
+            notifierRegistrationStatus.put(senderId, true);
+
+            //cancel the schedule when listener is registered with all notifiers
+            if (!registrationSchedule.isCancelled()) {
+                boolean cancelScheduler = true;
+                for (Boolean value : notifierRegistrationStatus.values()) {
+                    cancelScheduler = cancelScheduler & value;
+                }
+                if (cancelScheduler) {
+                    registrationSchedule.cancel();
+                }
+            }
+        } else {
+            LOG.info("Unexpected, RegisterRoleChangeListenerReply received from notifier which is not known to Listener:{}",
+                senderId);
+        }
+    }
+
+
+    @Override
+    public void close() throws Exception {
+        registrationSchedule.cancel();
+    }
+}
index de6169791ed4cb4405e6f47e85e0ed3535155fd1..cd2e4a506ce5365bc45cc89f160695516846b4f2 100644 (file)
@@ -3,15 +3,17 @@ package org.opendaylight.controller.cluster.example;
 import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
 import com.google.common.base.Optional;
-import org.opendaylight.controller.cluster.example.messages.PrintRole;
-import org.opendaylight.controller.cluster.example.messages.PrintState;
-import org.opendaylight.controller.cluster.raft.ConfigParams;
-
+import com.google.common.collect.Lists;
+import com.typesafe.config.ConfigFactory;
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import org.opendaylight.controller.cluster.example.messages.PrintRole;
+import org.opendaylight.controller.cluster.example.messages.PrintState;
+import org.opendaylight.controller.cluster.raft.ConfigParams;
 
 /**
  * This is a test driver for testing akka-raft implementation
@@ -21,7 +23,7 @@ import java.util.concurrent.ConcurrentHashMap;
  */
 public class TestDriver {
 
-    private static final ActorSystem actorSystem = ActorSystem.create();
+
     private static Map<String, String> allPeers = new HashMap<>();
     private static Map<String, ActorRef> clientActorRefs  = new HashMap<String, ActorRef>();
     private static Map<String, ActorRef> actorRefs = new HashMap<String, ActorRef>();
@@ -29,6 +31,9 @@ public class TestDriver {
     private int nameCounter = 0;
     private static ConfigParams configParams = new ExampleConfigParamsImpl();
 
+    private static ActorSystem actorSystem;
+    private static ActorSystem listenerActorSystem;
+
     /**
      * Create nodes, add clients and start logging.
      * Commands
@@ -53,6 +58,13 @@ public class TestDriver {
      * @throws Exception
      */
     public static void main(String[] args) throws Exception {
+
+        actorSystem = ActorSystem.create("raft-test", ConfigFactory
+            .load().getConfig("raft-test"));
+
+        listenerActorSystem = ActorSystem.create("raft-test-listener", ConfigFactory
+            .load().getConfig("raft-test-listener"));
+
         TestDriver td = new TestDriver();
 
         System.out.println("Enter command (type bye to exit):");
@@ -113,6 +125,16 @@ public class TestDriver {
         }
     }
 
+    // create the listener using a separate actor system for each example actor
+    private void createClusterRoleChangeListener(List<String> memberIds) {
+        System.out.println("memberIds="+memberIds);
+        for (String memberId : memberIds) {
+            ActorRef listenerActor = listenerActorSystem.actorOf(
+                ExampleRoleChangeListener.getProps(memberId), memberId + "-role-change-listener");
+            System.out.println("Role Change Listener created:" + listenerActor.path().toString());
+        }
+    }
+
     public static ActorRef createExampleActor(String name) {
         return actorSystem.actorOf(ExampleActor.props(name, withoutPeer(name),
             Optional.of(configParams)), name);
@@ -121,7 +143,7 @@ public class TestDriver {
     public void createNodes(int num) {
         for (int i=0; i < num; i++)  {
             nameCounter = nameCounter + 1;
-            allPeers.put("example-"+nameCounter, "akka://default/user/example-"+nameCounter);
+            allPeers.put("example-"+nameCounter, "akka://raft-test/user/example-"+nameCounter);
         }
 
         for (String s : allPeers.keySet())  {
@@ -130,6 +152,8 @@ public class TestDriver {
             System.out.println("Created node:"+s);
 
         }
+
+        createClusterRoleChangeListener(Lists.newArrayList(allPeers.keySet()));
     }
 
     // add num clients to all nodes in the system
index e0873cc7bae06159f5644f5cda370b1ada78275b..d2862c2baf219acedc921cf0710f2978f7fe85f7 100644 (file)
@@ -9,13 +9,12 @@
 package org.opendaylight.controller.cluster.example.messages;
 
 import com.google.protobuf.GeneratedMessage;
-import org.opendaylight.controller.protobuff.messages.cluster.example.KeyValueMessages;
-import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
-import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
-
 import java.io.Serializable;
 import java.util.HashMap;
 import java.util.Map;
+import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
+import org.opendaylight.controller.protobuff.messages.cluster.example.KeyValueMessages;
+import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
 
 public class KeyValue extends Payload implements Serializable {
     private static final long serialVersionUID = 1L;
@@ -71,4 +70,9 @@ public class KeyValue extends Payload implements Serializable {
         return this;
     }
 
+    @Override
+    public int size() {
+        return this.value.length() + this.key.length();
+    }
+
 }
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/RegisterListener.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/RegisterListener.java
new file mode 100644 (file)
index 0000000..4507f43
--- /dev/null
@@ -0,0 +1,9 @@
+package org.opendaylight.controller.cluster.example.messages;
+
+/**
+ * Message sent by the Example Role Change Listener to itself for registering itself with the notifiers
+ *
+ * This message is sent by the scheduler
+ */
+public class RegisterListener {
+}
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/SetNotifiers.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/SetNotifiers.java
new file mode 100644 (file)
index 0000000..8adc0da
--- /dev/null
@@ -0,0 +1,18 @@
+package org.opendaylight.controller.cluster.example.messages;
+
+import java.util.List;
+
+/**
+ * Created by kramesha on 11/18/14.
+ */
+public class SetNotifiers {
+    private List<String> notifierList;
+
+    public SetNotifiers(List<String> notifierList) {
+        this.notifierList = notifierList;
+    }
+
+    public List<String> getNotifierList() {
+        return notifierList;
+    }
+}
index a2c9d660ad8d2472f7b9a83ab3f175b1883ad1f6..653520c2e47db4be19de53c9e3a42099904298d8 100644 (file)
@@ -26,6 +26,7 @@ public abstract class AbstractReplicatedLogImpl implements ReplicatedLog {
     protected ArrayList<ReplicatedLogEntry> snapshottedJournal;
     protected long previousSnapshotIndex = -1;
     protected long previousSnapshotTerm = -1;
+    protected int dataSize = 0;
 
     public AbstractReplicatedLogImpl(long snapshotIndex,
         long snapshotTerm, List<ReplicatedLogEntry> unAppliedEntries) {
@@ -198,6 +199,7 @@ public abstract class AbstractReplicatedLogImpl implements ReplicatedLog {
         snapshottedJournal = null;
         previousSnapshotIndex = -1;
         previousSnapshotTerm = -1;
+        dataSize = 0;
     }
 
     @Override
index 433c3f7e4b832d081de375e8b792f19f1ca4caa4..4245cf10f778fc81fe3181b0db5d9b825ea23a4c 100644 (file)
@@ -28,6 +28,14 @@ public interface ConfigParams {
      */
     long getSnapshotBatchCount();
 
+    /**
+     * The percentage of total memory in the in-memory Raft log before a snapshot
+     * is to be taken
+     *
+     * @return int
+     */
+    int getSnapshotDataThresholdPercentage();
+
     /**
      * The interval at which a heart beat message will be sent to the remote
      * RaftActor
index a2092234d54134fbe3de765d17041ad766d689c4..3a6bdbf0a3ec75151313c6b9a00143ea1d15cbd0 100644 (file)
@@ -7,9 +7,8 @@
  */
 package org.opendaylight.controller.cluster.raft;
 
-import scala.concurrent.duration.FiniteDuration;
-
 import java.util.concurrent.TimeUnit;
+import scala.concurrent.duration.FiniteDuration;
 
 /**
  * Default implementation of the ConfigParams
@@ -47,6 +46,10 @@ public class DefaultConfigParamsImpl implements ConfigParams {
     private FiniteDuration isolatedLeaderCheckInterval =
         new FiniteDuration(HEART_BEAT_INTERVAL.length() * 1000, HEART_BEAT_INTERVAL.unit());
 
+    // 12 is just an arbitrary percentage. This is the amount of the total memory that a raft actor's
+    // in-memory journal can use before it needs to snapshot
+    private int snapshotDataThresholdPercentage = 12;
+
     public void setHeartBeatInterval(FiniteDuration heartBeatInterval) {
         this.heartBeatInterval = heartBeatInterval;
     }
@@ -55,6 +58,10 @@ public class DefaultConfigParamsImpl implements ConfigParams {
         this.snapshotBatchCount = snapshotBatchCount;
     }
 
+    public void setSnapshotDataThresholdPercentage(int snapshotDataThresholdPercentage){
+        this.snapshotDataThresholdPercentage = snapshotDataThresholdPercentage;
+    }
+
     public void setJournalRecoveryLogBatchSize(int journalRecoveryLogBatchSize) {
         this.journalRecoveryLogBatchSize = journalRecoveryLogBatchSize;
     }
@@ -68,6 +75,12 @@ public class DefaultConfigParamsImpl implements ConfigParams {
         return snapshotBatchCount;
     }
 
+    @Override
+    public int getSnapshotDataThresholdPercentage() {
+        return snapshotDataThresholdPercentage;
+    }
+
+
     @Override
     public FiniteDuration getHeartBeatInterval() {
         return heartBeatInterval;
index 042b9fb56995d259d99a1559d4a3e3d5389fdba3..3b8469207798952298a6f304a2b07e18153e4ea2 100644 (file)
@@ -22,8 +22,11 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
 import com.google.common.base.Stopwatch;
 import com.google.protobuf.ByteString;
+import java.io.Serializable;
+import java.util.Map;
 import org.opendaylight.controller.cluster.DataPersistenceProvider;
 import org.opendaylight.controller.cluster.common.actor.AbstractUntypedPersistentActor;
+import org.opendaylight.controller.cluster.notifications.RoleChanged;
 import org.opendaylight.controller.cluster.raft.base.messages.ApplyLogEntries;
 import org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot;
 import org.opendaylight.controller.cluster.raft.base.messages.ApplyState;
@@ -41,9 +44,6 @@ import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
 import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
 import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
 
-import java.io.Serializable;
-import java.util.Map;
-
 /**
  * RaftActor encapsulates a state machine that needs to be kept synchronized
  * in a cluster. It implements the RAFT algorithm as described in the paper
@@ -169,8 +169,10 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor {
                 deleteSnapshots(new SnapshotSelectionCriteria(scala.Long.MaxValue(), scala.Long.MaxValue()));
 
                 onRecoveryComplete();
+
+                RaftActorBehavior oldBehavior = currentBehavior;
                 currentBehavior = new Follower(context);
-                onStateChanged();
+                handleBehaviorChange(oldBehavior, currentBehavior);
             }
         }
     }
@@ -269,8 +271,9 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor {
             replicatedLog.lastIndex(), replicatedLog.snapshotIndex,
             replicatedLog.snapshotTerm, replicatedLog.size());
 
+        RaftActorBehavior oldBehavior = currentBehavior;
         currentBehavior = new Follower(context);
-        onStateChanged();
+        handleBehaviorChange(oldBehavior, currentBehavior);
     }
 
     @Override public void handleCommand(Object message) {
@@ -366,26 +369,26 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor {
             RaftActorBehavior oldBehavior = currentBehavior;
             currentBehavior = currentBehavior.handleMessage(getSender(), message);
 
-            if(oldBehavior != currentBehavior){
-                onStateChanged();
-            }
-
-            onLeaderChanged(oldBehavior.getLeaderId(), currentBehavior.getLeaderId());
+            handleBehaviorChange(oldBehavior, currentBehavior);
         }
     }
 
-    public java.util.Set<String> getPeers() {
-
-        return context.getPeerAddresses().keySet();
-    }
+    private void handleBehaviorChange(RaftActorBehavior oldBehavior, RaftActorBehavior currentBehavior) {
+        if (oldBehavior != currentBehavior){
+            onStateChanged();
+        }
+        if (oldBehavior != null) {
+            // it can happen that the state has not changed but the leader has changed.
+            onLeaderChanged(oldBehavior.getLeaderId(), currentBehavior.getLeaderId());
 
-    protected String getReplicatedLogState() {
-        return "snapshotIndex=" + context.getReplicatedLog().getSnapshotIndex()
-            + ", snapshotTerm=" + context.getReplicatedLog().getSnapshotTerm()
-            + ", im-mem journal size=" + context.getReplicatedLog().size();
+            if (getRoleChangeNotifier().isPresent() && oldBehavior.state() != currentBehavior.state()) {
+                // we do not want to notify when the behavior/role is set for the first time (i.e follower)
+                getRoleChangeNotifier().get().tell(new RoleChanged(getId(), oldBehavior.state().name(),
+                    currentBehavior.state().name()), getSelf());
+            }
+        }
     }
 
-
     /**
      * When a derived RaftActor needs to persist something it must call
      * persistData.
@@ -578,6 +581,12 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor {
 
     protected abstract DataPersistenceProvider persistence();
 
+    /**
+     * Notifier Actor for this RaftActor to notify when a role change happens
+     * @return ActorRef - ActorRef of the notifier or Optional.absent if none.
+     */
+    protected abstract Optional<ActorRef> getRoleChangeNotifier();
+
     protected void onLeaderChanged(String oldLeader, String newLeader){};
 
     private void trimPersistentData(long sequenceNumber) {
@@ -667,6 +676,10 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor {
                 @Override public void apply(DeleteEntries param)
                     throws Exception {
                     //FIXME : Doing nothing for now
+                    dataSize = 0;
+                    for(ReplicatedLogEntry entry : journal){
+                        dataSize += entry.size();
+                    }
                 }
             });
         }
@@ -676,6 +689,11 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor {
             appendAndPersist(null, null, replicatedLogEntry);
         }
 
+        @Override
+        public int dataSize() {
+            return dataSize;
+        }
+
         public void appendAndPersist(final ActorRef clientActor,
             final String identifier,
             final ReplicatedLogEntry replicatedLogEntry) {
@@ -696,9 +714,15 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor {
                 new Procedure<ReplicatedLogEntry>() {
                     @Override
                     public void apply(ReplicatedLogEntry evt) throws Exception {
+                        dataSize += replicatedLogEntry.size();
+
+                        long dataThreshold = Runtime.getRuntime().totalMemory() *
+                                getRaftActorContext().getConfigParams().getSnapshotDataThresholdPercentage() / 100;
+
                         // when a snaphsot is being taken, captureSnapshot != null
                         if (hasSnapshotCaptureInitiated == false &&
-                            journal.size() % context.getConfigParams().getSnapshotBatchCount() == 0) {
+                                ( journal.size() % context.getConfigParams().getSnapshotBatchCount() == 0 ||
+                                        dataSize > dataThreshold)) {
 
                             LOG.info("Initiating Snapshot Capture..");
                             long lastAppliedIndex = -1;
@@ -843,4 +867,5 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor {
     protected RaftActorBehavior getCurrentBehavior() {
         return currentBehavior;
     }
+
 }
index 7ee85322a60f9ec93a4effc6e9379bd52d77a6ed..80b7ad90d05dbb1e9fe45ec57a65a44dedfe4463 100644 (file)
@@ -171,4 +171,9 @@ public interface ReplicatedLog {
      * Restores the replicated log to a state in the event of a save snapshot failure
      */
     public void snapshotRollback();
+
+    /**
+     * Size of the data in the log (in bytes)
+     */
+    public int dataSize();
 }
index f501c4d37f1f864c7a0551c119403d2b76457d1d..19796097364f3a2d321b11edb281834055f97a16 100644 (file)
@@ -34,4 +34,13 @@ public interface ReplicatedLogEntry {
      * @return
      */
     long getIndex();
+
+    /**
+     * The size of the entry in bytes.
+     *
+     * An approximate number may be good enough.
+     *
+     * @return
+     */
+    int size();
 }
index ceb5633d4d2deaedb8029a4eb9e7ee3864f68035..986c7f382c44f00405abb7d62394cda548e2a66c 100644 (file)
@@ -8,9 +8,8 @@
 
 package org.opendaylight.controller.cluster.raft;
 
-import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
-
 import java.io.Serializable;
+import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
 
 public class ReplicatedLogImplEntry implements ReplicatedLogEntry,
     Serializable {
@@ -39,6 +38,11 @@ public class ReplicatedLogImplEntry implements ReplicatedLogEntry,
         return index;
     }
 
+    @Override
+    public int size() {
+        return getData().size();
+    }
+
     @Override public String toString() {
         return "Entry{" +
             "index=" + index +
index d85ac8ef67ded21d6140bb42512ba5fa6eb2165d..e5c5dc752d3a257e9ce2f5852bf3350b006b8116 100644 (file)
@@ -67,6 +67,16 @@ import scala.concurrent.duration.FiniteDuration;
  * set commitIndex = N (§5.3, Â§5.4).
  */
 public abstract class AbstractLeader extends AbstractRaftActorBehavior {
+
+    // The index of the first chunk that is sent when installing a snapshot
+    public static final int FIRST_CHUNK_INDEX = 1;
+
+    // The index that the follower should respond with if it needs the install snapshot to be reset
+    public static final int INVALID_CHUNK_INDEX = -1;
+
+    // This would be passed as the hash code of the last chunk when sending the first chunk
+    public static final int INITIAL_LAST_CHUNK_HASH_CODE = -1;
+
     protected final Map<String, FollowerLogInformation> followerToLog = new HashMap<>();
     protected final Map<String, FollowerToSnapshot> mapFollowerToSnapshot = new HashMap<>();
 
@@ -332,6 +342,7 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior {
                         "sending snapshot chunk failed, Will retry, Chunk:{}",
                     reply.getChunkIndex()
                 );
+
                 followerToSnapshot.markSendStatus(false);
             }
 
@@ -341,6 +352,12 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior {
                     " or Chunk Index in InstallSnapshotReply not matching {} != {}",
                 followerToSnapshot.getChunkIndex(), reply.getChunkIndex()
             );
+
+            if(reply.getChunkIndex() == INVALID_CHUNK_INDEX){
+                // Since the Follower did not find this index to be valid we should reset the follower snapshot
+                // so that Installing the snapshot can resume from the beginning
+                followerToSnapshot.reset();
+            }
         }
     }
 
@@ -539,7 +556,8 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior {
                         context.getReplicatedLog().getSnapshotTerm(),
                         getNextSnapshotChunk(followerId,snapshot.get()),
                         mapFollowerToSnapshot.get(followerId).incrementChunkIndex(),
-                        mapFollowerToSnapshot.get(followerId).getTotalChunks()
+                        mapFollowerToSnapshot.get(followerId).getTotalChunks(),
+                        Optional.of(mapFollowerToSnapshot.get(followerId).getLastChunkHashCode())
                     ).toSerializable(),
                     actor()
                 );
@@ -636,11 +654,11 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior {
         private boolean replyStatus = false;
         private int chunkIndex;
         private int totalChunks;
+        private int lastChunkHashCode = AbstractLeader.INITIAL_LAST_CHUNK_HASH_CODE;
+        private int nextChunkHashCode = AbstractLeader.INITIAL_LAST_CHUNK_HASH_CODE;
 
         public FollowerToSnapshot(ByteString snapshotBytes) {
             this.snapshotBytes = snapshotBytes;
-            replyReceivedForOffset = -1;
-            chunkIndex = 1;
             int size = snapshotBytes.size();
             totalChunks = ( size / context.getConfigParams().getSnapshotChunkSize()) +
                 ((size % context.getConfigParams().getSnapshotChunkSize()) > 0 ? 1 : 0);
@@ -648,6 +666,8 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior {
                 LOG.debug("Snapshot {} bytes, total chunks to send:{}",
                     size, totalChunks);
             }
+            replyReceivedForOffset = -1;
+            chunkIndex = AbstractLeader.FIRST_CHUNK_INDEX;
         }
 
         public ByteString getSnapshotBytes() {
@@ -692,6 +712,7 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior {
                 // if the chunk sent was successful
                 replyReceivedForOffset = offset;
                 replyStatus = true;
+                lastChunkHashCode = nextChunkHashCode;
             } else {
                 // if the chunk sent was failure
                 replyReceivedForOffset = offset;
@@ -715,8 +736,24 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior {
                 LOG.debug("length={}, offset={},size={}",
                     snapshotLength, start, size);
             }
-            return getSnapshotBytes().substring(start, start + size);
+            ByteString substring = getSnapshotBytes().substring(start, start + size);
+            nextChunkHashCode = substring.hashCode();
+            return substring;
+        }
+
+        /**
+         * reset should be called when the Follower needs to be sent the snapshot from the beginning
+         */
+        public void reset(){
+            offset = 0;
+            replyStatus = false;
+            replyReceivedForOffset = offset;
+            chunkIndex = AbstractLeader.FIRST_CHUNK_INDEX;
+            lastChunkHashCode = AbstractLeader.INITIAL_LAST_CHUNK_HASH_CODE;
+        }
 
+        public int getLastChunkHashCode() {
+            return lastChunkHashCode;
         }
     }
 
index 7ada8b31c54f75c9c8f8dc9ce3456260d77af80a..b1c73f6f4155e045935fa37912245e3d03d45fc9 100644 (file)
@@ -9,7 +9,9 @@
 package org.opendaylight.controller.cluster.raft.behaviors;
 
 import akka.actor.ActorRef;
+import com.google.common.annotations.VisibleForTesting;
 import com.google.protobuf.ByteString;
+import java.util.ArrayList;
 import org.opendaylight.controller.cluster.raft.RaftActorContext;
 import org.opendaylight.controller.cluster.raft.RaftState;
 import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
@@ -23,8 +25,6 @@ import org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply;
 import org.opendaylight.controller.cluster.raft.messages.RaftRPC;
 import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
 
-import java.util.ArrayList;
-
 /**
  * The behavior of a RaftActor in the Follower state
  * <p/>
@@ -36,7 +36,8 @@ import java.util.ArrayList;
  * </ul>
  */
 public class Follower extends AbstractRaftActorBehavior {
-    private ByteString snapshotChunksCollected = ByteString.EMPTY;
+
+    private SnapshotTracker snapshotTracker = null;
 
     public Follower(RaftActorContext context) {
         super(context);
@@ -280,48 +281,54 @@ public class Follower extends AbstractRaftActorBehavior {
             );
         }
 
-        try {
-            if (installSnapshot.getChunkIndex() == installSnapshot.getTotalChunks()) {
-                // this is the last chunk, create a snapshot object and apply
-
-                snapshotChunksCollected = snapshotChunksCollected.concat(installSnapshot.getData());
-                if(LOG.isDebugEnabled()) {
-                    LOG.debug("Last chunk received: snapshotChunksCollected.size:{}",
-                            snapshotChunksCollected.size());
-                }
+        if(snapshotTracker == null){
+            snapshotTracker = new SnapshotTracker(LOG, installSnapshot.getTotalChunks());
+        }
 
-                Snapshot snapshot = Snapshot.create(snapshotChunksCollected.toByteArray(),
-                    new ArrayList<ReplicatedLogEntry>(),
-                    installSnapshot.getLastIncludedIndex(),
-                    installSnapshot.getLastIncludedTerm(),
-                    installSnapshot.getLastIncludedIndex(),
-                    installSnapshot.getLastIncludedTerm());
+        try {
+            if(snapshotTracker.addChunk(installSnapshot.getChunkIndex(), installSnapshot.getData(),
+                    installSnapshot.getLastChunkHashCode())){
+                Snapshot snapshot = Snapshot.create(snapshotTracker.getSnapshot(),
+                        new ArrayList<ReplicatedLogEntry>(),
+                        installSnapshot.getLastIncludedIndex(),
+                        installSnapshot.getLastIncludedTerm(),
+                        installSnapshot.getLastIncludedIndex(),
+                        installSnapshot.getLastIncludedTerm());
 
                 actor().tell(new ApplySnapshot(snapshot), actor());
 
-            } else {
-                // we have more to go
-                snapshotChunksCollected = snapshotChunksCollected.concat(installSnapshot.getData());
+                snapshotTracker = null;
 
-                if(LOG.isDebugEnabled()) {
-                    LOG.debug("Chunk={},snapshotChunksCollected.size:{}",
-                        installSnapshot.getChunkIndex(), snapshotChunksCollected.size());
-                }
             }
 
             sender.tell(new InstallSnapshotReply(
-                currentTerm(), context.getId(), installSnapshot.getChunkIndex(),
-                true), actor());
+                    currentTerm(), context.getId(), installSnapshot.getChunkIndex(),
+                    true), actor());
+
+        } catch (SnapshotTracker.InvalidChunkException e) {
+
+            sender.tell(new InstallSnapshotReply(currentTerm(), context.getId(),
+                    -1, false), actor());
+            snapshotTracker = null;
+
+        } catch (Exception e){
 
-        } catch (Exception e) {
             LOG.error(e, "Exception in InstallSnapshot of follower:");
             //send reply with success as false. The chunk will be sent again on failure
             sender.tell(new InstallSnapshotReply(currentTerm(), context.getId(),
-                installSnapshot.getChunkIndex(), false), actor());
+                    installSnapshot.getChunkIndex(), false), actor());
+
         }
     }
 
     @Override public void close() throws Exception {
         stopElection();
     }
+
+    @VisibleForTesting
+    ByteString getSnapshotChunksCollected(){
+        return snapshotTracker != null ? snapshotTracker.getCollectedChunks() : ByteString.EMPTY;
+    }
+
+
 }
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/SnapshotTracker.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/SnapshotTracker.java
new file mode 100644 (file)
index 0000000..26fbde0
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  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
+ */
+
+package org.opendaylight.controller.cluster.raft.behaviors;
+
+import akka.event.LoggingAdapter;
+import com.google.common.base.Optional;
+import com.google.protobuf.ByteString;
+
+/**
+ * SnapshotTracker does house keeping for a snapshot that is being installed in chunks on the Follower
+ */
+public class SnapshotTracker {
+    private final LoggingAdapter LOG;
+    private final int totalChunks;
+    private ByteString collectedChunks = ByteString.EMPTY;
+    private int lastChunkIndex = AbstractLeader.FIRST_CHUNK_INDEX - 1;
+    private boolean sealed = false;
+    private int lastChunkHashCode = AbstractLeader.INITIAL_LAST_CHUNK_HASH_CODE;
+
+    SnapshotTracker(LoggingAdapter LOG, int totalChunks){
+        this.LOG = LOG;
+        this.totalChunks = totalChunks;
+    }
+
+    /**
+     * Adds a chunk to the tracker
+     *
+     * @param chunkIndex
+     * @param chunk
+     * @return true when the lastChunk is received
+     * @throws InvalidChunkException
+     */
+    boolean addChunk(int chunkIndex, ByteString chunk, Optional<Integer> lastChunkHashCode) throws InvalidChunkException{
+        if(sealed){
+            throw new InvalidChunkException("Invalid chunk received with chunkIndex " + chunkIndex + " all chunks already received");
+        }
+
+        if(lastChunkIndex + 1 != chunkIndex){
+            throw new InvalidChunkException("Expected chunkIndex " + (lastChunkIndex + 1) + " got " + chunkIndex);
+        }
+
+        if(lastChunkHashCode.isPresent()){
+            if(lastChunkHashCode.get() != this.lastChunkHashCode){
+                throw new InvalidChunkException("The hash code of the recorded last chunk does not match " +
+                        "the senders hash code expected " + lastChunkHashCode + " was " + lastChunkHashCode.get());
+            }
+        }
+
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("Chunk={},collectedChunks.size:{}",
+                    chunkIndex, collectedChunks.size());
+        }
+
+        sealed = (chunkIndex == totalChunks);
+        lastChunkIndex = chunkIndex;
+        collectedChunks = collectedChunks.concat(chunk);
+        this.lastChunkHashCode = chunk.hashCode();
+        return sealed;
+    }
+
+    byte[] getSnapshot(){
+        if(!sealed) {
+            throw new IllegalStateException("lastChunk not received yet");
+        }
+
+        return collectedChunks.toByteArray();
+    }
+
+    ByteString getCollectedChunks(){
+        return collectedChunks;
+    }
+
+    public static class InvalidChunkException extends Exception {
+        InvalidChunkException(String message){
+            super(message);
+        }
+    }
+
+}
index 3c4e8117c798502d7f894709df052acb46df6c53..6337f8f6dce4f9cae5f223c4178f5095fb902c82 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.controller.cluster.raft.messages;
 
+import com.google.common.base.Optional;
 import com.google.protobuf.ByteString;
 import org.opendaylight.controller.protobuff.messages.cluster.raft.InstallSnapshotMessages;
 
@@ -22,9 +23,10 @@ public class InstallSnapshot extends AbstractRaftRPC {
     private final ByteString data;
     private final int chunkIndex;
     private final int totalChunks;
+    private final Optional<Integer> lastChunkHashCode;
 
     public InstallSnapshot(long term, String leaderId, long lastIncludedIndex,
-        long lastIncludedTerm, ByteString data, int chunkIndex, int totalChunks) {
+        long lastIncludedTerm, ByteString data, int chunkIndex, int totalChunks, Optional<Integer> lastChunkHashCode) {
         super(term);
         this.leaderId = leaderId;
         this.lastIncludedIndex = lastIncludedIndex;
@@ -32,8 +34,15 @@ public class InstallSnapshot extends AbstractRaftRPC {
         this.data = data;
         this.chunkIndex = chunkIndex;
         this.totalChunks = totalChunks;
+        this.lastChunkHashCode = lastChunkHashCode;
     }
 
+    public InstallSnapshot(long term, String leaderId, long lastIncludedIndex,
+                           long lastIncludedTerm, ByteString data, int chunkIndex, int totalChunks) {
+        this(term, leaderId, lastIncludedIndex, lastIncludedTerm, data, chunkIndex, totalChunks, Optional.<Integer>absent());
+    }
+
+
     public String getLeaderId() {
         return leaderId;
     }
@@ -58,25 +67,38 @@ public class InstallSnapshot extends AbstractRaftRPC {
         return totalChunks;
     }
 
-    public <T extends Object> Object toSerializable(){
-        return InstallSnapshotMessages.InstallSnapshot.newBuilder()
-            .setLeaderId(this.getLeaderId())
-            .setChunkIndex(this.getChunkIndex())
-            .setData(this.getData())
-            .setLastIncludedIndex(this.getLastIncludedIndex())
-            .setLastIncludedTerm(this.getLastIncludedTerm())
-            .setTotalChunks(this.getTotalChunks()).build();
+    public Optional<Integer> getLastChunkHashCode() {
+        return lastChunkHashCode;
+    }
 
+    public <T extends Object> Object toSerializable(){
+        InstallSnapshotMessages.InstallSnapshot.Builder builder = InstallSnapshotMessages.InstallSnapshot.newBuilder()
+                .setLeaderId(this.getLeaderId())
+                .setChunkIndex(this.getChunkIndex())
+                .setData(this.getData())
+                .setLastIncludedIndex(this.getLastIncludedIndex())
+                .setLastIncludedTerm(this.getLastIncludedTerm())
+                .setTotalChunks(this.getTotalChunks());
+
+        if(lastChunkHashCode.isPresent()){
+            builder.setLastChunkHashCode(lastChunkHashCode.get());
+        }
+        return builder.build();
     }
 
     public static InstallSnapshot fromSerializable (Object o) {
         InstallSnapshotMessages.InstallSnapshot from =
             (InstallSnapshotMessages.InstallSnapshot) o;
 
+        Optional<Integer> lastChunkHashCode = Optional.absent();
+        if(from.hasLastChunkHashCode()){
+            lastChunkHashCode = Optional.of(from.getLastChunkHashCode());
+        }
+
         InstallSnapshot installSnapshot = new InstallSnapshot(from.getTerm(),
             from.getLeaderId(), from.getLastIncludedIndex(),
             from.getLastIncludedTerm(), from.getData(),
-            from.getChunkIndex(), from.getTotalChunks());
+            from.getChunkIndex(), from.getTotalChunks(), lastChunkHashCode);
 
         return installSnapshot;
     }
index 9e42a13c6a0b1d948ff546c28f2f41bf894ff9d2..b2132b88b0c4f062414cf57a42fc8efdc3eb88dc 100644 (file)
@@ -13,8 +13,67 @@ akka {
 
         serialization-bindings {
             "org.opendaylight.controller.cluster.raft.ReplicatedLogImplEntry" = java
+            "org.opendaylight.controller.cluster.notifications.RegisterRoleChangeListener" = java
             "com.google.protobuf.Message" = proto
             "com.google.protobuf.GeneratedMessage" = proto
         }
     }
 }
+
+raft-test {
+    akka {
+
+        loglevel = "DEBUG"
+
+        actor {
+            # enable to test serialization only.
+            # serialize-messages = on
+
+            provider = "akka.remote.RemoteActorRefProvider"
+
+            serializers {
+              java  = "akka.serialization.JavaSerializer"
+              proto = "akka.remote.serialization.ProtobufSerializer"
+            }
+
+            serialization-bindings {
+                "org.opendaylight.controller.cluster.raft.ReplicatedLogImplEntry" = java
+                "org.opendaylight.controller.cluster.notifications.RegisterRoleChangeListener" = java
+                "com.google.protobuf.Message" = proto
+                "com.google.protobuf.GeneratedMessage" = proto
+            }
+        }
+
+        remote {
+                        log-remote-lifecycle-events = off
+                        netty.tcp {
+                            hostname = "127.0.0.1"
+                            port = 2550
+                        }
+                    }
+    }
+}
+
+raft-test-listener {
+
+  akka {
+    loglevel = "DEBUG"
+
+    actor {
+        provider = "akka.remote.RemoteActorRefProvider"
+    }
+
+    remote {
+        log-remote-lifecycle-events = off
+        netty.tcp {
+            hostname = "127.0.0.1"
+            port = 2554
+        }
+    }
+
+    member-id = "member-1"
+  }
+}
+
+
+
index 398a2e9b3651de7846eb36830b5b3410f71a254f..d95c9d502712159334171301868ee9af4cfa99d7 100644 (file)
@@ -164,6 +164,11 @@ public class AbstractReplicatedLogImplTest {
             this.snapshotTerm = snapshotTerm;
         }
 
+        @Override
+        public int dataSize() {
+            return -1;
+        }
+
         public List<ReplicatedLogEntry> getEntriesTill(final int index) {
             return journal.subList(0, index);
         }
index 562ca213a950123d876668fca5c47da4ea031995..2424d4d557f7f1dc58e65a1718e44a6a84db501f 100644 (file)
@@ -16,13 +16,12 @@ import akka.event.Logging;
 import akka.event.LoggingAdapter;
 import com.google.common.base.Preconditions;
 import com.google.protobuf.GeneratedMessage;
-import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
-import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
-import org.opendaylight.controller.protobuff.messages.cluster.raft.test.MockPayloadMessages;
-
 import java.io.Serializable;
 import java.util.HashMap;
 import java.util.Map;
+import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
+import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
+import org.opendaylight.controller.protobuff.messages.cluster.raft.test.MockPayloadMessages;
 
 public class MockRaftActorContext implements RaftActorContext {
 
@@ -192,6 +191,11 @@ public class MockRaftActorContext implements RaftActorContext {
             append(replicatedLogEntry);
         }
 
+        @Override
+        public int dataSize() {
+            return -1;
+        }
+
         @Override public void removeFromAndPersist(long index) {
             removeFrom(index);
         }
@@ -222,6 +226,11 @@ public class MockRaftActorContext implements RaftActorContext {
             return this;
         }
 
+        @Override
+        public int size() {
+            return value.length();
+        }
+
         @Override public String getClientPayloadClassName() {
             return MockPayload.class.getName();
         }
@@ -256,6 +265,11 @@ public class MockRaftActorContext implements RaftActorContext {
         @Override public long getIndex() {
             return index;
         }
+
+        @Override
+        public int size() {
+            return getData().size();
+        }
     }
 
     public static class MockReplicatedLogBuilder {
index 9eb2fb757bd2da0c6b2ce48ebbfeb72471ef48c1..c833a86e9b825c926002ce5fc5b163438a6a4ce0 100644 (file)
@@ -21,11 +21,25 @@ import com.google.common.base.Optional;
 import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.Uninterruptibles;
 import com.google.protobuf.ByteString;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.DataPersistenceProvider;
 import org.opendaylight.controller.cluster.datastore.DataPersistenceProviderMonitor;
+import org.opendaylight.controller.cluster.notifications.RoleChanged;
 import org.opendaylight.controller.cluster.raft.base.messages.ApplyLogEntries;
 import org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot;
 import org.opendaylight.controller.cluster.raft.base.messages.ApplyState;
@@ -36,27 +50,13 @@ import org.opendaylight.controller.cluster.raft.behaviors.Leader;
 import org.opendaylight.controller.cluster.raft.client.messages.FindLeader;
 import org.opendaylight.controller.cluster.raft.client.messages.FindLeaderReply;
 import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
+import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
 import org.opendaylight.controller.cluster.raft.utils.MockAkkaJournal;
 import org.opendaylight.controller.cluster.raft.utils.MockSnapshotStore;
 import scala.concurrent.Await;
 import scala.concurrent.Future;
 import scala.concurrent.duration.Duration;
 import scala.concurrent.duration.FiniteDuration;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
@@ -83,6 +83,9 @@ public class RaftActorTest extends AbstractActorTest {
 
         private final DataPersistenceProvider dataPersistenceProvider;
         private final RaftActor delegate;
+        private final CountDownLatch recoveryComplete = new CountDownLatch(1);
+        private final List<Object> state;
+        private ActorRef roleChangeNotifier;
 
         public static final class MockRaftActorCreator implements Creator<MockRaftActor> {
             private static final long serialVersionUID = 1L;
@@ -90,25 +93,27 @@ public class RaftActorTest extends AbstractActorTest {
             private final String id;
             private final Optional<ConfigParams> config;
             private final DataPersistenceProvider dataPersistenceProvider;
+            private final ActorRef roleChangeNotifier;
 
             private MockRaftActorCreator(Map<String, String> peerAddresses, String id,
-                    Optional<ConfigParams> config, DataPersistenceProvider dataPersistenceProvider) {
+                Optional<ConfigParams> config, DataPersistenceProvider dataPersistenceProvider,
+                ActorRef roleChangeNotifier) {
                 this.peerAddresses = peerAddresses;
                 this.id = id;
                 this.config = config;
                 this.dataPersistenceProvider = dataPersistenceProvider;
+                this.roleChangeNotifier = roleChangeNotifier;
             }
 
             @Override
             public MockRaftActor create() throws Exception {
-                return new MockRaftActor(id, peerAddresses, config, dataPersistenceProvider);
+                MockRaftActor mockRaftActor = new MockRaftActor(id, peerAddresses, config,
+                    dataPersistenceProvider);
+                mockRaftActor.roleChangeNotifier = this.roleChangeNotifier;
+                return mockRaftActor;
             }
         }
 
-        private final CountDownLatch recoveryComplete = new CountDownLatch(1);
-
-        private final List<Object> state;
-
         public MockRaftActor(String id, Map<String, String> peerAddresses, Optional<ConfigParams> config, DataPersistenceProvider dataPersistenceProvider) {
             super(id, peerAddresses, config);
             state = new ArrayList<>();
@@ -134,23 +139,24 @@ public class RaftActorTest extends AbstractActorTest {
 
         public static Props props(final String id, final Map<String, String> peerAddresses,
                 Optional<ConfigParams> config){
-            return Props.create(new MockRaftActorCreator(peerAddresses, id, config, null));
+            return Props.create(new MockRaftActorCreator(peerAddresses, id, config, null, null));
         }
 
         public static Props props(final String id, final Map<String, String> peerAddresses,
                                   Optional<ConfigParams> config, DataPersistenceProvider dataPersistenceProvider){
-            return Props.create(new MockRaftActorCreator(peerAddresses, id, config, dataPersistenceProvider));
+            return Props.create(new MockRaftActorCreator(peerAddresses, id, config, dataPersistenceProvider, null));
         }
 
+        public static Props props(final String id, final Map<String, String> peerAddresses,
+            Optional<ConfigParams> config, ActorRef roleChangeNotifier){
+            return Props.create(new MockRaftActorCreator(peerAddresses, id, config, null, roleChangeNotifier));
+        }
 
         @Override protected void applyState(ActorRef clientActor, String identifier, Object data) {
             delegate.applyState(clientActor, identifier, data);
             LOG.info("applyState called");
         }
 
-
-
-
         @Override
         protected void startLogRecoveryBatch(int maxBatchSize) {
         }
@@ -201,6 +207,11 @@ public class RaftActorTest extends AbstractActorTest {
             return this.dataPersistenceProvider;
         }
 
+        @Override
+        protected Optional<ActorRef> getRoleChangeNotifier() {
+            return Optional.fromNullable(roleChangeNotifier);
+        }
+
         @Override public String persistenceId() {
             return this.getId();
         }
@@ -862,6 +873,40 @@ public class RaftActorTest extends AbstractActorTest {
         };
     }
 
+    @Test
+    public void testRaftRoleChangeNotifier() throws Exception {
+        new JavaTestKit(getSystem()) {{
+            ActorRef notifierActor = getSystem().actorOf(Props.create(MessageCollectorActor.class));
+            DefaultConfigParamsImpl config = new DefaultConfigParamsImpl();
+            String id = "testRaftRoleChangeNotifier";
+
+            TestActorRef<MockRaftActor> mockActorRef = TestActorRef.create(getSystem(), MockRaftActor.props(id,
+                Collections.<String,String>emptyMap(), Optional.<ConfigParams>of(config), notifierActor), id);
+
+            MockRaftActor mockRaftActor = mockActorRef.underlyingActor();
+            mockRaftActor.setCurrentBehavior(new Follower(mockRaftActor.getRaftActorContext()));
+
+            // sleeping for a minimum of 2 seconds, if it spans more its fine.
+            Uninterruptibles.sleepUninterruptibly(2, TimeUnit.SECONDS);
+
+            List<Object> matches =  MessageCollectorActor.getAllMatching(notifierActor, RoleChanged.class);
+            assertNotNull(matches);
+            assertEquals(2, matches.size());
+
+            // check if the notifier got a role change from Follower to Candidate
+            RoleChanged raftRoleChanged = (RoleChanged) matches.get(0);
+            assertEquals(id, raftRoleChanged.getMemberId());
+            assertEquals(RaftState.Follower.name(), raftRoleChanged.getOldRole());
+            assertEquals(RaftState.Candidate.name(), raftRoleChanged.getNewRole());
+
+            // check if the notifier got a role change from Candidate to Leader
+            raftRoleChanged = (RoleChanged) matches.get(1);
+            assertEquals(id, raftRoleChanged.getMemberId());
+            assertEquals(RaftState.Candidate.name(), raftRoleChanged.getOldRole());
+            assertEquals(RaftState.Leader.name(), raftRoleChanged.getNewRole());
+        }};
+    }
+
     private ByteString fromObject(Object snapshot) throws Exception {
         ByteArrayOutputStream b = null;
         ObjectOutputStream o = null;
index 83b9ad3ec7b7a5c7033f876c45d4db2788f50716..0ee9693d326e6eff9ff37c77eeaf37b4c8678572 100644 (file)
@@ -1,9 +1,20 @@
 package org.opendaylight.controller.cluster.raft.behaviors;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 import akka.actor.ActorRef;
 import akka.actor.Props;
 import akka.testkit.JavaTestKit;
 import com.google.protobuf.ByteString;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
 import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
@@ -20,19 +31,6 @@ import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
 import org.opendaylight.controller.cluster.raft.utils.DoNothingActor;
 import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
 
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
 public class FollowerTest extends AbstractRaftActorBehaviorTest {
 
     private final ActorRef followerActor = getSystem().actorOf(Props.create(
@@ -452,18 +450,20 @@ public class FollowerTest extends AbstractRaftActorBehaviorTest {
             int offset = 0;
             int snapshotLength = bsSnapshot.size();
             int i = 1;
+            int chunkIndex = 1;
 
             do {
                 chunkData = getNextChunk(bsSnapshot, offset);
                 final InstallSnapshot installSnapshot =
                     new InstallSnapshot(1, "leader-1", i, 1,
-                        chunkData, i, 3);
+                        chunkData, chunkIndex, 3);
                 follower.handleMessage(leaderActor, installSnapshot);
                 offset = offset + 50;
                 i++;
+                chunkIndex++;
             } while ((offset+50) < snapshotLength);
 
-            final InstallSnapshot installSnapshot3 = new InstallSnapshot(1, "leader-1", 3, 1, chunkData, 3, 3);
+            final InstallSnapshot installSnapshot3 = new InstallSnapshot(1, "leader-1", 3, 1, chunkData, chunkIndex, 3);
             follower.handleMessage(leaderActor, installSnapshot3);
 
             String[] matches = new ReceiveWhile<String>(String.class, duration("2 seconds")) {
@@ -490,6 +490,9 @@ public class FollowerTest extends AbstractRaftActorBehaviorTest {
                 }
             }.get();
 
+            // Verify that after a snapshot is successfully applied the collected snapshot chunks is reset to empty
+            assertEquals(ByteString.EMPTY, follower.getSnapshotChunksCollected());
+
             String applySnapshotMatch = "";
             for (String reply: matches) {
                 if (reply.startsWith("applySnapshot")) {
@@ -517,6 +520,52 @@ public class FollowerTest extends AbstractRaftActorBehaviorTest {
         }};
     }
 
+    @Test
+    public void testHandleOutOfSequenceInstallSnapshot() throws Exception {
+        JavaTestKit javaTestKit = new JavaTestKit(getSystem()) {
+            {
+
+                ActorRef leaderActor = getSystem().actorOf(Props.create(
+                        MessageCollectorActor.class));
+
+                MockRaftActorContext context = (MockRaftActorContext)
+                        createActorContext(getRef());
+
+                Follower follower = (Follower) createBehavior(context);
+
+                HashMap<String, String> followerSnapshot = new HashMap<>();
+                followerSnapshot.put("1", "A");
+                followerSnapshot.put("2", "B");
+                followerSnapshot.put("3", "C");
+
+                ByteString bsSnapshot = toByteString(followerSnapshot);
+
+                final InstallSnapshot installSnapshot = new InstallSnapshot(1, "leader-1", 3, 1, getNextChunk(bsSnapshot, 10), 3, 3);
+                follower.handleMessage(leaderActor, installSnapshot);
+
+                Object messages = executeLocalOperation(leaderActor, "get-all-messages");
+
+                assertNotNull(messages);
+                assertTrue(messages instanceof List);
+                List<Object> listMessages = (List<Object>) messages;
+
+                int installSnapshotReplyReceivedCount = 0;
+                for (Object message: listMessages) {
+                    if (message instanceof InstallSnapshotReply) {
+                        ++installSnapshotReplyReceivedCount;
+                    }
+                }
+
+                assertEquals(1, installSnapshotReplyReceivedCount);
+                InstallSnapshotReply reply = (InstallSnapshotReply) listMessages.get(0);
+                assertEquals(false, reply.isSuccess());
+                assertEquals(-1, reply.getChunkIndex());
+                assertEquals(ByteString.EMPTY, follower.getSnapshotChunksCollected());
+
+
+            }};
+    }
+
     public Object executeLocalOperation(ActorRef actor, Object message) throws Exception {
         return MessageCollectorActor.getAllMessages(actor);
     }
index 0fc0b4ccfde37a802322e8d023c759f0e58ffd7e..895fe35bff7588526fac71e996e9120968234af2 100644 (file)
@@ -1,11 +1,16 @@
 package org.opendaylight.controller.cluster.raft.behaviors;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 import akka.actor.ActorRef;
 import akka.actor.PoisonPill;
 import akka.actor.Props;
 import akka.actor.Terminated;
 import akka.testkit.JavaTestKit;
+import akka.testkit.TestActorRef;
 import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Uninterruptibles;
 import com.google.protobuf.ByteString;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -41,9 +46,6 @@ import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
 import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
 import org.opendaylight.controller.protobuff.messages.cluster.raft.InstallSnapshotMessages;
 import scala.concurrent.duration.FiniteDuration;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
 
 public class LeaderTest extends AbstractRaftActorBehaviorTest {
 
@@ -125,7 +127,7 @@ public class LeaderTest extends AbstractRaftActorBehaviorTest {
                     Map<String, String> peerAddresses = new HashMap<>();
 
                     peerAddresses.put(followerActor.path().toString(),
-                        followerActor.path().toString());
+                            followerActor.path().toString());
 
                     actorContext.setPeerAddresses(peerAddresses);
 
@@ -570,6 +572,156 @@ public class LeaderTest extends AbstractRaftActorBehaviorTest {
         }};
     }
 
+    @Test
+    public void testHandleInstallSnapshotReplyWithInvalidChunkIndex() throws Exception {
+        new JavaTestKit(getSystem()) {{
+
+            TestActorRef<MessageCollectorActor> followerActor =
+                    TestActorRef.create(getSystem(), Props.create(MessageCollectorActor.class), "follower");
+
+            Map<String, String> peerAddresses = new HashMap<>();
+            peerAddresses.put(followerActor.path().toString(),
+                    followerActor.path().toString());
+
+            final int followersLastIndex = 2;
+            final int snapshotIndex = 3;
+            final int snapshotTerm = 1;
+            final int currentTerm = 2;
+
+            MockRaftActorContext actorContext =
+                    (MockRaftActorContext) createActorContext();
+
+            actorContext.setConfigParams(new DefaultConfigParamsImpl(){
+                @Override
+                public int getSnapshotChunkSize() {
+                    return 50;
+                }
+            });
+            actorContext.setPeerAddresses(peerAddresses);
+            actorContext.setCommitIndex(followersLastIndex);
+
+            MockLeader leader = new MockLeader(actorContext);
+
+            Map<String, String> leadersSnapshot = new HashMap<>();
+            leadersSnapshot.put("1", "A");
+            leadersSnapshot.put("2", "B");
+            leadersSnapshot.put("3", "C");
+
+            // set the snapshot variables in replicatedlog
+            actorContext.getReplicatedLog().setSnapshotIndex(snapshotIndex);
+            actorContext.getReplicatedLog().setSnapshotTerm(snapshotTerm);
+            actorContext.getTermInformation().update(currentTerm, leaderActor.path().toString());
+
+            ByteString bs = toByteString(leadersSnapshot);
+            leader.setSnapshot(Optional.of(bs));
+
+            leader.handleMessage(leaderActor, new SendInstallSnapshot(bs));
+
+            Object o = MessageCollectorActor.getAllMessages(followerActor).get(0);
+
+            assertTrue(o instanceof InstallSnapshotMessages.InstallSnapshot);
+
+            InstallSnapshotMessages.InstallSnapshot installSnapshot = (InstallSnapshotMessages.InstallSnapshot) o;
+
+            assertEquals(1, installSnapshot.getChunkIndex());
+            assertEquals(3, installSnapshot.getTotalChunks());
+
+
+            leader.handleMessage(followerActor, new InstallSnapshotReply(actorContext.getTermInformation().getCurrentTerm(), followerActor.path().toString(), -1, false));
+
+            leader.handleMessage(leaderActor, new SendHeartBeat());
+
+            o = MessageCollectorActor.getAllMessages(followerActor).get(1);
+
+            assertTrue(o instanceof InstallSnapshotMessages.InstallSnapshot);
+
+            installSnapshot = (InstallSnapshotMessages.InstallSnapshot) o;
+
+            assertEquals(1, installSnapshot.getChunkIndex());
+            assertEquals(3, installSnapshot.getTotalChunks());
+
+            followerActor.tell(PoisonPill.getInstance(), getRef());
+        }};
+    }
+
+    @Test
+    public void testHandleSnapshotSendsPreviousChunksHashCodeWhenSendingNextChunk() throws Exception {
+        new JavaTestKit(getSystem()) {
+            {
+
+                TestActorRef<MessageCollectorActor> followerActor =
+                        TestActorRef.create(getSystem(), Props.create(MessageCollectorActor.class), "follower");
+
+                Map<String, String> peerAddresses = new HashMap<>();
+                peerAddresses.put(followerActor.path().toString(),
+                        followerActor.path().toString());
+
+                final int followersLastIndex = 2;
+                final int snapshotIndex = 3;
+                final int snapshotTerm = 1;
+                final int currentTerm = 2;
+
+                MockRaftActorContext actorContext =
+                        (MockRaftActorContext) createActorContext();
+
+                actorContext.setConfigParams(new DefaultConfigParamsImpl() {
+                    @Override
+                    public int getSnapshotChunkSize() {
+                        return 50;
+                    }
+                });
+                actorContext.setPeerAddresses(peerAddresses);
+                actorContext.setCommitIndex(followersLastIndex);
+
+                MockLeader leader = new MockLeader(actorContext);
+
+                Map<String, String> leadersSnapshot = new HashMap<>();
+                leadersSnapshot.put("1", "A");
+                leadersSnapshot.put("2", "B");
+                leadersSnapshot.put("3", "C");
+
+                // set the snapshot variables in replicatedlog
+                actorContext.getReplicatedLog().setSnapshotIndex(snapshotIndex);
+                actorContext.getReplicatedLog().setSnapshotTerm(snapshotTerm);
+                actorContext.getTermInformation().update(currentTerm, leaderActor.path().toString());
+
+                ByteString bs = toByteString(leadersSnapshot);
+                leader.setSnapshot(Optional.of(bs));
+
+                leader.handleMessage(leaderActor, new SendInstallSnapshot(bs));
+
+                Object o = MessageCollectorActor.getAllMessages(followerActor).get(0);
+
+                assertTrue(o instanceof InstallSnapshotMessages.InstallSnapshot);
+
+                InstallSnapshotMessages.InstallSnapshot installSnapshot = (InstallSnapshotMessages.InstallSnapshot) o;
+
+                assertEquals(1, installSnapshot.getChunkIndex());
+                assertEquals(3, installSnapshot.getTotalChunks());
+                assertEquals(AbstractLeader.INITIAL_LAST_CHUNK_HASH_CODE, installSnapshot.getLastChunkHashCode());
+
+                int hashCode = installSnapshot.getData().hashCode();
+
+                leader.handleMessage(followerActor, new InstallSnapshotReply(installSnapshot.getTerm(),followerActor.path().toString(),1,true ));
+
+                leader.handleMessage(leaderActor, new SendHeartBeat());
+
+                Uninterruptibles.sleepUninterruptibly(100, TimeUnit.MILLISECONDS);
+
+                o = MessageCollectorActor.getAllMessages(followerActor).get(1);
+
+                assertTrue(o instanceof InstallSnapshotMessages.InstallSnapshot);
+
+                installSnapshot = (InstallSnapshotMessages.InstallSnapshot) o;
+
+                assertEquals(2, installSnapshot.getChunkIndex());
+                assertEquals(3, installSnapshot.getTotalChunks());
+                assertEquals(hashCode, installSnapshot.getLastChunkHashCode());
+
+                followerActor.tell(PoisonPill.getInstance(), getRef());
+            }};
+    }
+
     @Test
     public void testFollowerToSnapshotLogic() {
 
diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/SnapshotTrackerTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/SnapshotTrackerTest.java
new file mode 100644 (file)
index 0000000..1b3a8f5
--- /dev/null
@@ -0,0 +1,181 @@
+package org.opendaylight.controller.cluster.raft.behaviors;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import akka.event.LoggingAdapter;
+import com.google.common.base.Optional;
+import com.google.protobuf.ByteString;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SnapshotTrackerTest {
+
+    Map<String, String> data;
+    ByteString byteString;
+    ByteString chunk1;
+    ByteString chunk2;
+    ByteString chunk3;
+
+    @Before
+    public void setup(){
+        data = new HashMap<>();
+        data.put("key1", "value1");
+        data.put("key2", "value2");
+        data.put("key3", "value3");
+
+        byteString = toByteString(data);
+        chunk1 = getNextChunk(byteString, 0, 10);
+        chunk2 = getNextChunk(byteString, 10, 10);
+        chunk3 = getNextChunk(byteString, 20, byteString.size());
+    }
+
+    @Test
+    public void testAddChunk() throws SnapshotTracker.InvalidChunkException {
+        SnapshotTracker tracker1 = new SnapshotTracker(mock(LoggingAdapter.class), 5);
+
+        tracker1.addChunk(1, chunk1, Optional.<Integer>absent());
+        tracker1.addChunk(2, chunk2, Optional.<Integer>absent());
+        tracker1.addChunk(3, chunk3, Optional.<Integer>absent());
+
+        // Verify that an InvalidChunkException is thrown when we try to add a chunk to a sealed tracker
+        SnapshotTracker tracker2 = new SnapshotTracker(mock(LoggingAdapter.class), 2);
+
+        tracker2.addChunk(1, chunk1, Optional.<Integer>absent());
+        tracker2.addChunk(2, chunk2, Optional.<Integer>absent());
+
+        try {
+            tracker2.addChunk(3, chunk3, Optional.<Integer>absent());
+            Assert.fail();
+        } catch(SnapshotTracker.InvalidChunkException e){
+            e.getMessage().startsWith("Invalid chunk");
+        }
+
+        // The first chunk's index must at least be FIRST_CHUNK_INDEX
+        SnapshotTracker tracker3 = new SnapshotTracker(mock(LoggingAdapter.class), 2);
+
+        try {
+            tracker3.addChunk(AbstractLeader.FIRST_CHUNK_INDEX - 1, chunk1, Optional.<Integer>absent());
+            Assert.fail();
+        } catch(SnapshotTracker.InvalidChunkException e){
+
+        }
+
+        // Out of sequence chunk indexes won't work
+        SnapshotTracker tracker4 = new SnapshotTracker(mock(LoggingAdapter.class), 2);
+
+        tracker4.addChunk(AbstractLeader.FIRST_CHUNK_INDEX, chunk1, Optional.<Integer>absent());
+
+        try {
+            tracker4.addChunk(AbstractLeader.FIRST_CHUNK_INDEX+2, chunk2, Optional.<Integer>absent());
+            Assert.fail();
+        } catch(SnapshotTracker.InvalidChunkException e){
+
+        }
+
+        // No exceptions will be thrown when invalid chunk is added with the right sequence
+        // If the lastChunkHashCode is missing
+        SnapshotTracker tracker5 = new SnapshotTracker(mock(LoggingAdapter.class), 2);
+
+        tracker5.addChunk(AbstractLeader.FIRST_CHUNK_INDEX, chunk1, Optional.<Integer>absent());
+        // Look I can add the same chunk again
+        tracker5.addChunk(AbstractLeader.FIRST_CHUNK_INDEX + 1, chunk1, Optional.<Integer>absent());
+
+        // An exception will be thrown when an invalid chunk is addedd with the right sequence
+        // when the lastChunkHashCode is present
+        SnapshotTracker tracker6 = new SnapshotTracker(mock(LoggingAdapter.class), 2);
+
+        tracker6.addChunk(AbstractLeader.FIRST_CHUNK_INDEX, chunk1, Optional.of(-1));
+
+        try {
+            // Here we add a second chunk and tell addChunk that the previous chunk had a hash code 777
+            tracker6.addChunk(AbstractLeader.FIRST_CHUNK_INDEX + 1, chunk2, Optional.of(777));
+            Assert.fail();
+        }catch(SnapshotTracker.InvalidChunkException e){
+
+        }
+
+    }
+
+    @Test
+    public void testGetSnapShot() throws SnapshotTracker.InvalidChunkException {
+
+        // Trying to get a snapshot before all chunks have been received will throw an exception
+        SnapshotTracker tracker1 = new SnapshotTracker(mock(LoggingAdapter.class), 5);
+
+        tracker1.addChunk(1, chunk1, Optional.<Integer>absent());
+        try {
+            tracker1.getSnapshot();
+            Assert.fail();
+        } catch(IllegalStateException e){
+
+        }
+
+        SnapshotTracker tracker2 = new SnapshotTracker(mock(LoggingAdapter.class), 3);
+
+        tracker2.addChunk(1, chunk1, Optional.<Integer>absent());
+        tracker2.addChunk(2, chunk2, Optional.<Integer>absent());
+        tracker2.addChunk(3, chunk3, Optional.<Integer>absent());
+
+        byte[] snapshot = tracker2.getSnapshot();
+
+        assertEquals(byteString, ByteString.copyFrom(snapshot));
+    }
+
+    @Test
+    public void testGetCollectedChunks() throws SnapshotTracker.InvalidChunkException {
+        SnapshotTracker tracker1 = new SnapshotTracker(mock(LoggingAdapter.class), 5);
+
+        ByteString chunks = chunk1.concat(chunk2);
+
+        tracker1.addChunk(1, chunk1, Optional.<Integer>absent());
+        tracker1.addChunk(2, chunk2, Optional.<Integer>absent());
+
+        assertEquals(chunks, tracker1.getCollectedChunks());
+    }
+
+    public ByteString getNextChunk (ByteString bs, int offset, int size){
+        int snapshotLength = bs.size();
+        int start = offset;
+        if (size > snapshotLength) {
+            size = snapshotLength;
+        } else {
+            if ((start + size) > snapshotLength) {
+                size = snapshotLength - start;
+            }
+        }
+        return bs.substring(start, start + size);
+    }
+
+    private ByteString toByteString(Map<String, String> state) {
+        ByteArrayOutputStream b = null;
+        ObjectOutputStream o = null;
+        try {
+            try {
+                b = new ByteArrayOutputStream();
+                o = new ObjectOutputStream(b);
+                o.writeObject(state);
+                byte[] snapshotBytes = b.toByteArray();
+                return ByteString.copyFrom(snapshotBytes);
+            } finally {
+                if (o != null) {
+                    o.flush();
+                    o.close();
+                }
+                if (b != null) {
+                    b.close();
+                }
+            }
+        } catch (IOException e) {
+            org.junit.Assert.fail("IOException in converting Hashmap to Bytestring:" + e);
+        }
+        return null;
+    }
+
+
+}
\ No newline at end of file
index 9fbdd4587f2c5e9f5b4a53e53876ca6981fb8af9..3469a956c3737df541c7523a539ab998bf6ac8df 100644 (file)
@@ -13,15 +13,14 @@ import akka.actor.UntypedActor;
 import akka.pattern.Patterns;
 import akka.util.Timeout;
 import com.google.common.collect.Lists;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
 import scala.concurrent.Await;
 import scala.concurrent.Future;
 import scala.concurrent.duration.Duration;
 import scala.concurrent.duration.FiniteDuration;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
 
 public class MessageCollectorActor extends UntypedActor {
     private List<Object> messages = new ArrayList<>();
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RegisterRoleChangeListener.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RegisterRoleChangeListener.java
new file mode 100644 (file)
index 0000000..1faa341
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  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
+ */
+
+package org.opendaylight.controller.cluster.notifications;
+
+import java.io.Serializable;
+
+/**
+ * Message sent from the listener of Role Change messages to register itself to the Role Change Notifier
+ *
+ * The Listener could be in a separate ActorSystem and hence this message needs to be Serializable
+ */
+public class RegisterRoleChangeListener implements Serializable {
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RegisterRoleChangeListenerReply.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RegisterRoleChangeListenerReply.java
new file mode 100644 (file)
index 0000000..f1d13e3
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  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
+ */
+
+package org.opendaylight.controller.cluster.notifications;
+
+import java.io.Serializable;
+
+/**
+ * Reply message sent from a RoleChangeNotifier to the Role Change Listener
+ *
+ * Can be sent to a separate actor system and hence should be made serializable.
+ */
+public class RegisterRoleChangeListenerReply implements Serializable {
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RoleChangeNotification.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RoleChangeNotification.java
new file mode 100644 (file)
index 0000000..de2733f
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  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
+ */
+
+package org.opendaylight.controller.cluster.notifications;
+
+import java.io.Serializable;
+
+/**
+ * Notification message representing a Role change of a cluster member
+ *
+ * Roles generally are Leader, Follower and Candidate. But can be based on the consensus strategy/implementation
+ *
+ * The Listener could be in a separate ActorSystem and hence this message needs to be Serializable
+ */
+public class RoleChangeNotification implements Serializable {
+    private String memberId;
+    private String oldRole;
+    private String newRole;
+
+    public RoleChangeNotification(String memberId, String oldRole, String newRole) {
+        this.memberId = memberId;
+        this.oldRole = oldRole;
+        this.newRole = newRole;
+    }
+
+    public String getMemberId() {
+        return memberId;
+    }
+
+    public String getOldRole() {
+        return oldRole;
+    }
+
+    public String getNewRole() {
+        return newRole;
+    }
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RoleChangeNotifier.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RoleChangeNotifier.java
new file mode 100644 (file)
index 0000000..a9aa561
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  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
+ */
+
+package org.opendaylight.controller.cluster.notifications;
+
+import akka.actor.Actor;
+import akka.actor.ActorPath;
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import akka.japi.Creator;
+import akka.serialization.Serialization;
+import com.google.common.collect.Maps;
+import java.util.Map;
+import org.opendaylight.controller.cluster.common.actor.AbstractUntypedActor;
+
+/**
+ * The RoleChangeNotifier is responsible for receiving Raft role change messages and notifying
+ * the listeners (within the same node), which are registered with it.
+ * <p/>
+ * The RoleChangeNotifier is instantiated by the Shard and injected into the RaftActor.
+ */
+public class RoleChangeNotifier extends AbstractUntypedActor implements AutoCloseable {
+
+    private String memberId;
+    private Map<ActorPath, ActorRef> registeredListeners = Maps.newHashMap();
+    private RoleChangeNotification latestRoleChangeNotification = null;
+
+    public RoleChangeNotifier(String memberId) {
+        this.memberId = memberId;
+    }
+
+    public static Props getProps(final String memberId) {
+        return Props.create(new Creator<Actor>() {
+            @Override
+            public Actor create() throws Exception {
+                return new RoleChangeNotifier(memberId);
+            }
+        });
+    }
+
+    @Override
+    public void preStart() throws Exception {
+        super.preStart();
+        LOG.info("RoleChangeNotifier:{} created and ready for shard:{}",
+            Serialization.serializedActorPath(getSelf()), memberId);
+    }
+
+    @Override
+    protected void handleReceive(Object message) throws Exception {
+        if (message instanceof RegisterRoleChangeListener) {
+            // register listeners for this shard
+
+            ActorRef curRef = registeredListeners.get(getSender().path());
+            if (curRef != null) {
+                // ActorPaths would pass equal even if the unique id of the actors are different
+                // if a listener actor is re-registering after reincarnation, then removing the existing
+                // entry so the actor path with correct unique id is registered.
+                registeredListeners.remove(getSender().path());
+            }
+            registeredListeners.put(getSender().path(), getSender());
+
+            LOG.info("RoleChangeNotifier for {} , registered listener {}", memberId,
+                getSender().path().toString());
+
+            getSender().tell(new RegisterRoleChangeListenerReply(), getSelf());
+
+            if (latestRoleChangeNotification != null) {
+                getSender().tell(latestRoleChangeNotification, getSelf());
+            }
+
+
+        } else if (message instanceof RoleChanged) {
+            // this message is sent by RaftActor. Notify registered listeners when this message is received.
+            RoleChanged roleChanged = (RoleChanged) message;
+
+            LOG.info("RoleChangeNotifier for {} , received role change from {} to {}", memberId,
+                roleChanged.getOldRole(), roleChanged.getNewRole());
+
+            latestRoleChangeNotification =
+                new RoleChangeNotification(roleChanged.getMemberId(),
+                    roleChanged.getOldRole(), roleChanged.getNewRole());
+
+            for (ActorRef listener: registeredListeners.values()) {
+                listener.tell(latestRoleChangeNotification, getSelf());
+            }
+        }
+    }
+
+    @Override
+    public void close() throws Exception {
+        registeredListeners.clear();
+    }
+}
+
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RoleChanged.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RoleChanged.java
new file mode 100644 (file)
index 0000000..f315bfd
--- /dev/null
@@ -0,0 +1,31 @@
+package org.opendaylight.controller.cluster.notifications;
+
+/**
+ * Role Change message initiated internally from the  Raft Actor when a the behavior/role changes.
+ *
+ * Since its internal , need not be serialized
+ *
+ */
+public class RoleChanged {
+    private String memberId;
+    private String oldRole;
+    private String newRole;
+
+    public RoleChanged(String memberId, String oldRole, String newRole) {
+        this.memberId = memberId;
+        this.oldRole = oldRole;
+        this.newRole = newRole;
+    }
+
+    public String getMemberId() {
+        return memberId;
+    }
+
+    public String getOldRole() {
+        return oldRole;
+    }
+
+    public String getNewRole() {
+        return newRole;
+    }
+}
index aadc3625cc34abf8c58dd0143bc97d4c571f7e6f..075c6075a86b327775d23f4c217794700b69611f 100644 (file)
@@ -12,12 +12,11 @@ import com.google.common.base.Preconditions;
 import com.google.protobuf.GeneratedMessage;
 import com.google.protobuf.InvalidProtocolBufferException;
 import com.google.protobuf.UnknownFieldSet;
-import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
-import org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages;
-
 import java.io.Serializable;
 import java.util.HashMap;
 import java.util.Map;
+import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
+import org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages;
 
 public class CompositeModificationPayload extends Payload implements
     Serializable {
@@ -73,4 +72,8 @@ public class CompositeModificationPayload extends Payload implements
     public Object getModification(){
         return this.modification;
     }
+
+    public int size(){
+        return this.modification.getSerializedSize();
+    }
 }
index 502c338f2298ea34b443d0b0f1e8d3a4d36df721..7df53082948d0c69f4ea2c1223025821bd5946bd 100644 (file)
@@ -10,9 +10,8 @@ package org.opendaylight.controller.cluster.raft.protobuff.client.messages;
 
 
 import com.google.protobuf.GeneratedMessage;
-import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
-
 import java.util.Map;
+import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
 
 /**
  * An instance of a Payload class is meant to be used as the Payload for
@@ -81,6 +80,8 @@ public abstract class Payload {
     public abstract Payload decode(
         AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload payload);
 
+    public abstract int size();
+
 
 
 }
index b93be3e009909c42eae18b50a15c318676371b65..de7f44e213ae1e8de0ceac507ad767f44a25467a 100644 (file)
@@ -85,6 +85,16 @@ public final class InstallSnapshotMessages {
      * <code>optional int32 totalChunks = 7;</code>
      */
     int getTotalChunks();
+
+    // optional int32 lastChunkHashCode = 8;
+    /**
+     * <code>optional int32 lastChunkHashCode = 8;</code>
+     */
+    boolean hasLastChunkHashCode();
+    /**
+     * <code>optional int32 lastChunkHashCode = 8;</code>
+     */
+    int getLastChunkHashCode();
   }
   /**
    * Protobuf type {@code org.opendaylight.controller.cluster.raft.InstallSnapshot}
@@ -172,6 +182,11 @@ public final class InstallSnapshotMessages {
               totalChunks_ = input.readInt32();
               break;
             }
+            case 64: {
+              bitField0_ |= 0x00000080;
+              lastChunkHashCode_ = input.readInt32();
+              break;
+            }
           }
         }
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -351,6 +366,22 @@ public final class InstallSnapshotMessages {
       return totalChunks_;
     }
 
+    // optional int32 lastChunkHashCode = 8;
+    public static final int LASTCHUNKHASHCODE_FIELD_NUMBER = 8;
+    private int lastChunkHashCode_;
+    /**
+     * <code>optional int32 lastChunkHashCode = 8;</code>
+     */
+    public boolean hasLastChunkHashCode() {
+      return ((bitField0_ & 0x00000080) == 0x00000080);
+    }
+    /**
+     * <code>optional int32 lastChunkHashCode = 8;</code>
+     */
+    public int getLastChunkHashCode() {
+      return lastChunkHashCode_;
+    }
+
     private void initFields() {
       term_ = 0L;
       leaderId_ = "";
@@ -359,6 +390,7 @@ public final class InstallSnapshotMessages {
       data_ = com.google.protobuf.ByteString.EMPTY;
       chunkIndex_ = 0;
       totalChunks_ = 0;
+      lastChunkHashCode_ = 0;
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
@@ -393,6 +425,9 @@ public final class InstallSnapshotMessages {
       if (((bitField0_ & 0x00000040) == 0x00000040)) {
         output.writeInt32(7, totalChunks_);
       }
+      if (((bitField0_ & 0x00000080) == 0x00000080)) {
+        output.writeInt32(8, lastChunkHashCode_);
+      }
       getUnknownFields().writeTo(output);
     }
 
@@ -430,6 +465,10 @@ public final class InstallSnapshotMessages {
         size += com.google.protobuf.CodedOutputStream
           .computeInt32Size(7, totalChunks_);
       }
+      if (((bitField0_ & 0x00000080) == 0x00000080)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(8, lastChunkHashCode_);
+      }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
       return size;
@@ -560,6 +599,8 @@ public final class InstallSnapshotMessages {
         bitField0_ = (bitField0_ & ~0x00000020);
         totalChunks_ = 0;
         bitField0_ = (bitField0_ & ~0x00000040);
+        lastChunkHashCode_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000080);
         return this;
       }
 
@@ -616,6 +657,10 @@ public final class InstallSnapshotMessages {
           to_bitField0_ |= 0x00000040;
         }
         result.totalChunks_ = totalChunks_;
+        if (((from_bitField0_ & 0x00000080) == 0x00000080)) {
+          to_bitField0_ |= 0x00000080;
+        }
+        result.lastChunkHashCode_ = lastChunkHashCode_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
@@ -655,6 +700,9 @@ public final class InstallSnapshotMessages {
         if (other.hasTotalChunks()) {
           setTotalChunks(other.getTotalChunks());
         }
+        if (other.hasLastChunkHashCode()) {
+          setLastChunkHashCode(other.getLastChunkHashCode());
+        }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
@@ -957,6 +1005,39 @@ public final class InstallSnapshotMessages {
         return this;
       }
 
+      // optional int32 lastChunkHashCode = 8;
+      private int lastChunkHashCode_ ;
+      /**
+       * <code>optional int32 lastChunkHashCode = 8;</code>
+       */
+      public boolean hasLastChunkHashCode() {
+        return ((bitField0_ & 0x00000080) == 0x00000080);
+      }
+      /**
+       * <code>optional int32 lastChunkHashCode = 8;</code>
+       */
+      public int getLastChunkHashCode() {
+        return lastChunkHashCode_;
+      }
+      /**
+       * <code>optional int32 lastChunkHashCode = 8;</code>
+       */
+      public Builder setLastChunkHashCode(int value) {
+        bitField0_ |= 0x00000080;
+        lastChunkHashCode_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int32 lastChunkHashCode = 8;</code>
+       */
+      public Builder clearLastChunkHashCode() {
+        bitField0_ = (bitField0_ & ~0x00000080);
+        lastChunkHashCode_ = 0;
+        onChanged();
+        return this;
+      }
+
       // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.cluster.raft.InstallSnapshot)
     }
 
@@ -983,13 +1064,14 @@ public final class InstallSnapshotMessages {
   static {
     java.lang.String[] descriptorData = {
       "\n\025InstallSnapshot.proto\022(org.opendayligh" +
-      "t.controller.cluster.raft\"\235\001\n\017InstallSna" +
+      "t.controller.cluster.raft\"\270\001\n\017InstallSna" +
       "pshot\022\014\n\004term\030\001 \001(\003\022\020\n\010leaderId\030\002 \001(\t\022\031\n" +
       "\021lastIncludedIndex\030\003 \001(\003\022\030\n\020lastIncluded" +
       "Term\030\004 \001(\003\022\014\n\004data\030\005 \001(\014\022\022\n\nchunkIndex\030\006" +
-      " \001(\005\022\023\n\013totalChunks\030\007 \001(\005BX\n;org.openday" +
-      "light.controller.protobuff.messages.clus" +
-      "ter.raftB\027InstallSnapshotMessagesH\001"
+      " \001(\005\022\023\n\013totalChunks\030\007 \001(\005\022\031\n\021lastChunkHa" +
+      "shCode\030\010 \001(\005BX\n;org.opendaylight.control" +
+      "ler.protobuff.messages.cluster.raftB\027Ins" +
+      "tallSnapshotMessagesH\001"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
       new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -1001,7 +1083,7 @@ public final class InstallSnapshotMessages {
           internal_static_org_opendaylight_controller_cluster_raft_InstallSnapshot_fieldAccessorTable = new
             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
               internal_static_org_opendaylight_controller_cluster_raft_InstallSnapshot_descriptor,
-              new java.lang.String[] { "Term", "LeaderId", "LastIncludedIndex", "LastIncludedTerm", "Data", "ChunkIndex", "TotalChunks", });
+              new java.lang.String[] { "Term", "LeaderId", "LastIncludedIndex", "LastIncludedTerm", "Data", "ChunkIndex", "TotalChunks", "LastChunkHashCode", });
           return null;
         }
       };
index 4198644b13952f8e05c5f9f4a0db75316594c7ba..adb58ae4affe1fba3be9b9afb9141a36255523fb 100644 (file)
@@ -12,4 +12,5 @@ message InstallSnapshot {
     optional bytes data = 5;
     optional int32 chunkIndex = 6;
     optional int32 totalChunks = 7;
+    optional int32 lastChunkHashCode = 8;
 }
index 99df01a32e17c9c10c0e4ada9268e52e15008162..d3abd38153968ca3c66430e6887b5b80c7220afb 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
@@ -37,8 +38,10 @@ import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
@@ -103,7 +106,10 @@ public class TestModel {
   private static final String TWO_ONE_NAME = "one";
   private static final String TWO_TWO_NAME = "two";
   private static final String DESC = "Hello there";
-
+  private static final Long LONG_ID = 1L;
+  private static final Boolean ENABLED = false;
+  private static final Short SHORT_ID = 1;
+  private static final Byte BYTE_ID = 1;
   // Family specific constants
   public static final QName FAMILY_QNAME =
       QName
@@ -142,6 +148,7 @@ public class TestModel {
   private static final String FIRST_GRAND_CHILD_NAME = "first grand child";
   private static final String SECOND_GRAND_CHILD_NAME = "second grand child";
 
+
   // first child
   private static final YangInstanceIdentifier CHILDREN_1_PATH =
       YangInstanceIdentifier.builder(CHILDREN_PATH)
@@ -364,30 +371,45 @@ public class TestModel {
                       QName.create(TEST_QNAME, "my-bits"))).withValue(
               ImmutableSet.of("foo", "bar"));
 
+      // Create unkey list entry
+      UnkeyedListEntryNode binaryDataKey =
+          Builders.unkeyedListEntryBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME)).
+              withChild(ImmutableNodes.leafNode(SOME_BINARY_DATE_QNAME, DESC)).build();
+
+      Map<QName, Object> keyValues = new HashMap<>();
+      keyValues.put(CHILDREN_QNAME, FIRST_CHILD_NAME);
+
 
       // Create the document
       return ImmutableContainerNodeBuilder
               .create()
               .withNodeIdentifier(
-                      new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME))
+                  new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME))
               .withChild(myBits.build())
               .withChild(ImmutableNodes.leafNode(DESC_QNAME, DESC))
-              .withChild(ImmutableNodes.leafNode(POINTER_QNAME, "pointer"))
+              .withChild(ImmutableNodes.leafNode(POINTER_QNAME, ENABLED))
+              .withChild(ImmutableNodes.leafNode(POINTER_QNAME, SHORT_ID))
+              .withChild(ImmutableNodes.leafNode(POINTER_QNAME, BYTE_ID))
               .withChild(
-                      ImmutableNodes.leafNode(SOME_REF_QNAME, YangInstanceIdentifier
-                              .builder().build()))
+                  ImmutableNodes.leafNode(SOME_REF_QNAME, GRAND_CHILD_1_PATH))
               .withChild(ImmutableNodes.leafNode(MYIDENTITY_QNAME, DESC_QNAME))
-
+               .withChild(Builders.unkeyedListBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(OUTER_LIST_QNAME))
+                   .withChild(binaryDataKey).build())
+               .withChild(Builders.orderedMapBuilder()
+                   .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME)).withChild(mapEntry).build())
+               .withChild(Builders.choiceBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME))
+                   .withChild(ImmutableNodes.leafNode(DESC_QNAME, LONG_ID)).build())
                       // .withChild(augmentationNode)
               .withChild(shoes)
               .withChild(numbers)
               .withChild(switchFeatures)
               .withChild(
-                      mapNodeBuilder(AUGMENTED_LIST_QNAME).withChild(mapEntry).build())
+                  mapNodeBuilder(AUGMENTED_LIST_QNAME).withChild(mapEntry).build())
               .withChild(
-                      mapNodeBuilder(OUTER_LIST_QNAME)
-                              .withChild(mapEntry(OUTER_LIST_QNAME, ID_QNAME, ONE_ID))
-                              .withChild(BAR_NODE).build());
+                  mapNodeBuilder(OUTER_LIST_QNAME)
+                      .withChild(mapEntry(OUTER_LIST_QNAME, ID_QNAME, ONE_ID))
+                      .withChild(BAR_NODE).build()
+              );
   }
 
   public static ContainerNode createTestContainer() {
index e18c00ec4b0b5449ddc071175b379372528796f4..daba3fdf8ac18ac889c348b1af017c679603ebb3 100644 (file)
@@ -8,17 +8,16 @@
 
 package org.opendaylight.controller.cluster.datastore;
 
+import akka.util.Timeout;
+import java.util.concurrent.TimeUnit;
 import org.opendaylight.controller.cluster.datastore.config.ConfigurationReader;
 import org.opendaylight.controller.cluster.datastore.config.FileConfigurationReader;
 import org.opendaylight.controller.cluster.raft.ConfigParams;
 import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreConfigProperties;
-import akka.util.Timeout;
 import scala.concurrent.duration.Duration;
 import scala.concurrent.duration.FiniteDuration;
 
-import java.util.concurrent.TimeUnit;
-
 /**
  * Contains contextual data for a data store.
  *
@@ -120,6 +119,7 @@ public class DatastoreContext {
         private boolean persistent = true;
         private ConfigurationReader configurationReader = new FileConfigurationReader();
         private int shardIsolatedLeaderCheckIntervalInMillis = shardHeartbeatIntervalInMillis * 10;
+        private int shardSnapshotDataThresholdPercentage = 12;
 
         public Builder shardTransactionIdleTimeout(Duration shardTransactionIdleTimeout) {
             this.shardTransactionIdleTimeout = shardTransactionIdleTimeout;
@@ -156,6 +156,12 @@ public class DatastoreContext {
             return this;
         }
 
+        public Builder shardSnapshotDataThresholdPercentage(int shardSnapshotDataThresholdPercentage) {
+            this.shardSnapshotDataThresholdPercentage = shardSnapshotDataThresholdPercentage;
+            return this;
+        }
+
+
         public Builder shardHeartbeatIntervalInMillis(int shardHeartbeatIntervalInMillis) {
             this.shardHeartbeatIntervalInMillis = shardHeartbeatIntervalInMillis;
             return this;
@@ -191,12 +197,14 @@ public class DatastoreContext {
             return this;
         }
 
+
         public DatastoreContext build() {
             DefaultConfigParamsImpl raftConfig = new DefaultConfigParamsImpl();
             raftConfig.setHeartBeatInterval(new FiniteDuration(shardHeartbeatIntervalInMillis,
                     TimeUnit.MILLISECONDS));
             raftConfig.setJournalRecoveryLogBatchSize(shardJournalRecoveryLogBatchSize);
             raftConfig.setSnapshotBatchCount(shardSnapshotBatchCount);
+            raftConfig.setSnapshotDataThresholdPercentage(shardSnapshotDataThresholdPercentage);
             raftConfig.setIsolatedLeaderCheckInterval(
                 new FiniteDuration(shardIsolatedLeaderCheckIntervalInMillis, TimeUnit.MILLISECONDS));
 
index d53cb48e501c75c25e3532ce2c71e481717612ad..af16d02eea2909ee75e83e2b62dc58bc633b7031 100644 (file)
@@ -65,6 +65,7 @@ import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContex
 import org.opendaylight.controller.cluster.datastore.modification.Modification;
 import org.opendaylight.controller.cluster.datastore.modification.MutableCompositeModification;
 import org.opendaylight.controller.cluster.datastore.node.NormalizedNodeToNodeCodec;
+import org.opendaylight.controller.cluster.notifications.RoleChangeNotifier;
 import org.opendaylight.controller.cluster.raft.RaftActor;
 import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
 import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshotReply;
@@ -131,6 +132,8 @@ public class Shard extends RaftActor {
 
     private Cancellable txCommitTimeoutCheckSchedule;
 
+    private Optional<ActorRef> roleChangeNotifier;
+
     /**
      * Coordinates persistence recovery on startup.
      */
@@ -171,6 +174,9 @@ public class Shard extends RaftActor {
 
         transactionCommitTimeout = TimeUnit.MILLISECONDS.convert(
                 datastoreContext.getShardTransactionCommitTimeoutInSeconds(), TimeUnit.SECONDS);
+
+        // create a notifier actor for each cluster member
+        roleChangeNotifier = createRoleChangeNotifier(name.toString());
     }
 
     private static Map<String, String> mapPeerAddresses(
@@ -196,6 +202,12 @@ public class Shard extends RaftActor {
         return Props.create(new ShardCreator(name, peerAddresses, datastoreContext, schemaContext));
     }
 
+    private Optional<ActorRef> createRoleChangeNotifier(String shardId) {
+        ActorRef shardRoleChangeNotifier = this.getContext().actorOf(
+            RoleChangeNotifier.getProps(shardId), shardId + "-notifier");
+        return Optional.<ActorRef>of(shardRoleChangeNotifier);
+    }
+
     @Override
     public void postStop() {
         super.postStop();
@@ -259,6 +271,11 @@ public class Shard extends RaftActor {
         }
     }
 
+    @Override
+    protected Optional<ActorRef> getRoleChangeNotifier() {
+        return roleChangeNotifier;
+    }
+
     private void handleTransactionCommitTimeoutCheck() {
         CohortEntry cohortEntry = commitCoordinator.getCurrentCohortEntry();
         if(cohortEntry != null) {
@@ -771,6 +788,7 @@ public class Shard extends RaftActor {
 
         shardMBean.setCommitIndex(getCommitIndex());
         shardMBean.setLastApplied(getLastApplied());
+        shardMBean.setDataSize(getRaftActorContext().getReplicatedLog().dataSize());
     }
 
     @Override
index 9decd82822a2533a092c39b3708b15e21a3be063..4fc2ed2d0691c400ce04eb04482e0794bfef217b 100644 (file)
@@ -62,6 +62,8 @@ public class ShardStats extends AbstractMXBean implements ShardStatsMXBean {
 
     private QueuedNotificationManagerMXBeanImpl notificationManagerStatsBean;
 
+    private volatile long dataSize = 0;
+
     private final SimpleDateFormat sdf =
         new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
 
@@ -218,6 +220,15 @@ public class ShardStats extends AbstractMXBean implements ShardStatsMXBean {
         this.lastCommittedTransactionTime = lastCommittedTransactionTime;
     }
 
+    public void setDataSize(long dataSize){
+        this.dataSize = dataSize;
+    }
+
+    @Override
+    public long getDataSize(){
+        return dataSize;
+    }
+
     @Override
     public ThreadExecutorStats getDataStoreExecutorStats() {
         // FIXME: this particular thing does not work, as it really is DS-specific
index 4d3d438b3267b857457e4f7a5c767c52a9338c6a..367d4f45e235209dd3a07b51107dec6198d1c157 100644 (file)
@@ -54,6 +54,12 @@ module distributed-datastore-provider {
         }
     }
 
+    typedef percentage {
+        type uint8 {
+            range "0..100";
+        }
+    }
+
     grouping data-store-properties {
         leaf max-shard-data-change-executor-queue-size {
             default 1000;
@@ -88,9 +94,16 @@ module distributed-datastore-provider {
          leaf shard-snapshot-batch-count {
             default 20000;
             type non-zero-uint32-type;
-            description "The minimum number of entries to be present in the in-memory journal log before a snapshot to be taken.";
+            description "The minimum number of entries to be present in the in-memory journal log before a snapshot is to be taken.";
          }
 
+         leaf shard-snapshot-data-threshold-percentage {
+            default 12;
+            type percentage;
+            description "The percentage of Runtime.totalMemory() used by the in-memory journal log before a snapshot is to be taken";
+         }
+
+
          leaf shard-hearbeat-interval-in-millis {
             default 500;
             type heartbeat-interval-type;
index 04d889fbe0f61eaa822b9b286c9527ad1b1e5447..9e02223f54e18d4d844f8b2be9af188df261a901 100644 (file)
@@ -1,5 +1,11 @@
 package org.opendaylight.controller.cluster.datastore;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Test;
@@ -13,13 +19,6 @@ import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
 import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
 public class CompositeModificationPayloadTest {
 
 
@@ -60,6 +59,11 @@ public class CompositeModificationPayloadTest {
             @Override public long getIndex() {
                 return 1;
             }
+
+            @Override
+            public int size() {
+                return getData().size();
+            }
         });
 
         AppendEntries appendEntries =
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/RoleChangeNotifierTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/RoleChangeNotifierTest.java
new file mode 100644 (file)
index 0000000..4e61260
--- /dev/null
@@ -0,0 +1,79 @@
+package org.opendaylight.controller.cluster.datastore;
+
+
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import akka.testkit.JavaTestKit;
+import akka.testkit.TestActorRef;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.utils.MessageCollectorActor;
+import org.opendaylight.controller.cluster.notifications.RegisterRoleChangeListener;
+import org.opendaylight.controller.cluster.notifications.RegisterRoleChangeListenerReply;
+import org.opendaylight.controller.cluster.notifications.RoleChangeNotification;
+import org.opendaylight.controller.cluster.notifications.RoleChangeNotifier;
+import org.opendaylight.controller.cluster.notifications.RoleChanged;
+import org.opendaylight.controller.cluster.raft.RaftState;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+public class RoleChangeNotifierTest extends AbstractActorTest  {
+
+    @Test
+    public void testHandleRegisterRoleChangeListener() throws Exception {
+        new JavaTestKit(getSystem()) {{
+            String memberId = "testHandleRegisterRoleChangeListener";
+            ActorRef listenerActor =  getSystem().actorOf(Props.create(MessageCollectorActor.class));
+
+            TestActorRef<RoleChangeNotifier> notifierTestActorRef = TestActorRef.create(
+                getSystem(), RoleChangeNotifier.getProps(memberId), memberId);
+
+            notifierTestActorRef.tell(new RegisterRoleChangeListener(), listenerActor);
+
+            RegisterRoleChangeListenerReply reply = (RegisterRoleChangeListenerReply)
+                MessageCollectorActor.getFirstMatching(listenerActor, RegisterRoleChangeListenerReply.class);
+            assertNotNull(reply);
+
+            RoleChangeNotification notification = (RoleChangeNotification)
+                MessageCollectorActor.getFirstMatching(listenerActor, RoleChangeNotification.class);
+            assertNull(notification);
+        }};
+
+    }
+
+    @Test
+    public void testHandleRaftRoleChanged() throws Exception {
+        new JavaTestKit(getSystem()) {{
+            String memberId = "testHandleRegisterRoleChangeListenerWithNotificationSet";
+            ActorRef listenerActor =  getSystem().actorOf(Props.create(MessageCollectorActor.class));
+            ActorRef shardActor =  getTestActor();
+
+            TestActorRef<RoleChangeNotifier> notifierTestActorRef = TestActorRef.create(
+                getSystem(), RoleChangeNotifier.getProps(memberId), memberId);
+
+            RoleChangeNotifier roleChangeNotifier = notifierTestActorRef.underlyingActor();
+
+            notifierTestActorRef.tell(new RoleChanged(memberId, RaftState.Candidate.name(), RaftState.Leader.name()), shardActor);
+
+            // no notification should be sent as listener has not yet registered
+            assertNull(MessageCollectorActor.getFirstMatching(listenerActor, RoleChangeNotification.class));
+
+            // listener registers after role has been changed, ensure we sent the latest role change after a reply
+            notifierTestActorRef.tell(new RegisterRoleChangeListener(), listenerActor);
+
+            RegisterRoleChangeListenerReply reply = (RegisterRoleChangeListenerReply)
+                MessageCollectorActor.getFirstMatching(listenerActor, RegisterRoleChangeListenerReply.class);
+            assertNotNull(reply);
+
+            RoleChangeNotification notification = (RoleChangeNotification)
+                MessageCollectorActor.getFirstMatching(listenerActor, RoleChangeNotification.class);
+            assertNotNull(notification);
+            assertEquals(RaftState.Candidate.name(), notification.getOldRole());
+            assertEquals(RaftState.Leader.name(), notification.getNewRole());
+
+        }};
+
+    }
+}
+
+
index f75aa5445bc34de451c900311c3c91b3a4866f4e..4bd0ad818fff437ba8fbddac035ba9b4075b60b0 100644 (file)
@@ -8,10 +8,19 @@
 
 package org.opendaylight.controller.cluster.datastore.utils;
 
+import akka.actor.ActorRef;
 import akka.actor.UntypedActor;
 
+import akka.pattern.Patterns;
+import akka.util.Timeout;
+import com.google.common.collect.Lists;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
+import scala.concurrent.Await;
+import scala.concurrent.Future;
+import scala.concurrent.duration.Duration;
+import scala.concurrent.duration.FiniteDuration;
 
 /**
  * MessageCollectorActor collects messages as it receives them. It can send
@@ -27,10 +36,55 @@ public class MessageCollectorActor extends UntypedActor {
     @Override public void onReceive(Object message) throws Exception {
         if(message instanceof String){
             if("messages".equals(message)){
-                getSender().tell(messages, getSelf());
+                getSender().tell(new ArrayList(messages), getSelf());
             }
         } else {
             messages.add(message);
         }
     }
+
+    public static List<Object> getAllMessages(ActorRef actor) throws Exception {
+        FiniteDuration operationDuration = Duration.create(5, TimeUnit.SECONDS);
+        Timeout operationTimeout = new Timeout(operationDuration);
+        Future<Object> future = Patterns.ask(actor, "messages", operationTimeout);
+
+        try {
+            return (List<Object>) Await.result(future, operationDuration);
+        } catch (Exception e) {
+            throw e;
+        }
+    }
+
+    /**
+     * Get the first message that matches the specified class
+     * @param actor
+     * @param clazz
+     * @return
+     */
+    public static Object getFirstMatching(ActorRef actor, Class<?> clazz) throws Exception {
+        List<Object> allMessages = getAllMessages(actor);
+
+        for(Object message : allMessages){
+            if(message.getClass().equals(clazz)){
+                return message;
+            }
+        }
+
+        return null;
+    }
+
+    public static List<Object> getAllMatching(ActorRef actor, Class<?> clazz) throws Exception {
+        List<Object> allMessages = getAllMessages(actor);
+
+        List<Object> output = Lists.newArrayList();
+
+        for(Object message : allMessages){
+            if(message.getClass().equals(clazz)){
+                output.add(message);
+            }
+        }
+
+        return output;
+    }
+
 }
index a2b78c6c152dd350b7a4f8bffc075af0ea97cd92..a3041e89dbf9ac2a9139552c6cafff7437bc0390 100644 (file)
@@ -13,19 +13,18 @@ import akka.actor.ActorSystem;
 import akka.actor.Props;
 import akka.actor.UntypedActor;
 import com.typesafe.config.ConfigFactory;
-import org.opendaylight.controller.cluster.raft.protobuff.client.messages.CompositeModificationPayload;
+import java.util.ArrayList;
+import java.util.List;
 import org.opendaylight.controller.cluster.datastore.modification.MutableCompositeModification;
 import org.opendaylight.controller.cluster.datastore.modification.WriteModification;
 import org.opendaylight.controller.cluster.example.messages.KeyValue;
 import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
 import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
+import org.opendaylight.controller.cluster.raft.protobuff.client.messages.CompositeModificationPayload;
 import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
 import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 
-import java.util.ArrayList;
-import java.util.List;
-
 public class Client {
 
     private static ActorSystem actorSystem;
@@ -93,6 +92,11 @@ public class Client {
             @Override public long getIndex() {
                 return 1;
             }
+
+            @Override
+            public int size() {
+                return getData().size();
+            }
         });
 
         return new AppendEntries(1, "member-1", 0, 100, modification, 1);
@@ -113,6 +117,11 @@ public class Client {
             @Override public long getIndex() {
                 return 1;
             }
+
+            @Override
+            public int size() {
+                return getData().size();
+            }
         });
 
         return new AppendEntries(1, "member-1", 0, 100, modification, 1);
index b50dfb1ba3e196f66e33d74438d43a2aca2d81ee..6ffe147e71384b66ece31c4e701294c8630456c8 100644 (file)
@@ -15,26 +15,24 @@ import akka.actor.Props;
 import akka.cluster.ClusterActorRefProvider;
 import akka.event.Logging;
 import akka.event.LoggingAdapter;
-import org.opendaylight.controller.cluster.common.actor.AbstractUntypedActorWithMetering;
-import org.opendaylight.controller.remote.rpc.RemoteRpcProviderConfig;
-import org.opendaylight.controller.utils.ConditionalProbe;
-
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-
-import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetAllBuckets;
-import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetAllBucketsReply;
-import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketVersions;
-import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketVersionsReply;
-import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketsByMembers;
-import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketsByMembersReply;
-import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetLocalBucket;
-import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetLocalBucketReply;
-import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.UpdateBucket;
-import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.UpdateRemoteBuckets;
+import org.opendaylight.controller.cluster.common.actor.AbstractUntypedActorWithMetering;
+import org.opendaylight.controller.remote.rpc.RemoteRpcProviderConfig;
+import org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetAllBuckets;
+import org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetAllBucketsReply;
+import org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketVersions;
+import org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketVersionsReply;
+import org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketsByMembers;
+import org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketsByMembersReply;
+import org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetLocalBucket;
+import org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetLocalBucketReply;
+import org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.UpdateBucket;
+import org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.UpdateRemoteBuckets;
+import org.opendaylight.controller.utils.ConditionalProbe;
 
 /**
  * A store that syncs its data across nodes in the cluster.
@@ -82,8 +80,9 @@ public class BucketStore extends AbstractUntypedActorWithMetering {
         ActorRefProvider provider = getContext().provider();
         selfAddress = provider.getDefaultAddress();
 
-        if ( provider instanceof ClusterActorRefProvider)
+        if ( provider instanceof ClusterActorRefProvider) {
             getContext().actorOf(Props.create(Gossiper.class).withMailbox(config.getMailBoxName()), "gossiper");
+        }
     }
 
 
@@ -94,8 +93,11 @@ public class BucketStore extends AbstractUntypedActorWithMetering {
         }
 
         if (message instanceof ConditionalProbe) {
+            // The ConditionalProbe is only used for unit tests.
             log.info("Received probe {} {}", getSelf(), message);
             probe = (ConditionalProbe) message;
+            // Send back any message to tell the caller we got the probe.
+            getSender().tell("Got it", getSelf());
         } else if (message instanceof UpdateBucket) {
             receiveUpdateBucket(((UpdateBucket) message).getBucket());
         } else if (message instanceof GetAllBuckets) {
@@ -184,13 +186,15 @@ public class BucketStore extends AbstractUntypedActorWithMetering {
         Map<Address, Bucket> buckets = new HashMap<>();
 
         //first add the local bucket if asked
-        if (members.contains(selfAddress))
+        if (members.contains(selfAddress)) {
             buckets.put(selfAddress, localBucket);
+        }
 
         //then get buckets for requested remote nodes
         for (Address address : members){
-            if (remoteBuckets.containsKey(address))
+            if (remoteBuckets.containsKey(address)) {
                 buckets.put(address, remoteBuckets.get(address));
+            }
         }
 
         return buckets;
@@ -214,7 +218,9 @@ public class BucketStore extends AbstractUntypedActorWithMetering {
     void receiveUpdateRemoteBuckets(Map<Address, Bucket> receivedBuckets){
 
         if (receivedBuckets == null || receivedBuckets.isEmpty())
+         {
             return; //nothing to do
+        }
 
         //Remote cant update self's bucket
         receivedBuckets.remove(selfAddress);
@@ -222,15 +228,20 @@ public class BucketStore extends AbstractUntypedActorWithMetering {
         for (Map.Entry<Address, Bucket> entry : receivedBuckets.entrySet()){
 
             Long localVersion = versions.get(entry.getKey());
-            if (localVersion == null) localVersion = -1L;
+            if (localVersion == null) {
+                localVersion = -1L;
+            }
 
             Bucket receivedBucket = entry.getValue();
 
-            if (receivedBucket == null)
+            if (receivedBucket == null) {
                 continue;
+            }
 
             Long remoteVersion = receivedBucket.getVersion();
-            if (remoteVersion == null) remoteVersion = -1L;
+            if (remoteVersion == null) {
+                remoteVersion = -1L;
+            }
 
             //update only if remote version is newer
             if ( remoteVersion.longValue() > localVersion.longValue() ) {
index ee96cb897fccd45239badad8cef7a0a161edd467..e0d145dbe179b4af06109f1df28151b066b50cd8 100644 (file)
@@ -1,14 +1,22 @@
 package org.opendaylight.controller.remote.rpc.registry;
 
-
 import akka.actor.ActorPath;
 import akka.actor.ActorRef;
 import akka.actor.ActorSelection;
 import akka.actor.ActorSystem;
 import akka.actor.ChildActorPath;
 import akka.actor.Props;
+import akka.pattern.Patterns;
 import akka.testkit.JavaTestKit;
+import akka.util.Timeout;
 import com.google.common.base.Predicate;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import javax.annotation.Nullable;
 import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Before;
@@ -16,224 +24,226 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.controller.remote.rpc.RemoteRpcProviderConfig;
 import org.opendaylight.controller.remote.rpc.RouteIdentifierImpl;
+import org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.AddOrUpdateRoutes;
+import org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.RemoveRoutes;
+import org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.SetLocalRouter;
 import org.opendaylight.controller.remote.rpc.registry.gossip.Messages;
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import org.opendaylight.controller.utils.ConditionalProbe;
 import org.opendaylight.yangtools.yang.common.QName;
+import scala.concurrent.Await;
+import scala.concurrent.Future;
+import scala.concurrent.duration.Duration;
 import scala.concurrent.duration.FiniteDuration;
 
-import javax.annotation.Nullable;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.AddOrUpdateRoutes;
-import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.RemoveRoutes;
-import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.SetLocalRouter;
-
 public class RpcRegistryTest {
 
-  private static ActorSystem node1;
-  private static ActorSystem node2;
-  private static ActorSystem node3;
-
-  private ActorRef registry1;
-  private ActorRef registry2;
-  private ActorRef registry3;
-
-  @BeforeClass
-  public static void setup() throws InterruptedException {
-    RemoteRpcProviderConfig config1 = new RemoteRpcProviderConfig.Builder("memberA").build();
-    RemoteRpcProviderConfig config2 = new RemoteRpcProviderConfig.Builder("memberB").build();
-    RemoteRpcProviderConfig config3 = new RemoteRpcProviderConfig.Builder("memberC").build();
-    node1 = ActorSystem.create("opendaylight-rpc", config1.get());
-    node2 = ActorSystem.create("opendaylight-rpc", config2.get());
-    node3 = ActorSystem.create("opendaylight-rpc", config3.get());
-  }
-
-  @AfterClass
-  public static void teardown() {
-    JavaTestKit.shutdownActorSystem(node1);
-    JavaTestKit.shutdownActorSystem(node2);
-    JavaTestKit.shutdownActorSystem(node3);
-    if (node1 != null)
-      node1.shutdown();
-    if (node2 != null)
-      node2.shutdown();
-    if (node3 != null)
-      node3.shutdown();
-
-  }
-
-  @Before
-  public void createRpcRegistry() throws InterruptedException {
-    registry1 = node1.actorOf(Props.create(RpcRegistry.class));
-    registry2 = node2.actorOf(Props.create(RpcRegistry.class));
-    registry3 = node3.actorOf(Props.create(RpcRegistry.class));
-  }
-
-  @After
-  public void stopRpcRegistry() throws InterruptedException {
-    if (registry1 != null)
-      node1.stop(registry1);
-    if (registry2 != null)
-      node2.stop(registry2);
-    if (registry3 != null)
-      node3.stop(registry3);
-  }
-
-  /**
-   * One node cluster.
-   * 1. Register rpc, ensure router can be found
-   * 2. Then remove rpc, ensure its deleted
-   *
-   * @throws URISyntaxException
-   * @throws InterruptedException
-   */
-  @Test
-  public void testAddRemoveRpcOnSameNode() throws URISyntaxException, InterruptedException {
-
-    final JavaTestKit mockBroker = new JavaTestKit(node1);
-
-    final ActorPath bucketStorePath = new ChildActorPath(registry1.path(), "store");
-
-    //install probe
-    final JavaTestKit probe1 = createProbeForMessage(
-        node1, bucketStorePath, Messages.BucketStoreMessages.UpdateBucket.class);
-
-    //Add rpc on node 1
-    registry1.tell(new SetLocalRouter(mockBroker.getRef()), mockBroker.getRef());
-    registry1.tell(getAddRouteMessage(), mockBroker.getRef());
-
-    //Bucket store should get an update bucket message. Updated bucket contains added rpc.
-    probe1.expectMsgClass(
-        FiniteDuration.apply(10, TimeUnit.SECONDS),
-        Messages.BucketStoreMessages.UpdateBucket.class);
-
-    //Now remove rpc
-    registry1.tell(getRemoveRouteMessage(), mockBroker.getRef());
-
-    //Bucket store should get an update bucket message. Rpc is removed in the updated bucket
-    probe1.expectMsgClass(
-        FiniteDuration.apply(10, TimeUnit.SECONDS),
-        Messages.BucketStoreMessages.UpdateBucket.class);
-
-
-  }
-
-
-  /**
-   * Three node cluster.
-   * 1. Register rpc on 1 node, ensure 2nd node gets updated
-   * 2. Remove rpc on 1 node, ensure 2nd node gets updated
-   *
-   * @throws URISyntaxException
-   * @throws InterruptedException
-   */
-  @Test
-  public void testRpcAddRemoveInCluster() throws URISyntaxException, InterruptedException {
-
-    final JavaTestKit mockBroker1 = new JavaTestKit(node1);
-
-    //install probe on node2's bucket store
-    final ActorPath bucketStorePath = new ChildActorPath(registry2.path(), "store");
-    final JavaTestKit probe2 = createProbeForMessage(
-        node2, bucketStorePath, Messages.BucketStoreMessages.UpdateRemoteBuckets.class);
-
-    //Add rpc on node 1
-    registry1.tell(new SetLocalRouter(mockBroker1.getRef()), mockBroker1.getRef());
-    registry1.tell(getAddRouteMessage(), mockBroker1.getRef());
-
-    //Bucket store on node2 should get a message to update its local copy of remote buckets
-    probe2.expectMsgClass(
-        FiniteDuration.apply(10, TimeUnit.SECONDS),
-        Messages.BucketStoreMessages.UpdateRemoteBuckets.class);
-
-    //Now remove
-    registry1.tell(getRemoveRouteMessage(), mockBroker1.getRef());
-
-    //Bucket store on node2 should get a message to update its local copy of remote buckets
-    probe2.expectMsgClass(
-        FiniteDuration.apply(10, TimeUnit.SECONDS),
-        Messages.BucketStoreMessages.UpdateRemoteBuckets.class);
-
-  }
-
-  /**
-   * Three node cluster.
-   * Register rpc on 2 nodes. Ensure 3rd gets updated.
-   *
-   * @throws Exception
-   */
-  @Test
-  public void testRpcAddedOnMultiNodes() throws Exception {
-
-    final JavaTestKit mockBroker1 = new JavaTestKit(node1);
-    final JavaTestKit mockBroker2 = new JavaTestKit(node2);
-    final JavaTestKit mockBroker3 = new JavaTestKit(node3);
-
-    registry3.tell(new SetLocalRouter(mockBroker3.getRef()), mockBroker3.getRef());
-
-    //install probe on node 3
-    final ActorPath bucketStorePath = new ChildActorPath(registry3.path(), "store");
-    final JavaTestKit probe3 = createProbeForMessage(
-        node3, bucketStorePath, Messages.BucketStoreMessages.UpdateRemoteBuckets.class);
-
-
-    //Add rpc on node 1
-    registry1.tell(new SetLocalRouter(mockBroker1.getRef()), mockBroker1.getRef());
-    registry1.tell(getAddRouteMessage(), mockBroker1.getRef());
-
-    probe3.expectMsgClass(
-        FiniteDuration.apply(10, TimeUnit.SECONDS),
-        Messages.BucketStoreMessages.UpdateRemoteBuckets.class);
-
+    private static ActorSystem node1;
+    private static ActorSystem node2;
+    private static ActorSystem node3;
+
+    private ActorRef registry1;
+    private ActorRef registry2;
+    private ActorRef registry3;
+
+    @BeforeClass
+    public static void staticSetup() throws InterruptedException {
+      RemoteRpcProviderConfig config1 = new RemoteRpcProviderConfig.Builder("memberA").build();
+      RemoteRpcProviderConfig config2 = new RemoteRpcProviderConfig.Builder("memberB").build();
+      RemoteRpcProviderConfig config3 = new RemoteRpcProviderConfig.Builder("memberC").build();
+      node1 = ActorSystem.create("opendaylight-rpc", config1.get());
+      node2 = ActorSystem.create("opendaylight-rpc", config2.get());
+      node3 = ActorSystem.create("opendaylight-rpc", config3.get());
+    }
+
+    @AfterClass
+    public static void staticTeardown() {
+      JavaTestKit.shutdownActorSystem(node1);
+      JavaTestKit.shutdownActorSystem(node2);
+      JavaTestKit.shutdownActorSystem(node3);
+    }
+
+    @Before
+    public void setup() {
+        registry1 = node1.actorOf(Props.create(RpcRegistry.class));
+        registry2 = node2.actorOf(Props.create(RpcRegistry.class));
+        registry3 = node3.actorOf(Props.create(RpcRegistry.class));
+    }
+
+    @After
+    public void teardown() {
+        if (registry1 != null) {
+            node1.stop(registry1);
+        }
+        if (registry2 != null) {
+            node2.stop(registry2);
+        }
+        if (registry3 != null) {
+            node3.stop(registry3);
+        }
+    }
+
+    /**
+     * One node cluster. 1. Register rpc, ensure router can be found 2. Then remove rpc, ensure its
+     * deleted
+     *
+     * @throws URISyntaxException
+     * @throws InterruptedException
+     */
+    @Test
+    public void testAddRemoveRpcOnSameNode() throws Exception {
+
+        System.out.println("testAddRemoveRpcOnSameNode starting");
+
+        final JavaTestKit mockBroker = new JavaTestKit(node1);
+
+        final ActorPath bucketStorePath = new ChildActorPath(registry1.path(), "store");
+
+        // Add rpc on node 1
+        registry1.tell(new SetLocalRouter(mockBroker.getRef()), mockBroker.getRef());
+
+        // install probe
+        final JavaTestKit probe1 = createProbeForMessage(node1, bucketStorePath,
+                Messages.BucketStoreMessages.UpdateBucket.class);
+
+        registry1.tell(getAddRouteMessage(), mockBroker.getRef());
+
+        // Bucket store should get an update bucket message. Updated bucket contains added rpc.
+        probe1.expectMsgClass(FiniteDuration.apply(10, TimeUnit.SECONDS),
+                Messages.BucketStoreMessages.UpdateBucket.class);
+
+        // Now remove rpc
+        registry1.tell(getRemoveRouteMessage(), mockBroker.getRef());
+
+        // Bucket store should get an update bucket message. Rpc is removed in the updated bucket
+        probe1.expectMsgClass(FiniteDuration.apply(10, TimeUnit.SECONDS),
+                Messages.BucketStoreMessages.UpdateBucket.class);
+
+        System.out.println("testAddRemoveRpcOnSameNode ending");
+
+    }
+
+    /**
+     * Three node cluster. 1. Register rpc on 1 node, ensure 2nd node gets updated 2. Remove rpc on
+     * 1 node, ensure 2nd node gets updated
+     *
+     * @throws URISyntaxException
+     * @throws InterruptedException
+     */
+    @Test
+    public void testRpcAddRemoveInCluster() throws Exception {
+
+        System.out.println("testRpcAddRemoveInCluster starting");
+
+        final JavaTestKit mockBroker1 = new JavaTestKit(node1);
+
+        // install probe on node2's bucket store
+        final ActorPath bucketStorePath = new ChildActorPath(registry2.path(), "store");
+        final JavaTestKit probe2 = createProbeForMessage(node2, bucketStorePath,
+                Messages.BucketStoreMessages.UpdateRemoteBuckets.class);
+
+        // Add rpc on node 1
+        registry1.tell(new SetLocalRouter(mockBroker1.getRef()), mockBroker1.getRef());
+        registry1.tell(getAddRouteMessage(), mockBroker1.getRef());
+
+        // Bucket store on node2 should get a message to update its local copy of remote buckets
+        probe2.expectMsgClass(FiniteDuration.apply(10, TimeUnit.SECONDS),
+                Messages.BucketStoreMessages.UpdateRemoteBuckets.class);
+
+        // Now remove
+        registry1.tell(getRemoveRouteMessage(), mockBroker1.getRef());
+
+        // Bucket store on node2 should get a message to update its local copy of remote buckets
+        probe2.expectMsgClass(FiniteDuration.apply(10, TimeUnit.SECONDS),
+                Messages.BucketStoreMessages.UpdateRemoteBuckets.class);
+
+        System.out.println("testRpcAddRemoveInCluster ending");
+    }
+
+    /**
+     * Three node cluster. Register rpc on 2 nodes. Ensure 3rd gets updated.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testRpcAddedOnMultiNodes() throws Exception {
+
+        final JavaTestKit mockBroker1 = new JavaTestKit(node1);
+        final JavaTestKit mockBroker2 = new JavaTestKit(node2);
+        final JavaTestKit mockBroker3 = new JavaTestKit(node3);
+
+        registry3.tell(new SetLocalRouter(mockBroker3.getRef()), mockBroker3.getRef());
+
+        // install probe on node 3
+        final ActorPath bucketStorePath = new ChildActorPath(registry3.path(), "store");
+        final JavaTestKit probe3 = createProbeForMessage(node3, bucketStorePath,
+                Messages.BucketStoreMessages.UpdateRemoteBuckets.class);
+
+        // Add rpc on node 1
+        registry1.tell(new SetLocalRouter(mockBroker1.getRef()), mockBroker1.getRef());
+        registry1.tell(getAddRouteMessage(), mockBroker1.getRef());
 
-    //Add same rpc on node 2
-    registry2.tell(new SetLocalRouter(mockBroker2.getRef()), mockBroker2.getRef());
-    registry2.tell(getAddRouteMessage(), mockBroker2.getRef());
+        probe3.expectMsgClass(FiniteDuration.apply(10, TimeUnit.SECONDS),
+                Messages.BucketStoreMessages.UpdateRemoteBuckets.class);
 
-    probe3.expectMsgClass(
-        FiniteDuration.apply(10, TimeUnit.SECONDS),
-        Messages.BucketStoreMessages.UpdateRemoteBuckets.class);
-  }
-
-  private JavaTestKit createProbeForMessage(ActorSystem node, ActorPath subjectPath, final Class<?> clazz) {
-    final JavaTestKit probe = new JavaTestKit(node);
+        // Add same rpc on node 2
+        registry2.tell(new SetLocalRouter(mockBroker2.getRef()), mockBroker2.getRef());
+        registry2.tell(getAddRouteMessage(), mockBroker2.getRef());
 
-    ConditionalProbe conditionalProbe =
-        new ConditionalProbe(probe.getRef(), new Predicate<Object>() {
-          @Override
-          public boolean apply(@Nullable Object input) {
-              if (input != null)
-                return clazz.equals(input.getClass());
-              else
-                  return false;
-          }
-        });
-
-    ActorSelection subject = node.actorSelection(subjectPath);
-    subject.tell(conditionalProbe, ActorRef.noSender());
-
-    return probe;
+        probe3.expectMsgClass(FiniteDuration.apply(10, TimeUnit.SECONDS),
+                Messages.BucketStoreMessages.UpdateRemoteBuckets.class);
+    }
 
-  }
+    private JavaTestKit createProbeForMessage(ActorSystem node, ActorPath subjectPath, final Class<?> clazz)
+            throws Exception {
+        final JavaTestKit probe = new JavaTestKit(node);
 
-  private AddOrUpdateRoutes getAddRouteMessage() throws URISyntaxException {
-    return new AddOrUpdateRoutes(createRouteIds());
-  }
-
-  private RemoveRoutes getRemoveRouteMessage() throws URISyntaxException {
-    return new RemoveRoutes(createRouteIds());
-  }
+        ConditionalProbe conditionalProbe = new ConditionalProbe(probe.getRef(), new Predicate<Object>() {
+            @Override
+            public boolean apply(@Nullable Object input) {
+                if (input != null) {
+                    return clazz.equals(input.getClass());
+                } else {
+                    return false;
+                }
+            }
+        });
 
-  private List<RpcRouter.RouteIdentifier<?, ?, ?>> createRouteIds() throws URISyntaxException {
-    QName type = new QName(new URI("/mockrpc"), "mockrpc");
-    List<RpcRouter.RouteIdentifier<?, ?, ?>> routeIds = new ArrayList<>();
-    routeIds.add(new RouteIdentifierImpl(null, type, null));
-    return routeIds;
-  }
+        FiniteDuration duration = Duration.create(3, TimeUnit.SECONDS);
+        Timeout timeout = new Timeout(duration);
+        int maxTries = 30;
+        int i = 0;
+        while(true) {
+            ActorSelection subject = node.actorSelection(subjectPath);
+            Future<Object> future = Patterns.ask(subject, conditionalProbe, timeout);
+
+            try {
+                Await.ready(future, duration);
+                break;
+            } catch (TimeoutException | InterruptedException e) {
+                if(++i > maxTries) {
+                    throw e;
+                }
+            }
+        }
+
+        return probe;
+
+    }
+
+    private AddOrUpdateRoutes getAddRouteMessage() throws URISyntaxException {
+        return new AddOrUpdateRoutes(createRouteIds());
+    }
+
+    private RemoveRoutes getRemoveRouteMessage() throws URISyntaxException {
+        return new RemoveRoutes(createRouteIds());
+    }
+
+    private List<RpcRouter.RouteIdentifier<?, ?, ?>> createRouteIds() throws URISyntaxException {
+        QName type = new QName(new URI("/mockrpc"), "mockrpc");
+        List<RpcRouter.RouteIdentifier<?, ?, ?>> routeIds = new ArrayList<>();
+        routeIds.add(new RouteIdentifierImpl(null, type, null));
+        return routeIds;
+    }
 
 }
diff --git a/opendaylight/md-sal/statistics-manager-config/pom.xml b/opendaylight/md-sal/statistics-manager-config/pom.xml
new file mode 100644 (file)
index 0000000..f4b5f76
--- /dev/null
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2014 Cisco Systems, Inc. and others.  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
+-->
+<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">
+
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-parent</artifactId>
+        <version>1.2.0-SNAPSHOT</version>
+    </parent>
+
+    <groupId>org.opendaylight.controller.md</groupId>
+    <artifactId>statistics-manager-config</artifactId>
+    <description>Configuration files for statistics manager</description>
+    <packaging>jar</packaging>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>attach-artifacts</id>
+                        <goals>
+                            <goal>attach-artifact</goal>
+                        </goals>
+                        <phase>package</phase>
+                        <configuration>
+                            <artifacts>
+                                <artifact>
+                                    <file>${project.build.directory}/classes/initial/30-statistics-manager.xml</file>
+                                    <type>xml</type>
+                                    <classifier>config</classifier>
+                                </artifact>
+                            </artifacts>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/opendaylight/md-sal/statistics-manager-config/src/main/resources/initial/30-statistics-manager.xml b/opendaylight/md-sal/statistics-manager-config/src/main/resources/initial/30-statistics-manager.xml
new file mode 100644 (file)
index 0000000..797c14e
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2014 Cisco Systems, Inc. and others.  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
+-->
+<snapshot>
+    <configuration>
+        <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+            <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+                <module>
+                    <type xmlns:statsmanager="urn:opendaylight:params:xml:ns:yang:controller:md:sal:statistics-manager">
+                        statsmanager:statistics-manager
+                    </type>
+                    <name>statistics-manager</name>
+
+                    <rpc-registry>
+                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+                        <name>binding-rpc-broker</name>
+                    </rpc-registry>
+
+                    <data-broker>
+                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
+                        <name>binding-data-broker</name>
+                    </data-broker>
+
+                    <notification-service>
+                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+                            binding:binding-notification-service
+                        </type>
+                        <name>binding-notification-broker</name>
+                    </notification-service>
+
+                    <statistics-manager-settings>
+                        <min-request-net-monitor-interval>3000</min-request-net-monitor-interval>
+                        <max-nodes-for-collector>16</max-nodes-for-collector>
+                    </statistics-manager-settings>
+
+                </module>
+            </modules>
+        </data>
+    </configuration>
+
+    <required-capabilities>
+        <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:statistics-manager?module=statistics-manager&amp;revision=2014-09-25</capability>
+    </required-capabilities>
+
+</snapshot>
+
index eb6c51b35194e54c2c33ebc220668a99270a134a..234e1084f6a4ff5447d4c8552d984bd3d4c325c0 100644 (file)
       <artifactId>org.osgi.core</artifactId>
       <scope>provided</scope>
     </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-binding-config</artifactId>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>config-api</artifactId>
+      </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-log4j12</artifactId>
 
   <build>
     <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <configuration>
-          <instructions>
-            <Bundle-Activator>org.opendaylight.controller.md.statistics.manager.StatisticsManagerActivator</Bundle-Activator>
-          </instructions>
-        </configuration>
-      </plugin>
+        <plugin>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>maven-bundle-plugin</artifactId>
+            <configuration>
+                <instructions>
+                    <Import-Package>*</Import-Package>
+                </instructions>
+            </configuration>
+        </plugin>
+        <plugin>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-maven-plugin</artifactId>
+            <executions>
+                <execution>
+                    <id>config</id>
+                    <goals>
+                        <goal>generate-sources</goal>
+                    </goals>
+                    <configuration>
+                        <codeGenerators>
+                            <generator>
+                                <codeGeneratorClass>org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator</codeGeneratorClass>
+                                <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
+                                <additionalConfiguration>
+                                    <namespaceToPackage1>urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang</namespaceToPackage1>
+                                </additionalConfiguration>
+                            </generator>
+                            <generator>
+                                <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+                                <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+                            </generator>
+                        </codeGenerators>
+                        <inspectDependencies>true</inspectDependencies>
+                    </configuration>
+                </execution>
+            </executions>
+        </plugin>
     </plugins>
   </build>
   <scm>
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/config/yang/md/sal/statistics_manager/StatisticsManagerModule.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/config/yang/md/sal/statistics_manager/StatisticsManagerModule.java
new file mode 100644 (file)
index 0000000..fb920a6
--- /dev/null
@@ -0,0 +1,71 @@
+package org.opendaylight.controller.config.yang.md.sal.statistics_manager;
+
+import org.opendaylight.controller.md.statistics.manager.StatisticsManager;
+import org.opendaylight.controller.md.statistics.manager.impl.StatisticsManagerConfig;
+import org.opendaylight.controller.md.statistics.manager.impl.StatisticsManagerImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class StatisticsManagerModule extends org.opendaylight.controller.config.yang.md.sal.statistics_manager.AbstractStatisticsManagerModule {
+    private final static Logger LOG = LoggerFactory.getLogger(StatisticsManagerModule.class);
+
+    private final static int MAX_NODES_FOR_COLLECTOR_DEFAULT = 16;
+    private final static int MIN_REQUEST_NET_MONITOR_INTERVAL_DEFAULT = 3000;
+
+    private StatisticsManager statisticsManagerProvider;
+
+    public StatisticsManagerModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public StatisticsManagerModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, final StatisticsManagerModule oldModule, final java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+        // add custom validation form module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        LOG.info("StatisticsManager module initialization.");
+        final StatisticsManagerConfig config = createConfig();
+        statisticsManagerProvider = new StatisticsManagerImpl(getDataBrokerDependency(), config);
+        statisticsManagerProvider.start(getNotificationServiceDependency(), getRpcRegistryDependency());
+        LOG.info("StatisticsManager started successfully.");
+        return new AutoCloseable() {
+            @Override
+            public void close() throws Exception {
+                try {
+                    statisticsManagerProvider.close();
+                }
+                catch (final Exception e) {
+                    LOG.error("Unexpected error by stopping StatisticsManager module", e);
+                }
+                LOG.info("StatisticsManager module stopped.");
+            }
+        };
+    }
+
+    public StatisticsManagerConfig createConfig() {
+        final StatisticsManagerConfig.StatisticsManagerConfigBuilder builder = StatisticsManagerConfig.builder();
+        if (getStatisticsManagerSettings() != null && getStatisticsManagerSettings().getMaxNodesForCollector() != null) {
+            builder.setMaxNodesForCollector(getStatisticsManagerSettings().getMaxNodesForCollector());
+        } else {
+            LOG.warn("Load the xml ConfigSubsystem input value fail! MaxNodesForCollector value is set to {} ",
+                    MAX_NODES_FOR_COLLECTOR_DEFAULT);
+            builder.setMaxNodesForCollector(MAX_NODES_FOR_COLLECTOR_DEFAULT);
+        }
+        if (getStatisticsManagerSettings() != null &&
+                getStatisticsManagerSettings().getMinRequestNetMonitorInterval() != null) {
+            builder.setMinRequestNetMonitorInterval(getStatisticsManagerSettings().getMinRequestNetMonitorInterval());
+        } else {
+            LOG.warn("Load the xml CofnigSubsystem input value fail! MinRequestNetMonitorInterval value is set to {} ",
+                    MIN_REQUEST_NET_MONITOR_INTERVAL_DEFAULT);
+            builder.setMinRequestNetMonitorInterval(MIN_REQUEST_NET_MONITOR_INTERVAL_DEFAULT);
+        }
+        return builder.build();
+    }
+
+}
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/config/yang/md/sal/statistics_manager/StatisticsManagerModuleFactory.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/config/yang/md/sal/statistics_manager/StatisticsManagerModuleFactory.java
new file mode 100644 (file)
index 0000000..dc37447
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: statistics-manager yang module local name: statistics-manager
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Tue Oct 07 14:09:47 CEST 2014
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.md.sal.statistics_manager;
+public class StatisticsManagerModuleFactory extends org.opendaylight.controller.config.yang.md.sal.statistics_manager.AbstractStatisticsManagerModuleFactory {
+
+}
index 7d57067df167ca95c0c1f8bc3b570c7ab4707a7a..831dc224d113ec364257e57a292d98b24b908cc3 100644 (file)
@@ -13,6 +13,7 @@ import java.util.List;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
 import org.opendaylight.controller.md.statistics.manager.StatPermCollector.StatCapabTypes;
+import org.opendaylight.controller.md.statistics.manager.impl.StatisticsManagerConfig;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
 import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
@@ -70,7 +71,7 @@ public interface StatisticsManager extends AutoCloseable, TransactionChainListen
      * @param minReqNetMonitInt
      */
     void start(final NotificationProviderService notifService,
-            final RpcConsumerRegistry rpcRegistry, final long minReqNetMonitInt);
+            final RpcConsumerRegistry rpcRegistry);
 
     /**
      * Method provides read/write DataStore functionality cross applyOperation
@@ -185,5 +186,7 @@ public interface StatisticsManager extends AutoCloseable, TransactionChainListen
      */
     StatNotifyCommiter<OpendaylightPortStatisticsListener> getPortNotifyCommit();
 
+    StatisticsManagerConfig getConfiguration();
+
 }
 
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerActivator.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerActivator.java
deleted file mode 100644 (file)
index c505af4..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright IBM Corporation, 2013.  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
- */
-
-package org.opendaylight.controller.md.statistics.manager;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.statistics.manager.impl.StatisticsManagerImpl;
-import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.osgi.framework.BundleContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.annotations.VisibleForTesting;
-
-/**
- * Statistics Manager Activator
- *
- * OSGi bundle activator
- *
- */
-public class StatisticsManagerActivator extends AbstractBindingAwareProvider {
-
-    private final static Logger LOG = LoggerFactory.getLogger(StatisticsManagerActivator.class);
-
-    /* TODO move it to ConfigSubsystem */
-    private static final long DEFAULT_MIN_REQUEST_NET_MONITOR_INTERVAL = 3000L;
-    private static final int MAX_NODES_FOR_COLLECTOR = 16;
-
-    private StatisticsManager statsProvider;
-
-    @Override
-    public void onSessionInitiated(final ProviderContext session) {
-        LOG.info("StatisticsManagerActivator initialization.");
-        try {
-            final DataBroker dataBroker = session.getSALService(DataBroker.class);
-            final NotificationProviderService notifService =
-                    session.getSALService(NotificationProviderService.class);
-            statsProvider = new StatisticsManagerImpl(dataBroker, MAX_NODES_FOR_COLLECTOR);
-            statsProvider.start(notifService, session, DEFAULT_MIN_REQUEST_NET_MONITOR_INTERVAL);
-            LOG.info("StatisticsManagerActivator started successfully.");
-        }
-        catch (final Exception e) {
-            LOG.error("Unexpected error by initialization of StatisticsManagerActivator", e);
-            stopImpl(null);
-        }
-    }
-
-    @VisibleForTesting
-    StatisticsManager getStatisticManager() {
-        return statsProvider;
-    }
-
-    @Override
-    protected void stopImpl(final BundleContext context) {
-        if (statsProvider != null) {
-            try {
-                statsProvider.close();
-            }
-            catch (final Exception e) {
-                LOG.error("Unexpected error by stopping StatisticsManagerActivator", e);
-            }
-            statsProvider = null;
-        }
-        LOG.info("StatisticsManagerActivator stoped.");
-    }
-}
index 07e167d1e481aa427e53ba869182e10472fc28df..f5c5689b7bcbe162178ff44e42c2742ecd3574c6 100644 (file)
@@ -26,6 +26,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.Fl
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
@@ -167,11 +168,13 @@ public class StatListenCommitQueue extends StatAbstractListenCommit<Queue, Opend
                             new FlowCapableNodeConnectorQueueStatisticsDataBuilder();
                     statBuild.setFlowCapableNodeConnectorQueueStatistics(statChild);
                     final QueueKey qKey = new QueueKey(queueStat.getQueueId());
-                    final InstanceIdentifier<FlowCapableNodeConnectorQueueStatisticsData> queueStatIdent = nodeIdent
+                    final InstanceIdentifier<Queue> queueIdent = nodeIdent
                             .child(NodeConnector.class, new NodeConnectorKey(queueStat.getNodeConnectorId()))
                             .augmentation(FlowCapableNodeConnector.class)
-                            .child(Queue.class, qKey).augmentation(FlowCapableNodeConnectorQueueStatisticsData.class);
+                            .child(Queue.class, qKey);
+                    final InstanceIdentifier<FlowCapableNodeConnectorQueueStatisticsData> queueStatIdent = queueIdent.augmentation(FlowCapableNodeConnectorQueueStatisticsData.class);
                     existQueueKeys.remove(qKey);
+                    tx.merge(LogicalDatastoreType.OPERATIONAL, queueIdent, new QueueBuilder().setKey(qKey).build());
                     tx.put(LogicalDatastoreType.OPERATIONAL, queueStatIdent, statBuild.build());
                 }
             }
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatisticsManagerConfig.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatisticsManagerConfig.java
new file mode 100644 (file)
index 0000000..0f56ea9
--- /dev/null
@@ -0,0 +1,48 @@
+package org.opendaylight.controller.md.statistics.manager.impl;
+
+public class StatisticsManagerConfig {
+    private final int maxNodesForCollector;
+    private final int minRequestNetMonitorInterval;
+
+    private StatisticsManagerConfig(StatisticsManagerConfigBuilder builder) {
+        this.maxNodesForCollector = builder.getMaxNodesForCollector();
+        this.minRequestNetMonitorInterval = builder.getMinRequestNetMonitorInterval();
+    }
+
+    public int getMaxNodesForCollector() {
+        return maxNodesForCollector;
+    }
+
+    public int getMinRequestNetMonitorInterval() {
+        return minRequestNetMonitorInterval;
+    }
+
+    public static StatisticsManagerConfigBuilder builder() {
+        return new StatisticsManagerConfigBuilder();
+    }
+
+    public static class StatisticsManagerConfigBuilder {
+        private int maxNodesForCollector;
+        private int minRequestNetMonitorInterval;
+
+        public int getMaxNodesForCollector() {
+            return maxNodesForCollector;
+        }
+
+        public void setMaxNodesForCollector(int maxNodesForCollector) {
+            this.maxNodesForCollector = maxNodesForCollector;
+        }
+
+        public int getMinRequestNetMonitorInterval() {
+            return minRequestNetMonitorInterval;
+        }
+
+        public void setMinRequestNetMonitorInterval(int minRequestNetMonitorInterval) {
+            this.minRequestNetMonitorInterval = minRequestNetMonitorInterval;
+        }
+
+        public StatisticsManagerConfig build() {
+            return new StatisticsManagerConfig(this);
+        }
+    }
+}
index 396ff0e1f6c8700d16b8e07f491d33e1fcc63bcf..edf9fad433f6af8244948fc181dfce97b3d24177 100644 (file)
@@ -8,15 +8,8 @@
 
 package org.opendaylight.controller.md.statistics.manager.impl;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingDeque;
-import java.util.concurrent.ThreadFactory;
-
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
@@ -46,8 +39,14 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.ThreadFactory;
 
 /**
 * statistics-manager
@@ -73,8 +72,6 @@ public class StatisticsManagerImpl implements StatisticsManager, Runnable {
    private final BlockingQueue<StatDataStoreOperation> dataStoreOperQueue = new LinkedBlockingDeque<>(QUEUE_DEPTH);
 
    private final DataBroker dataBroker;
-   private final int maxNodesForCollectors;
-   private long minReqNetMonitInt;
    private final ExecutorService statRpcMsgManagerExecutor;
    private final ExecutorService statDataStoreOperationServ;
    private StatRpcMsgManager rpcMsgManager;
@@ -91,23 +88,24 @@ public class StatisticsManagerImpl implements StatisticsManager, Runnable {
    private StatNotifyCommiter<OpendaylightFlowTableStatisticsListener> tableNotifCommiter;
    private StatNotifyCommiter<OpendaylightPortStatisticsListener> portNotifyCommiter;
 
-   public StatisticsManagerImpl (final DataBroker dataBroker, final int maxNodesForCollector) {
+   private final StatisticsManagerConfig statManagerConfig;
+
+   public StatisticsManagerImpl (final DataBroker dataBroker, StatisticsManagerConfig statManagerconfig) {
+       this.statManagerConfig = Preconditions.checkNotNull(statManagerconfig);
        this.dataBroker = Preconditions.checkNotNull(dataBroker, "DataBroker can not be null!");
        ThreadFactory threadFact;
        threadFact = new ThreadFactoryBuilder().setNameFormat("odl-stat-rpc-oper-thread-%d").build();
        statRpcMsgManagerExecutor = Executors.newSingleThreadExecutor(threadFact);
        threadFact = new ThreadFactoryBuilder().setNameFormat("odl-stat-ds-oper-thread-%d").build();
        statDataStoreOperationServ = Executors.newSingleThreadExecutor(threadFact);
-       maxNodesForCollectors = maxNodesForCollector;
        txChain =  dataBroker.createTransactionChain(this);
    }
 
    @Override
    public void start(final NotificationProviderService notifService,
-           final RpcConsumerRegistry rpcRegistry, final long minReqNetMonitInt) {
+           final RpcConsumerRegistry rpcRegistry) {
        Preconditions.checkArgument(rpcRegistry != null, "RpcConsumerRegistry can not be null !");
-       this.minReqNetMonitInt = minReqNetMonitInt;
-       rpcMsgManager = new StatRpcMsgManagerImpl(this, rpcRegistry, minReqNetMonitInt);
+       rpcMsgManager = new StatRpcMsgManagerImpl(this, rpcRegistry, statManagerConfig.getMinRequestNetMonitorInterval());
        statCollectors = Collections.emptyList();
        nodeRegistrator = new StatNodeRegistrationImpl(this, dataBroker, notifService);
        flowListeningCommiter = new StatListenCommitFlow(this, dataBroker, notifService);
@@ -272,7 +270,8 @@ public class StatisticsManagerImpl implements StatisticsManager, Runnable {
                }
            }
            final StatPermCollectorImpl newCollector = new StatPermCollectorImpl(this,
-                   minReqNetMonitInt, statCollectors.size() + 1, maxNodesForCollectors);
+                   statManagerConfig.getMinRequestNetMonitorInterval(), statCollectors.size() + 1,
+                   statManagerConfig.getMaxNodesForCollector());
            final List<StatPermCollector> statCollectorsNew = new ArrayList<>(statCollectors);
            newCollector.connectedNodeRegistration(nodeIdent, statTypes, nrOfSwitchTables);
            statCollectorsNew.add(newCollector);
@@ -355,5 +354,10 @@ public class StatisticsManagerImpl implements StatisticsManager, Runnable {
    public StatNotifyCommiter<OpendaylightPortStatisticsListener> getPortNotifyCommit() {
        return portNotifyCommiter;
    }
+
+    @Override
+    public StatisticsManagerConfig getConfiguration() {
+        return statManagerConfig;
+    }
 }
 
diff --git a/opendaylight/md-sal/statistics-manager/src/main/yang/statistics-manager.yang b/opendaylight/md-sal/statistics-manager/src/main/yang/statistics-manager.yang
new file mode 100644 (file)
index 0000000..5f35f70
--- /dev/null
@@ -0,0 +1,66 @@
+module statistics-manager {
+
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:statistics-manager";
+    prefix "statistics-manager";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
+
+    description
+        "This module contains the base YANG definitions for
+        statitics-manager implementation.";
+
+    revision "2014-09-25" {
+        description
+            "Initial revision.";
+    }
+
+    identity statistics-manager {
+            base config:module-type;
+            config:java-name-prefix StatisticsManager;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case statistics-manager {
+            when "/config:modules/config:module/config:type = 'statistics-manager'";
+
+            container rpc-registry {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity mdsal:binding-rpc-registry;
+                    }
+                }
+            }
+
+            container notification-service {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity mdsal:binding-notification-service;
+                    }
+                }
+            }
+
+            container data-broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory false;
+                        config:required-identity mdsal:binding-async-data-broker;
+                    }
+                }
+            }
+
+            container statistics-manager-settings {
+                leaf min-request-net-monitor-interval {
+                    type int32;
+                }
+                leaf max-nodes-for-collector {
+                    type int32;
+                }
+            }
+        }
+    }
+
+}
diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerProvider.java b/opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerProvider.java
deleted file mode 100644 (file)
index 6a01cd2..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  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
- */
-
-package org.opendaylight.controller.md.statistics.manager;
-
-/**
- * statistics-manager
- * org.opendaylight.controller.md.statistics.manager
- *
- *
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- * Created: Sep 6, 2014
- */
-public class StatisticsManagerProvider {
-
-    private final StatisticsManagerActivator activator;
-
-    public StatisticsManagerProvider(final StatisticsManagerActivator activator) {
-        this.activator = activator;
-    }
-
-    /**
-     * Method provides Initialized {@link StatisticsManager}
-     * from {@link StatisticsManagerActivator} for all tests
-     * suites;
-     *
-     * @return
-     */
-    public StatisticsManager getStatisticsManager() {
-        return activator.getStatisticManager();
-    }
-}
diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/FlowStatisticsTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/FlowStatisticsTest.java
deleted file mode 100644 (file)
index 7fc171c..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-package test.mock;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Collections;
-import java.util.concurrent.ExecutionException;
-
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.statistics.manager.StatisticsManagerActivator;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityFlowStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-import test.mock.util.StatisticsManagerTest;
-
-import com.google.common.base.Optional;
-
-public class FlowStatisticsTest extends StatisticsManagerTest {
-    private final Object waitObject = new Object();
-
-//    @Test(timeout = 5000)
-    public void addedFlowOnDemandStatsTest() throws ExecutionException, InterruptedException, ReadFailedException {
-        final StatisticsManagerActivator activator = new StatisticsManagerActivator();
-        activator.onSessionInitiated(providerContext);
-
-        addFlowCapableNode(s1Key);
-
-        final Flow flow = getFlow();
-
-        final InstanceIdentifier<Flow> flowII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
-                .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(flow.getTableId()))
-                .child(Flow.class, flow.getKey());
-        final InstanceIdentifier<Table> tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
-                .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(flow.getTableId()));
-        final Table table = new TableBuilder().setKey(new TableKey(flow.getTableId())).setFlow(Collections.<Flow>emptyList()).build();
-
-        final WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.put(LogicalDatastoreType.CONFIGURATION, tableII, table);
-        writeTx.put(LogicalDatastoreType.CONFIGURATION, flowII, flow);
-        writeTx.put(LogicalDatastoreType.OPERATIONAL, tableII, table);
-        writeTx.put(LogicalDatastoreType.OPERATIONAL, flowII, flow);
-        assertCommit(writeTx.submit());
-
-        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                flowII.augmentation(FlowStatisticsData.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
-
-        synchronized (waitObject) {
-            waitObject.wait();
-        }
-
-        final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
-        final Optional<FlowStatisticsData> flowStatDataOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, flowII.augmentation(FlowStatisticsData.class))
-                .checkedGet();
-        assertTrue(flowStatDataOptional.isPresent());
-        assertEquals(COUNTER_64_TEST_VALUE, flowStatDataOptional.get().getFlowStatistics().getByteCount());
-
-    }
-
-//    @Test(timeout = 5000)
-    public void deletedFlowStatsRemovalTest() throws ExecutionException, InterruptedException, ReadFailedException {
-        final StatisticsManagerActivator activator = new StatisticsManagerActivator();
-        activator.onSessionInitiated(providerContext);
-
-        addFlowCapableNode(s1Key);
-
-        final Flow flow = getFlow();
-
-        final InstanceIdentifier<Flow> flowII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
-                .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(flow.getTableId()))
-                .child(Flow.class, flow.getKey());
-        final InstanceIdentifier<Table> tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
-                .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(flow.getTableId()));
-        final Table table = new TableBuilder().setKey(new TableKey(flow.getTableId())).setFlow(Collections.<Flow>emptyList()).build();
-
-        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.put(LogicalDatastoreType.CONFIGURATION, tableII, table);
-        writeTx.put(LogicalDatastoreType.CONFIGURATION, flowII, flow);
-        writeTx.put(LogicalDatastoreType.OPERATIONAL, tableII, table);
-        writeTx.put(LogicalDatastoreType.OPERATIONAL, flowII, flow);
-
-        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                flowII.augmentation(FlowStatisticsData.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
-
-        assertCommit(writeTx.submit());
-
-        synchronized (waitObject) {
-            waitObject.wait();
-        }
-
-        ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
-        Optional<Flow> flowStatDataOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, flowII).checkedGet();
-        assertTrue(flowStatDataOptional.isPresent());
-//        assertEquals(COUNTER_64_TEST_VALUE, flowStatDataOptional.get().getFlowStatistics().getByteCount());
-
-        writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.delete(LogicalDatastoreType.CONFIGURATION, flowII);
-        assertCommit(writeTx.submit());
-
-        readTx = getDataBroker().newReadOnlyTransaction();
-        flowStatDataOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, flowII).checkedGet();
-        assertFalse(flowStatDataOptional.isPresent());
-    }
-
-//    @Test(timeout = 23000)
-    public void getAllStatsWhenNodeIsConnectedTest() throws ExecutionException, InterruptedException, ReadFailedException {
-        final StatisticsManagerActivator activator = new StatisticsManagerActivator();
-        activator.onSessionInitiated(providerContext);
-
-        addFlowCapableNodeWithFeatures(s1Key, false, FlowFeatureCapabilityFlowStats.class);
-
-        final Flow flow = getFlow();
-
-        final InstanceIdentifier<Table> tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
-                .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(flow.getTableId()));
-
-        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                tableII.child(Flow.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
-
-        synchronized (waitObject) {
-            waitObject.wait();
-        }
-
-        final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
-        final Optional<Table> tableOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class)
-                .child(Node.class, s1Key).augmentation(FlowCapableNode.class)
-                .child(Table.class, new TableKey(flow.getTableId()))).checkedGet();
-        assertTrue(tableOptional.isPresent());
-        final FlowStatisticsData flowStats = tableOptional.get().getFlow().get(0).getAugmentation(FlowStatisticsData.class);
-        assertTrue(flowStats != null);
-        assertEquals(COUNTER_64_TEST_VALUE, flowStats.getFlowStatistics().getByteCount());
-    }
-
-    public class ChangeListener implements DataChangeListener {
-
-        @Override
-        public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
-            synchronized (waitObject) {
-                waitObject.notify();
-            }
-        }
-    }
-}
-
diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/GroupStatisticsTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/GroupStatisticsTest.java
deleted file mode 100644 (file)
index 7a61bf2..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-package test.mock;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.util.concurrent.ExecutionException;
-
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.statistics.manager.StatisticsManagerActivator;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityGroupStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupDescStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeatures;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.features.GroupFeatures;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-import test.mock.util.StatisticsManagerTest;
-
-import com.google.common.base.Optional;
-
-public class GroupStatisticsTest extends StatisticsManagerTest {
-    private final Object waitObject = new Object();
-
-//    @Test(timeout = 5000)
-    public void addedGroupOnDemandStatsTest() throws ExecutionException, InterruptedException, ReadFailedException {
-        final StatisticsManagerActivator activator = new StatisticsManagerActivator();
-        activator.onSessionInitiated(providerContext);
-
-        addFlowCapableNode(s1Key);
-
-        final Group group = getGroup();
-
-        final InstanceIdentifier<Group> groupII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
-                .augmentation(FlowCapableNode.class).child(Group.class, group.getKey());
-
-        final WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.put(LogicalDatastoreType.CONFIGURATION, groupII, group);
-        writeTx.put(LogicalDatastoreType.OPERATIONAL, groupII, group);
-        assertCommit(writeTx.submit());
-
-        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                groupII.augmentation(NodeGroupStatistics.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
-
-        synchronized (waitObject) {
-            waitObject.wait();
-        }
-
-        final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
-        final Optional<NodeGroupStatistics> groupOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, groupII.augmentation(NodeGroupStatistics.class)).checkedGet();
-        assertTrue(groupOptional.isPresent());
-        assertEquals(COUNTER_64_TEST_VALUE, groupOptional.get().getGroupStatistics().getByteCount());
-    }
-
-//    @Test(timeout = 5000)
-    public void deletedGroupStasRemovalTest() throws ExecutionException, InterruptedException, ReadFailedException {
-        final StatisticsManagerActivator activator = new StatisticsManagerActivator();
-        activator.onSessionInitiated(providerContext);
-
-        addFlowCapableNode(s1Key);
-
-        final Group group = getGroup();
-        final InstanceIdentifier<Group> groupII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
-                .augmentation(FlowCapableNode.class).child(Group.class, group.getKey());
-
-        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.put(LogicalDatastoreType.CONFIGURATION, groupII, group);
-        writeTx.put(LogicalDatastoreType.OPERATIONAL, groupII, group);
-        assertCommit(writeTx.submit());
-
-        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                groupII.augmentation(NodeGroupStatistics.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
-
-        synchronized (waitObject) {
-            waitObject.wait();
-        }
-
-        ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
-        Optional<NodeGroupStatistics> groupOptional = readTx.read(LogicalDatastoreType.OPERATIONAL,
-                groupII.augmentation(NodeGroupStatistics.class)).checkedGet();
-        assertTrue(groupOptional.isPresent());
-        assertEquals(COUNTER_64_TEST_VALUE, groupOptional.get().getGroupStatistics().getByteCount());
-
-        writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.delete(LogicalDatastoreType.CONFIGURATION, groupII);
-        assertCommit(writeTx.submit());
-
-        readTx = getDataBroker().newReadOnlyTransaction();
-        groupOptional = readTx.read(LogicalDatastoreType.OPERATIONAL,
-                groupII.augmentation(NodeGroupStatistics.class)).checkedGet();
-        assertFalse(groupOptional.isPresent());
-
-    }
-
-//    @Test(timeout = 23000)
-    public void getAllStatsFromConnectedNodeTest() throws ExecutionException, InterruptedException {
-        final StatisticsManagerActivator activator = new StatisticsManagerActivator();
-        activator.onSessionInitiated(providerContext);
-
-        addFlowCapableNodeWithFeatures(s1Key, false, FlowFeatureCapabilityGroupStats.class);
-
-        final InstanceIdentifier<Group> groupII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
-                .augmentation(FlowCapableNode.class).child(Group.class, getGroup().getKey());
-        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                groupII.augmentation(NodeGroupStatistics.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
-
-        synchronized (waitObject) {
-            waitObject.wait();
-        }
-
-        ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
-        final Optional<Group> optionalGroup = readTx.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class)
-                .child(Node.class, s1Key).augmentation(FlowCapableNode.class)
-                .child(Group.class, getGroup().getKey())).get();
-
-        assertTrue(optionalGroup.isPresent());
-        assertTrue(optionalGroup.get().getAugmentation(NodeGroupDescStats.class) != null);
-        final NodeGroupStatistics groupStats = optionalGroup.get().getAugmentation(NodeGroupStatistics.class);
-        assertTrue(groupStats != null);
-        assertEquals(COUNTER_64_TEST_VALUE, groupStats.getGroupStatistics().getByteCount());
-
-        readTx = getDataBroker().newReadOnlyTransaction();
-        final Optional<GroupFeatures> optionalGroupFeatures = readTx.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class)
-                .child(Node.class, s1Key).augmentation(NodeGroupFeatures.class).child(GroupFeatures.class)).get();
-        assertTrue(optionalGroupFeatures.isPresent());
-        assertEquals(1, optionalGroupFeatures.get().getMaxGroups().size());
-        assertEquals(MAX_GROUPS_TEST_VALUE, optionalGroupFeatures.get().getMaxGroups().get(0));
-    }
-
-    private class ChangeListener implements DataChangeListener {
-
-        @Override
-        public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
-            synchronized (waitObject) {
-                waitObject.notify();
-            }
-        }
-    }
-}
-
diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/MeterStatisticsTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/MeterStatisticsTest.java
deleted file mode 100644 (file)
index a0f360c..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-package test.mock;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.util.concurrent.ExecutionException;
-
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.statistics.manager.StatisticsManagerActivator;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterConfigStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeatures;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterFeatures;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-import test.mock.util.StatisticsManagerTest;
-
-import com.google.common.base.Optional;
-
-public class MeterStatisticsTest extends StatisticsManagerTest {
-    private final Object waitObject = new Object();
-
-//    @Test(timeout = 5000)
-    public void addedMeterOnDemandStatsTest() throws ExecutionException, InterruptedException, ReadFailedException {
-        final StatisticsManagerActivator activator = new StatisticsManagerActivator();
-        activator.onSessionInitiated(providerContext);
-
-        addFlowCapableNode(s1Key);
-
-        final Meter meter = getMeter();
-        final InstanceIdentifier<Meter> meterII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
-                .augmentation(FlowCapableNode.class).child(Meter.class, meter.getKey());
-
-        final WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.put(LogicalDatastoreType.CONFIGURATION, meterII, meter);
-        writeTx.put(LogicalDatastoreType.OPERATIONAL, meterII, meter);
-        assertCommit(writeTx.submit());
-
-        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                meterII.augmentation(NodeMeterStatistics.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
-
-        synchronized (waitObject) {
-            waitObject.wait();
-        }
-
-        final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
-        final Optional<NodeMeterStatistics> meterStatsOptional = readTx.read(LogicalDatastoreType.OPERATIONAL,
-                meterII.augmentation(NodeMeterStatistics.class)).checkedGet();
-        assertTrue(meterStatsOptional.isPresent());
-        assertEquals(COUNTER_64_TEST_VALUE, meterStatsOptional.get().getMeterStatistics().getByteInCount());
-        assertEquals(COUNTER_64_TEST_VALUE, meterStatsOptional.get().getMeterStatistics().getPacketInCount());
-    }
-
-//    @Test(timeout = 5000)
-    public void deletedMeterStatsRemovalTest() throws ExecutionException, InterruptedException, ReadFailedException {
-        final StatisticsManagerActivator activator = new StatisticsManagerActivator();
-        activator.onSessionInitiated(providerContext);
-
-        addFlowCapableNode(s1Key);
-
-        final Meter meter = getMeter();
-        final InstanceIdentifier<Meter> meterII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
-                .augmentation(FlowCapableNode.class).child(Meter.class, meter.getKey());
-
-        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.put(LogicalDatastoreType.CONFIGURATION, meterII, meter);
-        writeTx.put(LogicalDatastoreType.OPERATIONAL, meterII, meter);
-        assertCommit(writeTx.submit());
-
-        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                meterII.augmentation(NodeMeterStatistics.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
-
-        synchronized (waitObject) {
-            waitObject.wait();
-        }
-
-        ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
-        final Optional<NodeMeterStatistics> meterStatsOptional = readTx.read(LogicalDatastoreType.OPERATIONAL,
-                meterII.augmentation(NodeMeterStatistics.class)).checkedGet();
-        assertTrue(meterStatsOptional.isPresent());
-        assertEquals(COUNTER_64_TEST_VALUE, meterStatsOptional.get().getMeterStatistics().getByteInCount());
-        assertEquals(COUNTER_64_TEST_VALUE, meterStatsOptional.get().getMeterStatistics().getPacketInCount());
-
-        writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.delete(LogicalDatastoreType.CONFIGURATION, meterII);
-        assertCommit(writeTx.submit());
-
-        readTx = getDataBroker().newReadOnlyTransaction();
-        final Optional<Meter> meterOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, meterII).checkedGet();
-        assertFalse(meterOptional.isPresent());
-    }
-
-//    @Test(timeout = 23000)
-    public void getAllStatsFromConnectedNodeTest() throws ExecutionException, InterruptedException {
-        final StatisticsManagerActivator activator = new StatisticsManagerActivator();
-        activator.onSessionInitiated(providerContext);
-
-        addFlowCapableNodeWithFeatures(s1Key, true);
-
-        final InstanceIdentifier<Meter> meterII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
-                .augmentation(FlowCapableNode.class).child(Meter.class, getMeter().getKey());
-        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                meterII.augmentation(NodeMeterStatistics.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
-
-        synchronized (waitObject) {
-            waitObject.wait();
-        }
-
-        ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
-        final Optional<Meter> optionalMeter = readTx.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class)
-                .child(Node.class, s1Key).augmentation(FlowCapableNode.class)
-                .child(Meter.class, getMeter().getKey())).get();
-
-        assertTrue(optionalMeter.isPresent());
-        assertTrue(optionalMeter.get().getAugmentation(NodeMeterConfigStats.class) != null);
-        final NodeMeterStatistics meterStats = optionalMeter.get().getAugmentation(NodeMeterStatistics.class);
-        assertTrue(meterStats != null);
-        assertEquals(COUNTER_64_TEST_VALUE, meterStats.getMeterStatistics().getByteInCount());
-        assertEquals(COUNTER_64_TEST_VALUE, meterStats.getMeterStatistics().getPacketInCount());
-
-        readTx = getDataBroker().newReadOnlyTransaction();
-        final Optional<MeterFeatures> optionalMeterFeautures = readTx.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class)
-                .child(Node.class, s1Key).augmentation(NodeMeterFeatures.class).child(MeterFeatures.class)).get();
-        assertTrue(optionalMeterFeautures.isPresent());
-        assertEquals(COUNTER_32_TEST_VALUE, optionalMeterFeautures.get().getMaxMeter());
-    }
-
-    private class ChangeListener implements DataChangeListener {
-
-        @Override
-        public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
-            synchronized (waitObject) {
-                waitObject.notify();
-            }
-        }
-    }
-}
-
index 18bd2d42ef404d2f3c1c5d047760c249afa7e2f4..79eb23608906d58e01f9fefc5b2235f07e56613f 100644 (file)
@@ -1,48 +1,43 @@
 package test.mock;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.util.concurrent.ExecutionException;
-
-import org.opendaylight.controller.md.statistics.manager.StatisticsManagerActivator;
-import org.opendaylight.controller.md.statistics.manager.StatisticsManagerProvider;
+import org.junit.Test;
+import org.opendaylight.controller.md.statistics.manager.StatisticsManager;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
 import test.mock.util.StatisticsManagerTest;
 
+import java.util.concurrent.ExecutionException;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 public class NodeRegistrationTest extends StatisticsManagerTest {
 
-//    @Test
+    @Test
     public void nodeRegistrationTest() throws ExecutionException, InterruptedException {
-        final StatisticsManagerActivator activator = new StatisticsManagerActivator();
-        final StatisticsManagerProvider statisticsManagerProvider = new StatisticsManagerProvider(activator);
-        activator.onSessionInitiated(providerContext);
+        StatisticsManager statisticsManager = setupStatisticsManager();
 
         addFlowCapableNode(s1Key);
-        Thread.sleep(1000);
+        Thread.sleep(2000);
         final InstanceIdentifier<Node> nodeII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key);
 
-        assertTrue(statisticsManagerProvider.getStatisticsManager().isProvidedFlowNodeActive(nodeII));
+        assertTrue(statisticsManager.isProvidedFlowNodeActive(nodeII));
     }
 
-//    @Test
+    @Test
     public void nodeUnregistrationTest() throws ExecutionException, InterruptedException {
-        final StatisticsManagerActivator activator = new StatisticsManagerActivator();
-        final StatisticsManagerProvider statisticsManagerProvider = new StatisticsManagerProvider(activator);
-        activator.onSessionInitiated(providerContext);
+        StatisticsManager statisticsManager = setupStatisticsManager();
 
         addFlowCapableNode(s1Key);
-        Thread.sleep(1000);
+        Thread.sleep(2000);
         final InstanceIdentifier<Node> nodeII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key);
 
-        assertTrue(statisticsManagerProvider.getStatisticsManager().isProvidedFlowNodeActive(nodeII));
+        assertTrue(statisticsManager.isProvidedFlowNodeActive(nodeII));
 
         removeNode(s1Key);
-        Thread.sleep(1000);
-        assertFalse(statisticsManagerProvider.getStatisticsManager().isProvidedFlowNodeActive(nodeII));
+        Thread.sleep(2000);
+        assertFalse(statisticsManager.isProvidedFlowNodeActive(nodeII));
     }
 }
 
diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/PortStatisticsTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/PortStatisticsTest.java
deleted file mode 100644 (file)
index 9f193b0..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-package test.mock;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.util.concurrent.ExecutionException;
-
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.statistics.manager.StatisticsManagerActivator;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityPortStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-import test.mock.util.StatisticsManagerTest;
-
-import com.google.common.base.Optional;
-
-public class PortStatisticsTest extends StatisticsManagerTest {
-    private final Object waitObject = new Object();
-
-//    @Test(timeout = 23000)
-    public void getPortStatisticsTest() throws ExecutionException, InterruptedException, ReadFailedException {
-        final StatisticsManagerActivator activator = new StatisticsManagerActivator();
-        activator.onSessionInitiated(providerContext);
-
-        addFlowCapableNodeWithFeatures(s1Key, false, FlowFeatureCapabilityPortStats.class);
-
-        final InstanceIdentifier<NodeConnector> nodeConnectorII = InstanceIdentifier.create(Nodes.class)
-                .child(Node.class, s1Key).child(NodeConnector.class, new NodeConnectorKey(getNodeConnectorId()));
-
-
-        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                nodeConnectorII.augmentation(FlowCapableNodeConnectorStatisticsData.class),
-                                                new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
-
-        synchronized (waitObject) {
-            waitObject.wait();
-        }
-
-        final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
-        final Optional<FlowCapableNodeConnectorStatisticsData> flowCapableNodeConnectorStatisticsDataOptional =
-                readTx.read(LogicalDatastoreType.OPERATIONAL,
-                        nodeConnectorII.augmentation(FlowCapableNodeConnectorStatisticsData.class)).checkedGet();
-        assertTrue(flowCapableNodeConnectorStatisticsDataOptional.isPresent());
-        assertEquals(BIG_INTEGER_TEST_VALUE,
-                flowCapableNodeConnectorStatisticsDataOptional.get().getFlowCapableNodeConnectorStatistics()
-                        .getReceiveDrops());
-        assertEquals(BIG_INTEGER_TEST_VALUE,
-                flowCapableNodeConnectorStatisticsDataOptional.get().getFlowCapableNodeConnectorStatistics()
-                        .getCollisionCount());
-    }
-
-    private class ChangeListener implements DataChangeListener {
-
-        @Override
-        public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
-            synchronized (waitObject) {
-                waitObject.notify();
-            }
-        }
-    }
-}
-
diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/QueueStatisticsTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/QueueStatisticsTest.java
deleted file mode 100644 (file)
index bb9bd21..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-package test.mock;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Collections;
-import java.util.concurrent.ExecutionException;
-
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.statistics.manager.StatisticsManagerActivator;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityQueueStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.port.mod.port.Port;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsData;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-import test.mock.util.StatisticsManagerTest;
-
-import com.google.common.base.Optional;
-
-
-public class QueueStatisticsTest extends StatisticsManagerTest {
-    private final Object waitObject = new Object();
-
-//    @Test(timeout = 5000)
-    public void addedQueueOnDemandStatsTest() throws ExecutionException, InterruptedException, ReadFailedException {
-        final StatisticsManagerActivator activator = new StatisticsManagerActivator();
-        activator.onSessionInitiated(providerContext);
-
-        addFlowCapableNode(s1Key);
-
-        final Port port = getPort();
-
-        final NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder();
-        final FlowCapableNodeConnectorBuilder fcncBuilder = new FlowCapableNodeConnectorBuilder();
-        fcncBuilder.setConfiguration(port.getConfiguration());
-        fcncBuilder.setPortNumber(port.getPortNumber());
-        fcncBuilder.setQueue(Collections.<Queue>emptyList());
-        ncBuilder.setKey(new NodeConnectorKey(new NodeConnectorId("connector.1")));
-        ncBuilder.addAugmentation(FlowCapableNodeConnector.class, fcncBuilder.build());
-
-
-        final Queue queue = getQueue();
-        final InstanceIdentifier<Queue> queueII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
-                .child(NodeConnector.class, ncBuilder.getKey()).augmentation(FlowCapableNodeConnector.class)
-                .child(Queue.class, queue.getKey());
-        final InstanceIdentifier<NodeConnector> nodeConnectorII = InstanceIdentifier.create(Nodes.class)
-                .child(Node.class, s1Key).child(NodeConnector.class, ncBuilder.getKey());
-
-        final WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.put(LogicalDatastoreType.CONFIGURATION, nodeConnectorII, ncBuilder.build());
-        writeTx.put(LogicalDatastoreType.CONFIGURATION, queueII, queue);
-        writeTx.put(LogicalDatastoreType.OPERATIONAL, nodeConnectorII, ncBuilder.build());
-        writeTx.put(LogicalDatastoreType.OPERATIONAL, queueII, queue);
-        assertCommit(writeTx.submit());
-
-        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                queueII.augmentation(FlowCapableNodeConnectorQueueStatisticsData.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
-
-        synchronized (waitObject) {
-            waitObject.wait();
-        }
-
-        final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
-        final Optional<FlowCapableNodeConnectorQueueStatisticsData> queueStatsOptional = readTx.read(LogicalDatastoreType.OPERATIONAL,
-                queueII.augmentation(FlowCapableNodeConnectorQueueStatisticsData.class)).checkedGet();
-        assertTrue(queueStatsOptional.isPresent());
-        assertEquals(COUNTER_64_TEST_VALUE,
-                queueStatsOptional.get().getFlowCapableNodeConnectorQueueStatistics().getTransmittedBytes());
-    }
-
-//    @Test(timeout = 5000)
-    public void deletedQueueStatsRemovalTest() throws ExecutionException, InterruptedException, ReadFailedException {
-        final StatisticsManagerActivator activator = new StatisticsManagerActivator();
-        activator.onSessionInitiated(providerContext);
-
-        addFlowCapableNode(s1Key);
-
-        final Port port = getPort();
-
-        final NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder();
-        final FlowCapableNodeConnectorBuilder fcncBuilder = new FlowCapableNodeConnectorBuilder();
-        fcncBuilder.setConfiguration(port.getConfiguration());
-        fcncBuilder.setPortNumber(port.getPortNumber());
-        fcncBuilder.setQueue(Collections.<Queue>emptyList());
-        ncBuilder.setKey(new NodeConnectorKey(new NodeConnectorId("connector.1")));
-        ncBuilder.addAugmentation(FlowCapableNodeConnector.class, fcncBuilder.build());
-
-
-        final Queue queue = getQueue();
-        final InstanceIdentifier<Queue> queueII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
-                .child(NodeConnector.class, ncBuilder.getKey()).augmentation(FlowCapableNodeConnector.class)
-                .child(Queue.class, queue.getKey());
-        final InstanceIdentifier<NodeConnector> nodeConnectorII = InstanceIdentifier.create(Nodes.class)
-                .child(Node.class, s1Key).child(NodeConnector.class, ncBuilder.getKey());
-
-        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.put(LogicalDatastoreType.CONFIGURATION, nodeConnectorII, ncBuilder.build());
-        writeTx.put(LogicalDatastoreType.CONFIGURATION, queueII, queue);
-        writeTx.put(LogicalDatastoreType.OPERATIONAL, nodeConnectorII, ncBuilder.build());
-        writeTx.put(LogicalDatastoreType.OPERATIONAL, queueII, queue);
-        assertCommit(writeTx.submit());
-
-        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                queueII.augmentation(FlowCapableNodeConnectorQueueStatisticsData.class),
-                                        new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
-
-        synchronized (waitObject) {
-            waitObject.wait();
-        }
-
-        ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
-        Optional<FlowCapableNodeConnectorQueueStatisticsData> queueStatsOptional = readTx.read(LogicalDatastoreType.OPERATIONAL,
-                queueII.augmentation(FlowCapableNodeConnectorQueueStatisticsData.class)).checkedGet();
-        assertTrue(queueStatsOptional.isPresent());
-        assertEquals(COUNTER_64_TEST_VALUE,
-                queueStatsOptional.get().getFlowCapableNodeConnectorQueueStatistics().getTransmittedBytes());
-
-        writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.delete(LogicalDatastoreType.CONFIGURATION, queueII);
-        assertCommit(writeTx.submit());
-
-        readTx = getDataBroker().newReadOnlyTransaction();
-        queueStatsOptional = readTx.read(LogicalDatastoreType.OPERATIONAL,
-                queueII.augmentation(FlowCapableNodeConnectorQueueStatisticsData.class)).checkedGet();
-        assertFalse(queueStatsOptional.isPresent());
-    }
-
-//    @Test(timeout = 23000)
-    public void getAllStatsFromConnectedNodeTest() throws ExecutionException, InterruptedException, ReadFailedException {
-        final StatisticsManagerActivator activator = new StatisticsManagerActivator();
-        activator.onSessionInitiated(providerContext);
-
-        addFlowCapableNodeWithFeatures(s1Key, false, FlowFeatureCapabilityQueueStats.class);
-
-        final NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder();
-        final FlowCapableNodeConnectorBuilder fcncBuilder = new FlowCapableNodeConnectorBuilder();
-        ncBuilder.setKey(new NodeConnectorKey(getNodeConnectorId()));
-        ncBuilder.addAugmentation(FlowCapableNodeConnector.class, fcncBuilder.build());
-
-        final InstanceIdentifier<NodeConnector> nodeConnectorII = InstanceIdentifier.create(Nodes.class)
-                .child(Node.class, s1Key)
-                .child(NodeConnector.class, ncBuilder.getKey());
-
-        final WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.put(LogicalDatastoreType.OPERATIONAL, nodeConnectorII, ncBuilder.build());
-        final InstanceIdentifier<Queue> queueII = nodeConnectorII.augmentation(FlowCapableNodeConnector.class)
-                .child(Queue.class, getQueue().getKey());
-        final QueueBuilder qBuilder = new QueueBuilder(getQueue());
-        writeTx.put(LogicalDatastoreType.OPERATIONAL, queueII, qBuilder.build());
-        assertCommit(writeTx.submit());
-
-        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                queueII.augmentation(FlowCapableNodeConnectorQueueStatisticsData.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
-
-        synchronized (waitObject) {
-            waitObject.wait();
-        }
-
-        final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
-        final Optional<Queue> queueOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, queueII).checkedGet();
-        assertTrue(queueOptional.isPresent());
-        final FlowCapableNodeConnectorQueueStatisticsData queueStats =
-                queueOptional.get().getAugmentation(FlowCapableNodeConnectorQueueStatisticsData.class);
-        assertTrue(queueStats != null);
-        assertEquals(COUNTER_64_TEST_VALUE,
-                queueStats.getFlowCapableNodeConnectorQueueStatistics().getTransmittedBytes());
-    }
-
-    private class ChangeListener implements DataChangeListener {
-
-        @Override
-        public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
-            synchronized (waitObject) {
-                waitObject.notify();
-            }
-        }
-    }
-}
-
diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/StatCollectorTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/StatCollectorTest.java
new file mode 100644 (file)
index 0000000..48a993e
--- /dev/null
@@ -0,0 +1,298 @@
+package test.mock;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.base.Optional;
+import java.util.concurrent.ExecutionException;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityFlowStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityGroupStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityPortStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityQueueStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityTableStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupDescStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.features.GroupFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterConfigStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import test.mock.util.StatisticsManagerTest;
+
+public class StatCollectorTest extends StatisticsManagerTest {
+    private final Object waitObject = new Object();
+
+    @Test(timeout = 200000)
+    public void getAllFlowStatsTest() throws ExecutionException, InterruptedException, ReadFailedException {
+        setupStatisticsManager();
+
+        addFlowCapableNodeWithFeatures(s1Key, false, FlowFeatureCapabilityFlowStats.class);
+
+        final Flow flow = getFlow();
+
+        final InstanceIdentifier<Table> tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(flow.getTableId()));
+
+        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                tableII.child(Flow.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
+
+        synchronized (waitObject) {
+            waitObject.wait();
+        }
+
+        final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
+        final Optional<Table> tableOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class)
+                .child(Node.class, s1Key).augmentation(FlowCapableNode.class)
+                .child(Table.class, new TableKey(flow.getTableId()))).checkedGet();
+        assertTrue(tableOptional.isPresent());
+        final FlowStatisticsData flowStats = tableOptional.get().getFlow().get(0).getAugmentation(FlowStatisticsData.class);
+        assertTrue(flowStats != null);
+        assertEquals(COUNTER_64_TEST_VALUE, flowStats.getFlowStatistics().getByteCount());
+    }
+
+    @Test(timeout = 200000)
+    public void getAllGroupStatsFeatureNotAdvertisedTest() throws ExecutionException, InterruptedException {
+        setupStatisticsManager();
+
+        addFlowCapableNodeWithFeatures(s1Key, true);
+
+        final InstanceIdentifier<Group> groupII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Group.class, getGroup().getKey());
+        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                groupII.augmentation(NodeGroupStatistics.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
+
+        synchronized (waitObject) {
+            waitObject.wait();
+        }
+
+        ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
+        final Optional<Group> optionalGroup = readTx.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class)
+                .child(Node.class, s1Key).augmentation(FlowCapableNode.class)
+                .child(Group.class, getGroup().getKey())).get();
+
+        assertTrue(optionalGroup.isPresent());
+        assertTrue(optionalGroup.get().getAugmentation(NodeGroupDescStats.class) != null);
+        final NodeGroupStatistics groupStats = optionalGroup.get().getAugmentation(NodeGroupStatistics.class);
+        assertTrue(groupStats != null);
+        assertEquals(COUNTER_64_TEST_VALUE, groupStats.getGroupStatistics().getByteCount());
+
+        readTx = getDataBroker().newReadOnlyTransaction();
+        final Optional<GroupFeatures> optionalGroupFeatures = readTx.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class)
+                .child(Node.class, s1Key).augmentation(NodeGroupFeatures.class).child(GroupFeatures.class)).get();
+        assertTrue(optionalGroupFeatures.isPresent());
+        assertEquals(1, optionalGroupFeatures.get().getMaxGroups().size());
+        assertEquals(MAX_GROUPS_TEST_VALUE, optionalGroupFeatures.get().getMaxGroups().get(0));
+    }
+
+    @Test(timeout = 200000)
+    public void getAllGroupStatsFeatureAdvertisedTest() throws ExecutionException, InterruptedException {
+        setupStatisticsManager();
+
+        addFlowCapableNodeWithFeatures(s1Key, false, FlowFeatureCapabilityGroupStats.class);
+
+        final InstanceIdentifier<Group> groupII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Group.class, getGroup().getKey());
+        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                groupII.augmentation(NodeGroupStatistics.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
+
+        synchronized (waitObject) {
+            waitObject.wait();
+        }
+
+        ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
+        final Optional<Group> optionalGroup = readTx.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class)
+                .child(Node.class, s1Key).augmentation(FlowCapableNode.class)
+                .child(Group.class, getGroup().getKey())).get();
+
+        assertTrue(optionalGroup.isPresent());
+        assertTrue(optionalGroup.get().getAugmentation(NodeGroupDescStats.class) != null);
+        final NodeGroupStatistics groupStats = optionalGroup.get().getAugmentation(NodeGroupStatistics.class);
+        assertTrue(groupStats != null);
+        assertEquals(COUNTER_64_TEST_VALUE, groupStats.getGroupStatistics().getByteCount());
+
+        readTx = getDataBroker().newReadOnlyTransaction();
+        final Optional<GroupFeatures> optionalGroupFeatures = readTx.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class)
+                .child(Node.class, s1Key).augmentation(NodeGroupFeatures.class).child(GroupFeatures.class)).get();
+        assertTrue(optionalGroupFeatures.isPresent());
+        assertEquals(1, optionalGroupFeatures.get().getMaxGroups().size());
+        assertEquals(MAX_GROUPS_TEST_VALUE, optionalGroupFeatures.get().getMaxGroups().get(0));
+    }
+
+    @Test(timeout = 200000)
+    public void getAllMeterStatsTest() throws ExecutionException, InterruptedException {
+        setupStatisticsManager();
+
+        addFlowCapableNodeWithFeatures(s1Key, true);
+
+        final InstanceIdentifier<Meter> meterII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Meter.class, getMeter().getKey());
+        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                meterII.augmentation(NodeMeterStatistics.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
+
+        synchronized (waitObject) {
+            waitObject.wait();
+        }
+
+        ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
+        final Optional<Meter> optionalMeter = readTx.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class)
+                .child(Node.class, s1Key).augmentation(FlowCapableNode.class)
+                .child(Meter.class, getMeter().getKey())).get();
+
+        assertTrue(optionalMeter.isPresent());
+        assertTrue(optionalMeter.get().getAugmentation(NodeMeterConfigStats.class) != null);
+        final NodeMeterStatistics meterStats = optionalMeter.get().getAugmentation(NodeMeterStatistics.class);
+        assertTrue(meterStats != null);
+        assertEquals(COUNTER_64_TEST_VALUE, meterStats.getMeterStatistics().getByteInCount());
+        assertEquals(COUNTER_64_TEST_VALUE, meterStats.getMeterStatistics().getPacketInCount());
+
+        readTx = getDataBroker().newReadOnlyTransaction();
+        final Optional<MeterFeatures> optionalMeterFeautures = readTx.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class)
+                .child(Node.class, s1Key).augmentation(NodeMeterFeatures.class).child(MeterFeatures.class)).get();
+        assertTrue(optionalMeterFeautures.isPresent());
+        assertEquals(COUNTER_32_TEST_VALUE, optionalMeterFeautures.get().getMaxMeter());
+    }
+
+    @Test(timeout = 200000)
+    public void getAllQueueStatsTest() throws ExecutionException, InterruptedException, ReadFailedException {
+        setupStatisticsManager();
+
+        addFlowCapableNodeWithFeatures(s1Key, false, FlowFeatureCapabilityQueueStats.class);
+
+        final NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder();
+        final FlowCapableNodeConnectorBuilder fcncBuilder = new FlowCapableNodeConnectorBuilder();
+        ncBuilder.setKey(new NodeConnectorKey(getNodeConnectorId()));
+        ncBuilder.addAugmentation(FlowCapableNodeConnector.class, fcncBuilder.build());
+
+        final InstanceIdentifier<NodeConnector> nodeConnectorII = InstanceIdentifier.create(Nodes.class)
+                .child(Node.class, s1Key)
+                .child(NodeConnector.class, ncBuilder.getKey());
+
+        final WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.OPERATIONAL, nodeConnectorII, ncBuilder.build());
+        final InstanceIdentifier<Queue> queueII = nodeConnectorII.augmentation(FlowCapableNodeConnector.class)
+                .child(Queue.class, getQueue().getKey());
+        final QueueBuilder qBuilder = new QueueBuilder(getQueue());
+        writeTx.put(LogicalDatastoreType.OPERATIONAL, queueII, qBuilder.build());
+        assertCommit(writeTx.submit());
+
+        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                queueII.augmentation(FlowCapableNodeConnectorQueueStatisticsData.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
+
+        synchronized (waitObject) {
+            waitObject.wait();
+        }
+
+        final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
+        final Optional<Queue> queueOptional = readTx.read(LogicalDatastoreType.OPERATIONAL, queueII).checkedGet();
+        assertTrue(queueOptional.isPresent());
+        final FlowCapableNodeConnectorQueueStatisticsData queueStats =
+                queueOptional.get().getAugmentation(FlowCapableNodeConnectorQueueStatisticsData.class);
+        assertTrue(queueStats != null);
+        assertEquals(COUNTER_64_TEST_VALUE,
+                queueStats.getFlowCapableNodeConnectorQueueStatistics().getTransmittedBytes());
+    }
+
+    @Test(timeout = 200000)
+    public void getAllPortStatsTest() throws ExecutionException, InterruptedException, ReadFailedException {
+        setupStatisticsManager();
+
+        addFlowCapableNodeWithFeatures(s1Key, false, FlowFeatureCapabilityPortStats.class);
+
+        final InstanceIdentifier<NodeConnector> nodeConnectorII = InstanceIdentifier.create(Nodes.class)
+                .child(Node.class, s1Key).child(NodeConnector.class, new NodeConnectorKey(getNodeConnectorId()));
+
+        NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder();
+        ncBuilder.setKey(new NodeConnectorKey(getNodeConnectorId()));
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.OPERATIONAL, nodeConnectorII, ncBuilder.build());
+        assertCommit(writeTx.submit());
+
+        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                nodeConnectorII.augmentation(FlowCapableNodeConnectorStatisticsData.class),
+                new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
+
+        synchronized (waitObject) {
+            waitObject.wait();
+        }
+
+        final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
+        final Optional<FlowCapableNodeConnectorStatisticsData> flowCapableNodeConnectorStatisticsDataOptional =
+                readTx.read(LogicalDatastoreType.OPERATIONAL,
+                        nodeConnectorII.augmentation(FlowCapableNodeConnectorStatisticsData.class)).checkedGet();
+        assertTrue(flowCapableNodeConnectorStatisticsDataOptional.isPresent());
+        assertEquals(BIG_INTEGER_TEST_VALUE,
+                flowCapableNodeConnectorStatisticsDataOptional.get().getFlowCapableNodeConnectorStatistics()
+                        .getReceiveDrops());
+        assertEquals(BIG_INTEGER_TEST_VALUE,
+                flowCapableNodeConnectorStatisticsDataOptional.get().getFlowCapableNodeConnectorStatistics()
+                        .getCollisionCount());
+    }
+
+    @Test(timeout = 200000)
+    public void getAllTableStatsTest() throws ExecutionException, InterruptedException, ReadFailedException {
+        setupStatisticsManager();
+
+        addFlowCapableNodeWithFeatures(s1Key, false, FlowFeatureCapabilityTableStats.class);
+
+        final TableId tableId = getTableId();
+        final InstanceIdentifier<Table> tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId.getValue()));
+
+        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                tableII.augmentation(FlowTableStatisticsData.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
+
+        synchronized (waitObject) {
+            waitObject.wait();
+        }
+
+        final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
+        final Optional<FlowTableStatisticsData> flowTableStatisticsDataOptional = readTx.read(
+                LogicalDatastoreType.OPERATIONAL, tableII.augmentation(FlowTableStatisticsData.class)).checkedGet();
+        assertTrue(flowTableStatisticsDataOptional.isPresent());
+        assertEquals(COUNTER_32_TEST_VALUE,
+                flowTableStatisticsDataOptional.get().getFlowTableStatistics().getActiveFlows());
+        assertEquals(COUNTER_64_TEST_VALUE,
+                flowTableStatisticsDataOptional.get().getFlowTableStatistics().getPacketsLookedUp());
+    }
+
+    public class ChangeListener implements DataChangeListener {
+
+        @Override
+        public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+            synchronized (waitObject) {
+                waitObject.notify();
+            }
+        }
+    }
+}
diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/TableStatisticsTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/TableStatisticsTest.java
deleted file mode 100644 (file)
index f0c0fed..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-package test.mock;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.util.concurrent.ExecutionException;
-
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.statistics.manager.StatisticsManagerActivator;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityTableStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-import test.mock.util.StatisticsManagerTest;
-
-import com.google.common.base.Optional;
-
-public class TableStatisticsTest extends StatisticsManagerTest {
-    private final Object waitObject = new Object();
-
-//    @Test(timeout = 23000)
-    public void getTableStatisticsTest() throws ExecutionException, InterruptedException, ReadFailedException {
-        final StatisticsManagerActivator activator = new StatisticsManagerActivator();
-        activator.onSessionInitiated(providerContext);
-
-        addFlowCapableNodeWithFeatures(s1Key, false, FlowFeatureCapabilityTableStats.class);
-
-        final TableId tableId = getTableId();
-        final InstanceIdentifier<Table> tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
-                .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId.getValue()));
-
-        getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                tableII.augmentation(FlowTableStatisticsData.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
-
-        synchronized (waitObject) {
-            waitObject.wait();
-        }
-
-        final ReadOnlyTransaction readTx = getDataBroker().newReadOnlyTransaction();
-        final Optional<FlowTableStatisticsData> flowTableStatisticsDataOptional = readTx.read(
-                LogicalDatastoreType.OPERATIONAL, tableII.augmentation(FlowTableStatisticsData.class)).checkedGet();
-        assertTrue(flowTableStatisticsDataOptional.isPresent());
-        assertEquals(COUNTER_32_TEST_VALUE,
-                flowTableStatisticsDataOptional.get().getFlowTableStatistics().getActiveFlows());
-        assertEquals(COUNTER_64_TEST_VALUE,
-                flowTableStatisticsDataOptional.get().getFlowTableStatistics().getPacketsLookedUp());
-    }
-
-    private class ChangeListener implements DataChangeListener {
-
-        @Override
-        public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
-            synchronized (waitObject) {
-                waitObject.notify();
-            }
-        }
-    }
-}
-
index 2628bb9f41210ecd30cd375a59981fd43bf0e67b..f483881975ec5dcdd13ca156fa456b2fcf008afe 100644 (file)
@@ -1,6 +1,10 @@
 package test.mock.util;
 
 import com.google.common.util.concurrent.Futures;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsUpdateBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdateBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsInput;
@@ -27,15 +31,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Future;
-import java.util.concurrent.atomic.AtomicLong;
-
 public class OpendaylightFlowStatisticsServiceMock implements OpendaylightFlowStatisticsService {
     NotificationProviderServiceHelper notifService;
-    AtomicLong transNum = new AtomicLong();
 
     public OpendaylightFlowStatisticsServiceMock(NotificationProviderServiceHelper notifService) {
         this.notifService = notifService;
@@ -44,7 +41,7 @@ public class OpendaylightFlowStatisticsServiceMock implements OpendaylightFlowSt
     @Override
     public Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput>> getAggregateFlowStatisticsFromFlowTableForAllFlows(GetAggregateFlowStatisticsFromFlowTableForAllFlowsInput input) {
         GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutputBuilder builder = new GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build());
     }
@@ -52,7 +49,7 @@ public class OpendaylightFlowStatisticsServiceMock implements OpendaylightFlowSt
     @Override
     public Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>> getAggregateFlowStatisticsFromFlowTableForGivenMatch(GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput input) {
         GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder builder = new GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         AggregateFlowStatisticsUpdateBuilder afsuBuilder = new AggregateFlowStatisticsUpdateBuilder();
         afsuBuilder.setMoreReplies(false);
@@ -66,7 +63,7 @@ public class OpendaylightFlowStatisticsServiceMock implements OpendaylightFlowSt
     @Override
     public Future<RpcResult<GetAllFlowStatisticsFromFlowTableOutput>> getAllFlowStatisticsFromFlowTable(GetAllFlowStatisticsFromFlowTableInput input) {
         GetAllFlowStatisticsFromFlowTableOutputBuilder builder = new GetAllFlowStatisticsFromFlowTableOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build());
     }
@@ -74,7 +71,7 @@ public class OpendaylightFlowStatisticsServiceMock implements OpendaylightFlowSt
     @Override
     public Future<RpcResult<GetAllFlowsStatisticsFromAllFlowTablesOutput>> getAllFlowsStatisticsFromAllFlowTables(GetAllFlowsStatisticsFromAllFlowTablesInput input) {
         GetAllFlowsStatisticsFromAllFlowTablesOutputBuilder builder = new GetAllFlowsStatisticsFromAllFlowTablesOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         List<FlowAndStatisticsMapList> flowAndStatisticsMapLists = new ArrayList<>();
         FlowsStatisticsUpdateBuilder flowsStatisticsUpdateBuilder = new FlowsStatisticsUpdateBuilder();
@@ -95,7 +92,7 @@ public class OpendaylightFlowStatisticsServiceMock implements OpendaylightFlowSt
     @Override
     public Future<RpcResult<GetFlowStatisticsFromFlowTableOutput>> getFlowStatisticsFromFlowTable(GetFlowStatisticsFromFlowTableInput input) {
         GetFlowStatisticsFromFlowTableOutputBuilder builder = new GetFlowStatisticsFromFlowTableOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         List<FlowAndStatisticsMapList> flowAndStatisticsMapLists = new ArrayList<>();
         FlowsStatisticsUpdateBuilder flowsStatisticsUpdateBuilder = new FlowsStatisticsUpdateBuilder();
index 42be70892c6157b0b1f2a30a2db3d73c53fd35b1..ea9f40390f889277835c037ca237ad438c24598f 100644 (file)
@@ -1,6 +1,10 @@
 package test.mock.util;
 
 import com.google.common.util.concurrent.Futures;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsUpdateBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsOutput;
@@ -15,15 +19,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Future;
-import java.util.concurrent.atomic.AtomicLong;
-
 public class OpendaylightFlowTableStatisticsServiceMock implements OpendaylightFlowTableStatisticsService {
     NotificationProviderServiceHelper notifService;
-    AtomicLong transNum = new AtomicLong();
 
     public OpendaylightFlowTableStatisticsServiceMock(NotificationProviderServiceHelper notifService) {
         this.notifService = notifService;
@@ -32,7 +29,7 @@ public class OpendaylightFlowTableStatisticsServiceMock implements OpendaylightF
     @Override
     public Future<RpcResult<GetFlowTablesStatisticsOutput>> getFlowTablesStatistics(GetFlowTablesStatisticsInput input) {
         GetFlowTablesStatisticsOutputBuilder builder = new GetFlowTablesStatisticsOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         FlowTableStatisticsUpdateBuilder ftsBuilder = new FlowTableStatisticsUpdateBuilder();
         FlowTableAndStatisticsMapBuilder ftasmBuilder = new FlowTableAndStatisticsMapBuilder();
index 7e7342f609de994308005787aa8e929a551f4da1..4b9c047d847133a90b420913ad93cb1c0f80ca7c 100644 (file)
@@ -1,6 +1,10 @@
 package test.mock.util;
 
 import com.google.common.util.concurrent.Futures;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetAllGroupStatisticsInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetAllGroupStatisticsOutput;
@@ -29,15 +33,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Future;
-import java.util.concurrent.atomic.AtomicLong;
-
 public class OpendaylightGroupStatisticsServiceMock implements OpendaylightGroupStatisticsService {
     NotificationProviderServiceHelper notifService;
-    AtomicLong transNum = new AtomicLong();
 
     public OpendaylightGroupStatisticsServiceMock(NotificationProviderServiceHelper notifService) {
         this.notifService = notifService;
@@ -46,7 +43,7 @@ public class OpendaylightGroupStatisticsServiceMock implements OpendaylightGroup
     @Override
     public Future<RpcResult<GetAllGroupStatisticsOutput>> getAllGroupStatistics(GetAllGroupStatisticsInput input) {
         GetAllGroupStatisticsOutputBuilder builder = new GetAllGroupStatisticsOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         List<GroupStats> groupStats = new ArrayList<>();
         GroupStatsBuilder gsBuilder = new GroupStatsBuilder();
@@ -66,7 +63,7 @@ public class OpendaylightGroupStatisticsServiceMock implements OpendaylightGroup
     @Override
     public Future<RpcResult<GetGroupDescriptionOutput>> getGroupDescription(GetGroupDescriptionInput input) {
         GetGroupDescriptionOutputBuilder builder = new GetGroupDescriptionOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         List<GroupDescStats> groupDescStats = new ArrayList<>();
         GroupDescStatsUpdatedBuilder gdsuBuilder = new GroupDescStatsUpdatedBuilder();
@@ -89,7 +86,7 @@ public class OpendaylightGroupStatisticsServiceMock implements OpendaylightGroup
     @Override
     public Future<RpcResult<GetGroupFeaturesOutput>> getGroupFeatures(GetGroupFeaturesInput input) {
         GetGroupFeaturesOutputBuilder builder = new GetGroupFeaturesOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         GroupFeaturesUpdatedBuilder gfuBuilder = new GroupFeaturesUpdatedBuilder();
         gfuBuilder.setTransactionId(transId);
@@ -105,7 +102,7 @@ public class OpendaylightGroupStatisticsServiceMock implements OpendaylightGroup
     @Override
     public Future<RpcResult<GetGroupStatisticsOutput>> getGroupStatistics(GetGroupStatisticsInput input) {
         GetGroupStatisticsOutputBuilder builder = new GetGroupStatisticsOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         GroupStatsBuilder gsBuilder = new GroupStatsBuilder();
         List<GroupStats> groupStats = new ArrayList<>();
index 2d65d1ebedc60b71c3c6fd8ad5a88e9834a889cc..d5f0ce59951c8f79f5287b1d843ed02fefe13596 100644 (file)
@@ -1,6 +1,10 @@
 package test.mock.util;
 
 import com.google.common.util.concurrent.Futures;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
@@ -28,15 +32,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Future;
-import java.util.concurrent.atomic.AtomicLong;
-
 public class OpendaylightMeterStatisticsServiceMock implements OpendaylightMeterStatisticsService {
     NotificationProviderServiceHelper notifService;
-    AtomicLong transNum = new AtomicLong();
 
     public OpendaylightMeterStatisticsServiceMock(NotificationProviderServiceHelper notifService) {
         this.notifService = notifService;
@@ -45,7 +42,7 @@ public class OpendaylightMeterStatisticsServiceMock implements OpendaylightMeter
     @Override
     public Future<RpcResult<GetAllMeterConfigStatisticsOutput>> getAllMeterConfigStatistics(GetAllMeterConfigStatisticsInput input) {
         GetAllMeterConfigStatisticsOutputBuilder builder = new GetAllMeterConfigStatisticsOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         List<MeterConfigStats> meterConfigStats = new ArrayList<>();
         MeterConfigStatsBuilder mcsBuilder = new MeterConfigStatsBuilder();
@@ -66,7 +63,7 @@ public class OpendaylightMeterStatisticsServiceMock implements OpendaylightMeter
     @Override
     public Future<RpcResult<GetAllMeterStatisticsOutput>> getAllMeterStatistics(GetAllMeterStatisticsInput input) {
         GetAllMeterStatisticsOutputBuilder builder = new GetAllMeterStatisticsOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         MeterStatsBuilder msBuilder = new MeterStatsBuilder();
         msBuilder.setByteInCount(StatisticsManagerTest.COUNTER_64_TEST_VALUE);
@@ -86,7 +83,7 @@ public class OpendaylightMeterStatisticsServiceMock implements OpendaylightMeter
     @Override
     public Future<RpcResult<GetMeterFeaturesOutput>> getMeterFeatures(GetMeterFeaturesInput input) {
         GetMeterFeaturesOutputBuilder builder = new GetMeterFeaturesOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         MeterFeaturesUpdatedBuilder mfuBuilder = new MeterFeaturesUpdatedBuilder();
         mfuBuilder.setTransactionId(transId);
@@ -100,7 +97,7 @@ public class OpendaylightMeterStatisticsServiceMock implements OpendaylightMeter
     @Override
     public Future<RpcResult<GetMeterStatisticsOutput>> getMeterStatistics(GetMeterStatisticsInput input) {
         GetMeterStatisticsOutputBuilder builder = new GetMeterStatisticsOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         MeterStatsBuilder msBuilder = new MeterStatsBuilder();
         msBuilder.setKey(new MeterStatsKey(input.getMeterId()));
index 7164c56c1b3d1f8542480e25613d6fe0632356f7..c3d13f4c247c58d52085e10d0f1f9dd0ee3abe3a 100644 (file)
@@ -1,6 +1,10 @@
 package test.mock.util;
 
 import com.google.common.util.concurrent.Futures;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
@@ -18,15 +22,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.n
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Future;
-import java.util.concurrent.atomic.AtomicLong;
-
 public class OpendaylightPortStatisticsServiceMock implements OpendaylightPortStatisticsService {
     NotificationProviderServiceHelper notifService;
-    AtomicLong transNum = new AtomicLong();
 
     public OpendaylightPortStatisticsServiceMock(NotificationProviderServiceHelper notifService) {
         this.notifService = notifService;
@@ -35,7 +32,7 @@ public class OpendaylightPortStatisticsServiceMock implements OpendaylightPortSt
     @Override
     public Future<RpcResult<GetAllNodeConnectorsStatisticsOutput>> getAllNodeConnectorsStatistics(GetAllNodeConnectorsStatisticsInput input) {
         GetAllNodeConnectorsStatisticsOutputBuilder builder = new GetAllNodeConnectorsStatisticsOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         NodeConnectorStatisticsUpdateBuilder ncsuBuilder = new NodeConnectorStatisticsUpdateBuilder();
         NodeConnectorStatisticsAndPortNumberMapBuilder ncsapnmBuilder = new NodeConnectorStatisticsAndPortNumberMapBuilder();
@@ -43,7 +40,7 @@ public class OpendaylightPortStatisticsServiceMock implements OpendaylightPortSt
         ncsapnmBuilder.setKey(new NodeConnectorStatisticsAndPortNumberMapKey(StatisticsManagerTest.getNodeConnectorId()));
         ncsapnmBuilder.setReceiveDrops(StatisticsManagerTest.BIG_INTEGER_TEST_VALUE);
         nodeConnectorStatisticsAndPortNumberMaps.add(ncsapnmBuilder.build());
-        ncsuBuilder.setTransactionId(new TransactionId(BigInteger.valueOf(1)));
+        ncsuBuilder.setTransactionId(transId);
         ncsuBuilder.setId(input.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId());
         ncsuBuilder.setNodeConnectorStatisticsAndPortNumberMap(nodeConnectorStatisticsAndPortNumberMaps);
         ncsuBuilder.setMoreReplies(true);
@@ -60,7 +57,7 @@ public class OpendaylightPortStatisticsServiceMock implements OpendaylightPortSt
     @Override
     public Future<RpcResult<GetNodeConnectorStatisticsOutput>> getNodeConnectorStatistics(GetNodeConnectorStatisticsInput input) {
         GetNodeConnectorStatisticsOutputBuilder builder = new GetNodeConnectorStatisticsOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build());
     }
index 4f6806b8ca96735e3347854f11448effd2a659b6..8908dd5c0e73e64fce041aded43fa226ba98a636 100644 (file)
@@ -38,7 +38,7 @@ public class OpendaylightQueueStatisticsServiceMock implements OpendaylightQueue
     @Override
     public Future<RpcResult<GetAllQueuesStatisticsFromAllPortsOutput>> getAllQueuesStatisticsFromAllPorts(GetAllQueuesStatisticsFromAllPortsInput input) {
         GetAllQueuesStatisticsFromAllPortsOutputBuilder builder = new GetAllQueuesStatisticsFromAllPortsOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         QueueStatisticsUpdateBuilder qsuBuilder = new QueueStatisticsUpdateBuilder();
         QueueIdAndStatisticsMapBuilder qiasmBuilder = new QueueIdAndStatisticsMapBuilder();
@@ -57,7 +57,7 @@ public class OpendaylightQueueStatisticsServiceMock implements OpendaylightQueue
     @Override
     public Future<RpcResult<GetAllQueuesStatisticsFromGivenPortOutput>> getAllQueuesStatisticsFromGivenPort(GetAllQueuesStatisticsFromGivenPortInput input) {
         GetAllQueuesStatisticsFromGivenPortOutputBuilder builder = new GetAllQueuesStatisticsFromGivenPortOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         return Futures.immediateFuture(RpcResultBuilder.success(builder.build()).build());
     }
@@ -65,7 +65,7 @@ public class OpendaylightQueueStatisticsServiceMock implements OpendaylightQueue
     @Override
     public Future<RpcResult<GetQueueStatisticsFromGivenPortOutput>> getQueueStatisticsFromGivenPort(GetQueueStatisticsFromGivenPortInput input) {
         GetQueueStatisticsFromGivenPortOutputBuilder builder = new GetQueueStatisticsFromGivenPortOutputBuilder();
-        TransactionId transId = new TransactionId(BigInteger.valueOf(transNum.incrementAndGet()));
+        TransactionId transId = new TransactionId(BigInteger.valueOf(TestUtils.getNewTransactionId()));
         builder.setTransactionId(transId);
         QueueIdAndStatisticsMapBuilder qiasmBuilder = new QueueIdAndStatisticsMapBuilder();
         List<QueueIdAndStatisticsMap> queueIdAndStatisticsMaps = new ArrayList<>();
diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/ProviderContextMock.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/ProviderContextMock.java
deleted file mode 100644 (file)
index 9b40a76..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-package test.mock.util;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
-import org.opendaylight.controller.sal.binding.api.BindingAwareService;
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.RpcService;
-
-public class ProviderContextMock implements BindingAwareBroker.ProviderContext {
-
-    RpcProviderRegistry rpcProviderMock;
-    NotificationProviderService notificationProviderService;
-    DataBroker dataBroker;
-
-    public ProviderContextMock(RpcProviderRegistry rpcProviderMock, DataBroker dataBroker,
-                               NotificationProviderService notificationProviderServiceMock) {
-        this.rpcProviderMock = rpcProviderMock;
-        this.dataBroker = dataBroker;
-        this.notificationProviderService = notificationProviderServiceMock;
-    }
-
-    @Override
-    public void registerFunctionality(BindingAwareProvider.ProviderFunctionality functionality) {
-
-    }
-
-    @Override
-    public void unregisterFunctionality(BindingAwareProvider.ProviderFunctionality functionality) {
-
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public <T extends BindingAwareService> T getSALService(Class<T> service) {
-        if (service.equals(DataBroker.class)) {
-            return (T) dataBroker;
-        }
-        else if (service.equals(NotificationProviderService.class)) {
-            return (T) notificationProviderService;
-        }
-        return null;
-    }
-
-    @Override
-    public <T extends RpcService> BindingAwareBroker.RpcRegistration<T> addRpcImplementation(Class<T> serviceInterface, T implementation) throws IllegalStateException {
-        return null;
-    }
-
-    @Override
-    public <T extends RpcService> BindingAwareBroker.RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> serviceInterface, T implementation) throws IllegalStateException {
-        return null;
-    }
-
-    @Override
-    public <L extends RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>> ListenerRegistration<L> registerRouteChangeListener(L listener) {
-        return null;
-    }
-
-    @Override
-    public <T extends RpcService> T getRpcService(Class<T> serviceInterface) {
-        return rpcProviderMock.getRpcService(serviceInterface);
-    }
-}
index 7f266d9c3ca66462b20985d87be50d0ba4127f7e..45765edd0e99bd985ebde19dfbe86b09a0becaad 100644 (file)
@@ -1,9 +1,17 @@
 package test.mock.util;
 
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.statistics.manager.StatisticsManager;
+import org.opendaylight.controller.md.statistics.manager.impl.StatisticsManagerConfig;
+import org.opendaylight.controller.md.statistics.manager.impl.StatisticsManagerImpl;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter32;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter64;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FeatureCapability;
@@ -35,12 +43,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-
 public abstract class StatisticsManagerTest extends AbstractDataBrokerTest {
 
     public static final Counter64 COUNTER_64_TEST_VALUE = new Counter64(BigInteger.valueOf(128));
@@ -48,6 +50,9 @@ public abstract class StatisticsManagerTest extends AbstractDataBrokerTest {
     public static final Long MAX_GROUPS_TEST_VALUE = 2000L;
     public static final BigInteger BIG_INTEGER_TEST_VALUE = BigInteger.valueOf(1000);
 
+    private static final int DEFAULT_MIN_REQUEST_NET_MONITOR_INTERVAL = 5000;
+    private static final int MAX_NODES_FOR_COLLECTOR = 16;
+
     private static Flow flow;
     private static Group group;
     private static Meter meter;
@@ -59,7 +64,6 @@ public abstract class StatisticsManagerTest extends AbstractDataBrokerTest {
     private final NotificationProviderServiceHelper notificationMock = new NotificationProviderServiceHelper();
     protected final NodeKey s1Key = new NodeKey(new NodeId("S1"));
     protected RpcProviderRegistryMock rpcRegistry;
-    protected ProviderContextMock providerContext;
 
     @BeforeClass
     public static void setupTests() {
@@ -75,7 +79,6 @@ public abstract class StatisticsManagerTest extends AbstractDataBrokerTest {
     @Before
     public void init() {
         rpcRegistry = new RpcProviderRegistryMock(notificationMock);
-        providerContext = new ProviderContextMock(rpcRegistry, getDataBroker(), notificationMock.getNotifBroker());
     }
 
     // node with statistics capabilities will enable cyclic statistics collection
@@ -94,7 +97,7 @@ public abstract class StatisticsManagerTest extends AbstractDataBrokerTest {
             capabilitiyList.add(capability);
         }
         sfBuilder.setCapabilities(capabilitiyList);
-        sfBuilder.setMaxTables((short) 2);
+        sfBuilder.setMaxTables((short) 255);
         final NodeBuilder nodeBuilder = new NodeBuilder();
         nodeBuilder.setKey(nodeKey);
         fcnBuilder.setSwitchFeatures(sfBuilder.build());
@@ -137,6 +140,9 @@ public abstract class StatisticsManagerTest extends AbstractDataBrokerTest {
         final FlowCapableNodeBuilder fcnBuilder = new FlowCapableNodeBuilder();
         final NodeBuilder nodeBuilder = new NodeBuilder();
         nodeBuilder.setKey(nodeKey);
+        final SwitchFeaturesBuilder sfBuilder = new SwitchFeaturesBuilder();
+        sfBuilder.setMaxTables((short) 255);
+        fcnBuilder.setSwitchFeatures(sfBuilder.build());
         final FlowCapableNode flowCapableNode = fcnBuilder.build();
         nodeBuilder.addAugmentation(FlowCapableNode.class, flowCapableNode);
         final Node node = nodeBuilder.build();
@@ -167,6 +173,15 @@ public abstract class StatisticsManagerTest extends AbstractDataBrokerTest {
         notificationMock.pushNotification(nrBuilder.build());
     }
 
+    public StatisticsManager setupStatisticsManager() {
+        StatisticsManagerConfig.StatisticsManagerConfigBuilder confBuilder = StatisticsManagerConfig.builder();
+        confBuilder.setMaxNodesForCollector(MAX_NODES_FOR_COLLECTOR);
+        confBuilder.setMinRequestNetMonitorInterval(DEFAULT_MIN_REQUEST_NET_MONITOR_INTERVAL);
+        StatisticsManager statsProvider = new StatisticsManagerImpl(getDataBroker(), confBuilder.build());
+        statsProvider.start(notificationMock.getNotifBroker(), rpcRegistry);
+        return statsProvider;
+    }
+
     public static Flow getFlow() {
         return flow;
     }
index e38a25e8e9098b8851d2b68cd709c6733f3251e4..d18dc23ad4e959cc530f9c97cd7e193b1479d420 100644 (file)
@@ -1,11 +1,19 @@
 package test.mock.util;
 
 import java.util.Random;
+import java.util.concurrent.atomic.AtomicLong;
 
 public class TestUtils {
+
+    private static AtomicLong transId = new AtomicLong();
+
     private static Random rnd = new Random();
 
     public static long nextLong(long RangeBottom, long rangeTop) {
         return RangeBottom + ((long)(rnd.nextDouble()*(rangeTop - RangeBottom)));
     }
+
+    public static long getNewTransactionId() {
+        return transId.incrementAndGet();
+    }
 }
index fa8892853ba16626ac32f98e4a4bf187e3cba18e..21ec8e82d68632aeb6a2793a77d00f760a121740 100644 (file)
@@ -22,7 +22,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class ProxyServerHandler extends ChannelInboundHandlerAdapter {
-    private static final Logger logger = LoggerFactory.getLogger(ProxyServerHandler.class.getName());
+    private static final Logger LOG = LoggerFactory.getLogger(ProxyServerHandler.class);
     private final Bootstrap clientBootstrap;
     private final LocalAddress localAddress;
 
@@ -48,32 +48,32 @@ public class ProxyServerHandler extends ChannelInboundHandlerAdapter {
 
     @Override
     public void channelInactive(ChannelHandlerContext ctx) {
-        logger.trace("channelInactive - closing client channel");
+        LOG.trace("channelInactive - closing client channel");
         clientChannel.close();
     }
 
     @Override
     public void channelRead(ChannelHandlerContext ctx, final Object msg) {
-        logger.trace("Writing to client channel");
+        LOG.trace("Writing to client channel");
         clientChannel.write(msg);
     }
 
     @Override
     public void channelReadComplete(ChannelHandlerContext ctx) {
-        logger.trace("Flushing client channel");
+        LOG.trace("Flushing client channel");
         clientChannel.flush();
     }
 
     @Override
     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
         // Close the connection when an exception is raised.
-        logger.warn("Unexpected exception from downstream.", cause);
+        LOG.warn("Unexpected exception from downstream.", cause);
         ctx.close();
     }
 }
 
 class ProxyClientHandler extends ChannelInboundHandlerAdapter {
-    private static final Logger logger = LoggerFactory.getLogger(ProxyClientHandler.class);
+    private static final Logger LOG = LoggerFactory.getLogger(ProxyClientHandler.class);
 
     private final ChannelHandlerContext remoteCtx;
     private ChannelHandlerContext localCtx;
@@ -85,26 +85,26 @@ class ProxyClientHandler extends ChannelInboundHandlerAdapter {
     @Override
     public void channelActive(ChannelHandlerContext ctx) {
         checkState(this.localCtx == null);
-        logger.trace("Client channel active");
+        LOG.trace("Client channel active");
         this.localCtx = ctx;
     }
 
     @Override
     public void channelRead(ChannelHandlerContext ctx, Object msg) {
-        logger.trace("Forwarding message");
+        LOG.trace("Forwarding message");
         remoteCtx.write(msg);
     }
 
     @Override
     public void channelReadComplete(ChannelHandlerContext ctx) {
-        logger.trace("Flushing remote ctx");
+        LOG.trace("Flushing remote ctx");
         remoteCtx.flush();
     }
 
     @Override
     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
         // Close the connection when an exception is raised.
-        logger.warn("Unexpected exception from downstream", cause);
+        LOG.warn("Unexpected exception from downstream", cause);
         checkState(this.localCtx.equals(ctx));
         ctx.close();
     }
@@ -112,7 +112,7 @@ class ProxyClientHandler extends ChannelInboundHandlerAdapter {
     // called both when local or remote connection dies
     @Override
     public void channelInactive(ChannelHandlerContext ctx) {
-        logger.trace("channelInactive() called, closing remote client ctx");
+        LOG.trace("channelInactive() called, closing remote client ctx");
         remoteCtx.close();
     }
 
index bc94e596d77ceabd53667c5a9ab74a2928f74fff..355041f8dfffb74efb120cc99b9b9e077cc0b26e 100644 (file)
@@ -22,22 +22,22 @@ import org.slf4j.LoggerFactory;
  * Opens TCP port specified in config.ini, creates bridge between this port and local netconf server.
  */
 public class NetconfTCPActivator implements BundleActivator {
-    private static final Logger logger = LoggerFactory.getLogger(NetconfTCPActivator.class);
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfTCPActivator.class);
     private ProxyServer proxyServer;
 
     @Override
     public void start(BundleContext context) {
         final Optional<InetSocketAddress> maybeAddress = NetconfConfigUtil.extractNetconfServerAddress(context, InfixProp.tcp);
         if (maybeAddress.isPresent() == false) {
-            logger.debug("Netconf tcp server is not configured to start");
+            LOG.debug("Netconf tcp server is not configured to start");
             return;
         }
         InetSocketAddress address = maybeAddress.get();
         if (address.getAddress().isAnyLocalAddress()) {
-            logger.warn("Unprotected netconf TCP address is configured to ANY local address. This is a security risk. " +
-                    "Consider changing {} to 127.0.0.1", NetconfConfigUtil.getNetconfServerAddressKey(InfixProp.tcp));
+            LOG.warn("Unprotected netconf TCP address is configured to ANY local address. This is a security risk. Consider changing {} to 127.0.0.1",
+                    NetconfConfigUtil.getNetconfServerAddressKey(InfixProp.tcp));
         }
-        logger.info("Starting TCP netconf server at {}", address);
+        LOG.info("Starting TCP netconf server at {}", address);
         proxyServer = new ProxyServer(address, NetconfConfigUtil.getNetconfLocalAddress());
     }
 
index e36d58591e2ad8a1b2f757ca475ec7f41aa392ae..e441c709ccabcdcc9a9659a0ca96add3c21a27f1 100644 (file)
@@ -147,7 +147,7 @@ public final class Main {
 
         void validate() {
             checkArgument(deviceCount > 0, "Device count has to be > 0");
-            checkArgument(startingPort > 1024, "Starting port has to be > 1024");
+            checkArgument(startingPort > 1023, "Starting port has to be > 1023");
 
             if(schemasDir != null) {
                 checkArgument(schemasDir.exists(), "Schemas dir has to exist");
@@ -167,6 +167,10 @@ public final class Main {
         final NetconfDeviceSimulator netconfDeviceSimulator = new NetconfDeviceSimulator();
         try {
             final List<Integer> openDevices = netconfDeviceSimulator.start(params);
+            if (openDevices.size() == 0) {
+                LOG.error("Failed to start any simulated devices, exiting...");
+                System.exit(1);
+            }
             if(params.distroFolder != null) {
                 final ConfigGenerator configGenerator = new ConfigGenerator(params.distroFolder, openDevices);
                 final List<File> generated = configGenerator.generate(params.ssh, params.generateConfigBatchSize, params.generateConfigsTimeout, params.generateConfigsAddress);
index adcdea6073860b5f6b660faa356baf9cf7455df4..c6cad90355705961ca72e6cd64da36ff41780e14 100644 (file)
@@ -30,6 +30,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.lang.management.ManagementFactory;
+import java.net.BindException;
 import java.net.Inet4Address;
 import java.net.InetSocketAddress;
 import java.net.URI;
@@ -185,6 +186,10 @@ public class NetconfDeviceSimulator implements Closeable {
         final PEMGeneratorHostKeyProvider keyPairProvider = getPemGeneratorHostKeyProvider();
 
         for (int i = 0; i < params.deviceCount; i++) {
+            if (currentPort > 65535) {
+                LOG.warn("Port cannot be greater than 65535, stopping further attempts.");
+                break;
+            }
             final InetSocketAddress address = getAddress(currentPort);
 
             final ChannelFuture server;
@@ -197,14 +202,17 @@ public class NetconfDeviceSimulator implements Closeable {
                     final SshProxyServer sshServer = new SshProxyServer(minaTimerExecutor, nettyThreadgroup, nioExecutor);
                     sshServer.bind(getSshConfiguration(bindingAddress, tcpLocalAddress));
                     sshWrappers.add(sshServer);
-                } catch (final Exception e) {
-                    LOG.warn("Cannot start simulated device on {}, skipping", address, e);
+                } catch (final BindException e) {
+                    LOG.warn("Cannot start simulated device on {}, port already in use. Skipping.", address);
                     // Close local server and continue
                     server.cancel(true);
                     if(server.isDone()) {
                         server.channel().close();
                     }
                     continue;
+                } catch (final IOException e) {
+                    LOG.warn("Cannot start simulated device on {} due to IOException.", address, e);
+                    break;
                 } finally {
                     currentPort++;
                 }
@@ -242,6 +250,8 @@ public class NetconfDeviceSimulator implements Closeable {
 
         if(openDevices.size() == params.deviceCount) {
             LOG.info("All simulated devices started successfully from port {} to {}", params.startingPort, currentPort - 1);
+        } else if (openDevices.size() == 0) {
+            LOG.warn("No simulated devices started.");
         } else {
             LOG.warn("Not all simulated devices started successfully. Started devices ar on ports {}", openDevices);
         }
index da5e2090ff4cfb70d0c253ad339154dccd9ac107..cb5874ab24f6645b134c5483253dea85dc8bd712 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.netconf.auth.usermanager;
 
+import com.google.common.annotations.VisibleForTesting;
 import org.opendaylight.controller.netconf.auth.AuthProvider;
 import org.opendaylight.controller.sal.authorization.AuthResultEnum;
 import org.opendaylight.controller.usermanager.IUserManager;
@@ -17,13 +18,11 @@ import org.osgi.util.tracker.ServiceTrackerCustomizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.annotations.VisibleForTesting;
-
 /**
  * AuthProvider implementation delegating to AD-SAL UserManager instance.
  */
 public class AuthProviderImpl implements AuthProvider {
-    private static final Logger logger = LoggerFactory.getLogger(AuthProviderImpl.class);
+    private static final Logger LOG = LoggerFactory.getLogger(AuthProviderImpl.class);
 
     private IUserManager nullableUserManager;
 
@@ -32,20 +31,20 @@ public class AuthProviderImpl implements AuthProvider {
         final ServiceTrackerCustomizer<IUserManager, IUserManager> customizer = new ServiceTrackerCustomizer<IUserManager, IUserManager>() {
             @Override
             public IUserManager addingService(final ServiceReference<IUserManager> reference) {
-                logger.trace("UerManager {} added", reference);
+                LOG.trace("UerManager {} added", reference);
                 nullableUserManager = bundleContext.getService(reference);
                 return nullableUserManager;
             }
 
             @Override
             public void modifiedService(final ServiceReference<IUserManager> reference, final IUserManager service) {
-                logger.trace("Replacing modified UerManager {}", reference);
+                LOG.trace("Replacing modified UerManager {}", reference);
                 nullableUserManager = service;
             }
 
             @Override
             public void removedService(final ServiceReference<IUserManager> reference, final IUserManager service) {
-                logger.trace("Removing UerManager {}. This AuthProvider will fail to authenticate every time", reference);
+                LOG.trace("Removing UerManager {}. This AuthProvider will fail to authenticate every time", reference);
                 synchronized (AuthProviderImpl.this) {
                     nullableUserManager = null;
                 }
@@ -62,11 +61,11 @@ public class AuthProviderImpl implements AuthProvider {
     @Override
     public synchronized boolean authenticated(final String username, final String password) {
         if (nullableUserManager == null) {
-            logger.warn("Cannot authenticate user '{}', user manager service is missing", username);
+            LOG.warn("Cannot authenticate user '{}', user manager service is missing", username);
             throw new IllegalStateException("User manager service is not available");
         }
         final AuthResultEnum authResult = nullableUserManager.authenticate(username, password);
-        logger.debug("Authentication result for user '{}' : {}", username, authResult);
+        LOG.debug("Authentication result for user '{}' : {}", username, authResult);
         return authResult.equals(AuthResultEnum.AUTH_ACCEPT) || authResult.equals(AuthResultEnum.AUTH_ACCEPT_LOC);
     }
 
index 0269bcccb989492e69b616fc955545ca49509f31..5fd53dce55639e0b5c8a811e11ab4b7b2a637117 100644 (file)
@@ -8,7 +8,6 @@
 package org.opendaylight.controller.netconf.util;
 
 import com.google.common.base.Preconditions;
-
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
@@ -19,7 +18,7 @@ import org.w3c.dom.Document;
 
 public final class NetconfUtil {
 
-    private static final Logger logger = LoggerFactory.getLogger(NetconfUtil.class);
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfUtil.class);
 
     private NetconfUtil() {}
 
@@ -30,7 +29,7 @@ public final class NetconfUtil {
         if (element.getName().equals(XmlNetconfConstants.OK)) {
             return response;
         }
-        logger.warn("Can not load last configuration. Operation failed.");
+        LOG.warn("Can not load last configuration. Operation failed.");
         throw new IllegalStateException("Can not load last configuration. Operation failed: "
                 + XmlUtil.toString(response));
     }
index 6cc5006aba4ba7f9266935564911905d9b364b58..d2a6d2b58d237069ae67bd3c6a514ea5bfd090f6 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.controller.netconf.util.exception;
 
 import java.util.Collections;
 import java.util.Map;
-
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 
 public class MissingNameSpaceException extends NetconfDocumentedException {
index 7b5f52e3967178c8e30da453a06662994e054093..6d7c7ca7c434a884411822f2065096083cbe812e 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.controller.netconf.util.exception;
 
 import java.util.Collections;
 import java.util.Map;
-
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 
 public class UnexpectedElementException extends NetconfDocumentedException {
index 582fd23e16e7576c4b4c0622216f4db6f505f10f..4a19390b362f9358aff0db32d6e705b4bba16bbd 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.controller.netconf.util.exception;
 
 import java.util.Collections;
 import java.util.Map;
-
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 
 public class UnexpectedNamespaceException extends NetconfDocumentedException {
index 15223cb60ba994472cdedc939a6586f569471593..5cd17a2331e293c23d064c9acd535e021de43c8e 100644 (file)
@@ -8,11 +8,12 @@
 
 package org.opendaylight.controller.netconf.util.messages;
 
-import org.opendaylight.controller.netconf.api.NetconfMessage;
-
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
 import java.util.Set;
-
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
@@ -20,10 +21,6 @@ import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Sets;
-
 /**
  * NetconfMessage that can carry additional header with session metadata. See {@link org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader}
  */
index fa26455c9875d7245429ef72f2ce11b57c56acac..ac8a557d9ae359c8d5425f88ae7385905eaf9552 100644 (file)
@@ -8,10 +8,9 @@
 
 package org.opendaylight.controller.netconf.util.messages;
 
-import java.nio.ByteBuffer;
-
 import com.google.common.base.Charsets;
 import com.google.common.base.Preconditions;
+import java.nio.ByteBuffer;
 
 /**
  * Netconf message header is used only when chunked framing mechanism is
index c532b7f9a6f235a0eebc7dc4a53bc10f2208dbc4..61b23202c3a134c27d975279e2f29f7d7eefefa0 100644 (file)
@@ -23,7 +23,7 @@ import org.w3c.dom.Document;
 
 public final class NetconfMessageUtil {
 
-    private static final Logger logger = LoggerFactory.getLogger(NetconfMessageUtil.class);
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfMessageUtil.class);
 
     private NetconfMessageUtil() {}
 
@@ -70,7 +70,7 @@ public final class NetconfMessageUtil {
                 try {
                     return input.getTextContent().trim();
                 } catch (NetconfDocumentedException e) {
-                    logger.trace("Error fetching inpit text content becauese {}",e);
+                    LOG.trace("Error fetching input text content",e);
                     return null;
                 }
             }
index 6604834fe42c02b3b3188fd7cd7f85c7b887ff3d..fe5ed03320cdd3b921e0c6d056d89b4d3381a58c 100644 (file)
@@ -9,14 +9,12 @@
 package org.opendaylight.controller.netconf.util.messages;
 
 import com.google.common.base.Preconditions;
-
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelFutureListener;
-
-import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
@@ -27,20 +25,20 @@ import org.w3c.dom.Element;
 import org.w3c.dom.NamedNodeMap;
 
 public final class SendErrorExceptionUtil {
-    private static final Logger logger = LoggerFactory.getLogger(SendErrorExceptionUtil.class);
+    private static final Logger LOG = LoggerFactory.getLogger(SendErrorExceptionUtil.class);
 
     private SendErrorExceptionUtil() {}
 
     public static void sendErrorMessage(final NetconfSession session,
             final NetconfDocumentedException sendErrorException) {
-        logger.trace("Sending error {}", sendErrorException.getMessage(), sendErrorException);
+        LOG.trace("Sending error {}", sendErrorException.getMessage(), sendErrorException);
         final Document errorDocument = createDocument(sendErrorException);
         ChannelFuture f = session.sendMessage(new NetconfMessage(errorDocument));
         f.addListener(new SendErrorVerifyingListener(sendErrorException));
     }
 
     public static void sendErrorMessage(Channel channel, NetconfDocumentedException sendErrorException) {
-        logger.trace("Sending error {}", sendErrorException.getMessage(), sendErrorException);
+        LOG.trace("Sending error {}", sendErrorException.getMessage(), sendErrorException);
         final Document errorDocument = createDocument(sendErrorException);
         ChannelFuture f = channel.writeAndFlush(new NetconfMessage(errorDocument));
         f.addListener(new SendErrorVerifyingListener(sendErrorException));
@@ -49,7 +47,7 @@ public final class SendErrorExceptionUtil {
     public static void sendErrorMessage(NetconfSession session, NetconfDocumentedException sendErrorException,
             NetconfMessage incommingMessage) {
         final Document errorDocument = createDocument(sendErrorException);
-        logger.trace("Sending error {}", XmlUtil.toString(errorDocument));
+        LOG.trace("Sending error {}", XmlUtil.toString(errorDocument));
         tryToCopyAttributes(incommingMessage.getDocument(), errorDocument, sendErrorException);
         ChannelFuture f = session.sendMessage(new NetconfMessage(errorDocument));
         f.addListener(new SendErrorVerifyingListener(sendErrorException));
@@ -76,7 +74,7 @@ public final class SendErrorExceptionUtil {
                 rpcReply.setAttributeNode((Attr) errorDocument.importNode(attr, true));
             }
         } catch (final Exception e) {
-            logger.warn("Unable to copy incomming attributes to {}, returned rpc-error might be invalid for client",
+            LOG.warn("Unable to copy incomming attributes to {}, returned rpc-error might be invalid for client",
                     sendErrorException, e);
         }
     }
index c77e0d7da25dc112e54489fbae42bf317a3f2b3f..64aeebd54205c658cad64589994a436282cbdb5b 100644 (file)
@@ -16,7 +16,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public final class NetconfConfigUtil {
-    private static final Logger logger = LoggerFactory.getLogger(NetconfConfigUtil.class);
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfConfigUtil.class);
 
     private static final String PREFIX_PROP = "netconf.";
 
@@ -48,7 +48,7 @@ public final class NetconfConfigUtil {
         try {
             return Long.parseLong(timeoutString);
         } catch (final NumberFormatException e) {
-            logger.warn("Cannot parse {} property: {}, using defaults", key, timeoutString, e);
+            LOG.warn("Cannot parse {} property: {}, using defaults", key, timeoutString, e);
             return DEFAULT_TIMEOUT_MILLIS;
         }
     }
@@ -89,7 +89,7 @@ public final class NetconfConfigUtil {
             try {
                 return Optional.of(parseAddress(address, port));
             } catch (final RuntimeException e) {
-                logger.warn("Unable to parse {} netconf address from {}:{}, fallback to default",
+                LOG.warn("Unable to parse {} netconf address from {}:{}, fallback to default",
                         infixProp, address, port, e);
             }
         }
index 23fe7cdf41e1b5cc9266f53a3f8694316311daa1..87ecb2de090ec8813d0bd0215cde1ade3bfcddd9 100644 (file)
@@ -8,14 +8,12 @@
 
 package org.opendaylight.controller.netconf.util.xml;
 
+import com.google.common.collect.ImmutableMap;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.Map;
-
 import javax.xml.namespace.NamespaceContext;
 
-import com.google.common.collect.ImmutableMap;
-
 // http://www.ibm.com/developerworks/library/x-nmspccontext/
 public class HardcodedNamespaceResolver implements NamespaceContext {
     private final Map<String/* prefix */, String/* namespace */> prefixesToNamespaces;
index e7ce4541559943e86983e2e83285ff0d0b9c18e6..eaaf320b023c454f5638a0f2138d262c312d0d1d 100644 (file)
@@ -12,7 +12,6 @@ import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathExpression;
 import javax.xml.xpath.XPathExpressionException;
 import javax.xml.xpath.XPathFactory;
-
 import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 
 public final class XMLNetconfUtil {
index 3c63204881aa9ea0ef3e0909ad302e73187d5b31..e17cad977ce13dd254b996ebb9a31122fe6a87e0 100644 (file)
@@ -40,7 +40,7 @@ public final class XmlElement {
     public static final String DEFAULT_NAMESPACE_PREFIX = "";
 
     private final Element element;
-    private static final Logger logger = LoggerFactory.getLogger(XmlElement.class);
+    private static final Logger LOG = LoggerFactory.getLogger(XmlElement.class);
 
     private XmlElement(Element element) {
         this.element = element;
@@ -132,7 +132,7 @@ public final class XmlElement {
 
     public void checkNamespace(String expectedNamespace) throws UnexpectedNamespaceException, MissingNameSpaceException {
         if (!getNamespace().equals(expectedNamespace))
-       {
+        {
             throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s should be %s",
                     getNamespace(),
                     expectedNamespace),
@@ -405,7 +405,7 @@ public final class XmlElement {
             try {
                 sb.append(", namespace='").append(getNamespace()).append('\'');
             } catch (MissingNameSpaceException e) {
-                logger.trace("Missing namespace for element.");
+                LOG.trace("Missing namespace for element.");
             }
         }
         sb.append('}');
index 8108c8e7402fac29469cf7804efd96e1dc6455df..bdab8c6209184d1262542bcd1b25b7d171157919 100644 (file)
@@ -8,19 +8,16 @@
 
 package org.opendaylight.controller.netconf.util.xml;
 
+import com.google.common.base.Preconditions;
 import java.io.IOException;
 import java.io.InputStream;
-
 import javax.xml.transform.Source;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.validation.Schema;
 import javax.xml.validation.Validator;
-
 import org.w3c.dom.Document;
 import org.xml.sax.SAXException;
 
-import com.google.common.base.Preconditions;
-
 public final class XmlNetconfValidator {
 
     private static final Schema SCHEMA;
index 9e227ee05d6d9839c1f547ec5b53f1ff5b9f9a67..68c4d9fdab62413378eb2332ada310df601bf48e 100644 (file)
@@ -10,14 +10,12 @@ package org.opendaylight.controller.netconf.util.xml;
 
 import com.google.common.base.Charsets;
 import com.google.common.base.Optional;
-
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.StringWriter;
-
 import javax.xml.XMLConstants;
 import javax.xml.namespace.QName;
 import javax.xml.parsers.DocumentBuilder;
@@ -35,7 +33,6 @@ import javax.xml.validation.Schema;
 import javax.xml.validation.SchemaFactory;
 import javax.xml.xpath.XPathExpression;
 import javax.xml.xpath.XPathExpressionException;
-
 import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -124,7 +121,7 @@ public final class XmlUtil {
     public static Element createTextElementWithNamespacedContent(Document document, String qName, String prefix,
                                                                  String namespace, String contentWithoutPrefix) {
 
-       return createTextElementWithNamespacedContent(document, qName, prefix, namespace, contentWithoutPrefix, Optional.<String>absent());
+        return createTextElementWithNamespacedContent(document, qName, prefix, namespace, contentWithoutPrefix, Optional.<String>absent());
     }
 
     public static Element createTextElementWithNamespacedContent(Document document, String qName, String prefix,
index 47d0d4c7ccc56294d85e753f603e6c8bd951f2c0..dc175c57337205c27f76b03cd55c8af9ecf774fd 100644 (file)
@@ -7,9 +7,10 @@
  */
 package org.opendaylight.controller.netconf.util;
 
-import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.fail;
+import static org.hamcrest.CoreMatchers.containsString;
+
 import org.junit.Test;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Document;
index 62633dd3f25c45d704ab624f5e8d161ecc99c9f5..a6d1d5b999bcfa0757ec12b5aa13db0f2485d400 100644 (file)
@@ -8,6 +8,11 @@
 
 package org.opendaylight.controller.netconf.util.mapping;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
@@ -17,11 +22,6 @@ import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-
 public class AbstractLastNetconfOperationTest {
     class LastNetconfOperationImplTest extends  AbstractLastNetconfOperation  {
 
index ea4a6e61f23aecd32e2a4261438d5e46f416d328..c7f6321e2c2c22d6c5893af56e76817790ca7323 100644 (file)
@@ -8,6 +8,11 @@
 
 package org.opendaylight.controller.netconf.util.mapping;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
 import java.io.IOException;
 import org.junit.Before;
 import org.junit.Test;
@@ -21,11 +26,6 @@ import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.xml.sax.SAXException;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-
 public class AbstractNetconfOperationTest {
 
     class NetconfOperationImpl extends AbstractNetconfOperation {
index d1310de3e20999857cc1f5829e42c853621f9be4..911b73f097ffad0c24af495e3cc39ce113bba617 100644 (file)
@@ -8,6 +8,8 @@
 
 package org.opendaylight.controller.netconf.util.mapping;
 
+import static org.junit.Assert.assertEquals;
+
 import org.junit.Test;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
@@ -15,8 +17,6 @@ import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import static org.junit.Assert.assertEquals;
-
 public class AbstractSingletonNetconfOperationTest {
     class SingletonNCOperationImpl extends AbstractSingletonNetconfOperation {
 
index 95c91243af7a9e4b135f388c085e2543601c5bb0..5e50eb93fb1f62d43799a5bb510b07c4f52a22ff 100644 (file)
@@ -8,11 +8,11 @@
 
 package org.opendaylight.controller.netconf.util.messages;
 
+import static org.junit.Assert.assertEquals;
+
 import org.junit.Before;
 import org.junit.Test;
 
-import static org.junit.Assert.assertEquals;
-
 public class NetconfHelloMessageAdditionalHeaderTest {
 
 
index 5a9d07f6b1689455eae43a6dff82f6c5984803b7..4e157186ff911fed6a974709e703566080ffaa5d 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.controller.netconf.util.messages;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+
 import com.google.common.base.Optional;
 import java.util.Set;
 import org.junit.Before;
index d5ff3380d28b7493b1b7e18962fc1bdbc4505e16..05c31be3957b712a0418187efdad7546088b553e 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.netconf.util.messages;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+
 import com.google.common.base.Charsets;
 import org.junit.Test;
 
index 2af34e957e2505917117ac0bc758e86ed3ee8aad..12769f5ed371473680ee2e3c5bb1dfec49866b95 100644 (file)
@@ -8,15 +8,15 @@
 
 package org.opendaylight.controller.netconf.util.messages;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 import java.util.Collection;
 import org.junit.Test;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
 import org.w3c.dom.Document;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
 public class NetconfMessageUtilTest {
     @Test
     public void testNetconfMessageUtil() throws Exception {
index c8d562cb9c645879bbdaa868d227b675367e3e76..20287741b9fd57532a8fb4007ae320c517f34540 100644 (file)
@@ -8,6 +8,12 @@
 
 package org.opendaylight.controller.netconf.util.messages;
 
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
 import io.netty.util.concurrent.GenericFutureListener;
@@ -19,9 +25,6 @@ import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
 import org.w3c.dom.Document;
 
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.*;
-
 public class SendErrorExceptionUtilTest {
 
     NetconfSession netconfSession;
index ebee41145ab1d77c2296bf21ded57c83b172d98e..1a701057aa0ac8a4b2addc87af37b58582b24a46 100644 (file)
@@ -13,6 +13,7 @@ import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+
 import com.google.common.base.Optional;
 import io.netty.channel.local.LocalAddress;
 import java.net.InetSocketAddress;
index 457dda3080fa48adb18e170ba1e36d01d10513f6..e1331b1380935e86bad9fa962060e8c02210ce24 100644 (file)
@@ -8,23 +8,20 @@
 
 package org.opendaylight.controller.netconf.util.test;
 
+import com.google.common.base.Charsets;
+import com.google.common.base.Preconditions;
+import com.google.common.io.CharStreams;
+import com.google.common.io.InputSupplier;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-
 import javax.xml.parsers.ParserConfigurationException;
-
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.xml.sax.SAXException;
 
-import com.google.common.base.Charsets;
-import com.google.common.base.Preconditions;
-import com.google.common.io.CharStreams;
-import com.google.common.io.InputSupplier;
-
 public class XmlFileLoader {
 
     public static NetconfMessage xmlFileToNetconfMessage(final String fileName) throws IOException, SAXException,
index a88de956e2f336704ce9af6895b9cf7285ce7f2b..22210a394e6a344cdb66df27af19662777c65b59 100644 (file)
@@ -17,6 +17,7 @@ import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import com.google.common.base.Optional;
 import java.util.Map;
 import org.junit.Before;
 import org.junit.Test;
@@ -25,8 +26,6 @@ import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceExcept
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import com.google.common.base.Optional;
-
 public class XmlElementTest {
 
     private final String elementAsString = "<top xmlns=\"namespace\" xmlns:a=\"attrNamespace\" a:attr1=\"value1\" attr2=\"value2\">" +
index 5e94ac6110ca73d84817222f566cf965ff01d62d..0af445f17dea163739f22bf5e7bfd91242768045 100644 (file)
@@ -6,4 +6,4 @@
 <lexical-values/>
 </fidelity>
 </start-exi>
-</rpc>
+</rpc>
\ No newline at end of file
index 170c753993f174d5aeeba66ca7e157ec5a7ad757..7f1fe849e81e41ee7585660395e5443f451f0483 100644 (file)
@@ -1,3 +1,3 @@
 <rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <stop-exi xmlns="urn:ietf:params:xml:ns:netconf:exi:1.0"/>
-</rpc>
+</rpc>
\ No newline at end of file