From: Tony Tkacik Date: Wed, 3 Dec 2014 09:26:58 +0000 (+0000) Subject: Merge "Fix checkstyle warnings in netty-threadgroup-config." X-Git-Tag: release/lithium~807 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=0230f37066dfd974accaf36bc712d6f1e60637d0;hp=486da3c113fc33ef62a46589a4041c3ddcb42b9a Merge "Fix checkstyle warnings in netty-threadgroup-config." --- diff --git a/features/extras/pom.xml b/features/extras/pom.xml new file mode 100644 index 0000000000..20089c726a --- /dev/null +++ b/features/extras/pom.xml @@ -0,0 +1,116 @@ + + + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.5.0-SNAPSHOT + ../../opendaylight/commons/opendaylight + + features-extras + org.opendaylight.controller + jar + + features.xml + + 1.1.0-SNAPSHOT + 1.5.0-SNAPSHOT + 3.0.1 + 0.7.0-SNAPSHOT + 1.5.0-SNAPSHOT + 2.16 + + + + org.jolokia + jolokia-osgi + ${jolokia.version} + + + org.opendaylight.yangtools + features-test + ${feature.test.version} + test + + + + org.opendaylight.controller + opendaylight-karaf-empty + ${karaf.empty.version} + zip + + + + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-resources-plugin + + + filter + generate-resources + + resources + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + package + + attach-artifact + + + + + ${project.build.directory}/classes/${features.file} + xml + features + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${surefire.version} + + + org.opendaylight.controller + opendaylight-karaf-empty + ${karaf.empty.version} + + + org.opendaylight.yangtools:features-test + + + + + + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + HEAD + https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=summary + + diff --git a/features/extras/src/main/resources/features.xml b/features/extras/src/main/resources/features.xml new file mode 100644 index 0000000000..e7423ea17e --- /dev/null +++ b/features/extras/src/main/resources/features.xml @@ -0,0 +1,25 @@ + + + + + + + + odl-jolokia + + + http + mvn:org.jolokia/jolokia-osgi/${jolokia.version} + + diff --git a/features/flow/pom.xml b/features/flow/pom.xml index ab30b0b61f..53b45d2810 100644 --- a/features/flow/pom.xml +++ b/features/flow/pom.xml @@ -23,6 +23,15 @@ features xml + + + org.opendaylight.controller.md + statistics-manager-config + ${mdsal.version} + xml + config + + org.opendaylight.controller.model model-flow-base diff --git a/features/flow/src/main/resources/features.xml b/features/flow/src/main/resources/features.xml index 0540458630..cf54e8b446 100644 --- a/features/flow/src/main/resources/features.xml +++ b/features/flow/src/main/resources/features.xml @@ -21,6 +21,7 @@ mvn:org.opendaylight.controller.md/inventory-manager/${project.version} mvn:org.opendaylight.controller.md/forwardingrules-manager/${project.version} mvn:org.opendaylight.controller/liblldp/${sal.version} + mvn:org.opendaylight.controller.md/statistics-manager-config/${mdsal.version}/xml/config diff --git a/features/pom.xml b/features/pom.xml index ba938c6a6f..8be9f552f8 100644 --- a/features/pom.xml +++ b/features/pom.xml @@ -23,5 +23,6 @@ akka netconf-connector restconf + extras - \ No newline at end of file + diff --git a/opendaylight/commons/opendaylight/pom.xml b/opendaylight/commons/opendaylight/pom.xml index b2585adb04..1030be5699 100644 --- a/opendaylight/commons/opendaylight/pom.xml +++ b/opendaylight/commons/opendaylight/pom.xml @@ -87,6 +87,7 @@ 0.1.0-SNAPSHOT 0.5.0-SNAPSHOT 1.2.0-SNAPSHOT + 30-statistics-manager.xml 2.5.0 3.8.0.I20120518-2145 diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyModuleTest.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyModuleTest.java index 1148c6bebe..77589ed81d 100644 --- a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyModuleTest.java +++ b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyModuleTest.java @@ -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)); diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java index cfdf3bff28..7e3ed5b2de 100644 --- a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java +++ b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java @@ -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)); diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java index 1c068a98e7..ec8a9d6f29 100644 --- a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java +++ b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java @@ -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); diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.java index 598e6bffee..fd8c8d1df0 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.java @@ -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()); diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/test/TwoInterfacesExportTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/test/TwoInterfacesExportTest.java index fcefd06e4d..0e6a54fdc9 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/test/TwoInterfacesExportTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/test/TwoInterfacesExportTest.java @@ -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)); diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/test/SimpleConfigurationTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/test/SimpleConfigurationTest.java index 4ed10036f7..c20d3bfc04 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/test/SimpleConfigurationTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/test/SimpleConfigurationTest.java @@ -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); } } diff --git a/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java b/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java index 41a773a0d5..8fe3d7c24c 100644 --- a/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java +++ b/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java @@ -78,7 +78,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; } diff --git a/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/ImmediateEventExecutorModuleTest.java b/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/ImmediateEventExecutorModuleTest.java index 54c87604a4..d280bcac58 100644 --- a/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/ImmediateEventExecutorModuleTest.java +++ b/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/ImmediateEventExecutorModuleTest.java @@ -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; } diff --git a/opendaylight/distribution/opendaylight-karaf/pom.xml b/opendaylight/distribution/opendaylight-karaf/pom.xml index e44b569759..f4ca2217ce 100644 --- a/opendaylight/distribution/opendaylight-karaf/pom.xml +++ b/opendaylight/distribution/opendaylight-karaf/pom.xml @@ -82,6 +82,14 @@ xml runtime + + org.opendaylight.controller + features-extras + ${project.version} + features + xml + runtime + org.opendaylight.controller features-flow diff --git a/opendaylight/md-sal/pom.xml b/opendaylight/md-sal/pom.xml index 38756f2906..d21f16c478 100644 --- a/opendaylight/md-sal/pom.xml +++ b/opendaylight/md-sal/pom.xml @@ -51,6 +51,7 @@ inventory-manager statistics-manager + statistics-manager-config topology-manager forwardingrules-manager topology-lldp-discovery diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleActor.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleActor.java index 6dfa4afd6b..6c65021d86 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleActor.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleActor.java @@ -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 state = new HashMap<>(); + private final Map state = new HashMap(); private final DataPersistenceProvider dataPersistenceProvider; private long persistIdentifier = 1; + private Optional roleChangeNotifier; - public ExampleActor(final String id, final Map peerAddresses, - final Optional configParams) { + public ExampleActor(String id, Map peerAddresses, + Optional configParams) { super(id, peerAddresses, configParams); this.dataPersistenceProvider = new PersistentDataProvider(); + roleChangeNotifier = createRoleChangeNotifier(id); } public static Props props(final String id, final Map peerAddresses, final Optional configParams){ return Props.create(new Creator(){ - 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 createRoleChangeNotifier(String actorId) { + ActorRef exampleRoleChangeNotifier = this.getContext().actorOf( + RoleChangeNotifier.getProps(actorId), actorId + "-notifier"); + return Optional.of(exampleRoleChangeNotifier); + } + + @Override + protected Optional 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) 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 index 0000000000..c0ee095367 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleRoleChangeListener.java @@ -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 + *

+ * The Role Change listener receives a SetNotifiers message with the notifiers to register itself with. + *

+ * It kicks of a scheduler which sents registration messages to the notifiers, till it gets a RegisterRoleChangeListenerReply + *

+ * 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 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() { + @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 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(); + } +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/TestDriver.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/TestDriver.java index de6169791e..cd2e4a506c 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/TestDriver.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/TestDriver.java @@ -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 allPeers = new HashMap<>(); private static Map clientActorRefs = new HashMap(); private static Map actorRefs = new HashMap(); @@ -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 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 diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/KeyValue.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/KeyValue.java index e0873cc7ba..d2862c2baf 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/KeyValue.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/KeyValue.java @@ -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 index 0000000000..4507f43b8f --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/RegisterListener.java @@ -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 index 0000000000..8adc0dac13 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/SetNotifiers.java @@ -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 notifierList; + + public SetNotifiers(List notifierList) { + this.notifierList = notifierList; + } + + public List getNotifierList() { + return notifierList; + } +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImpl.java index a2c9d660ad..653520c2e4 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImpl.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImpl.java @@ -26,6 +26,7 @@ public abstract class AbstractReplicatedLogImpl implements ReplicatedLog { protected ArrayList snapshottedJournal; protected long previousSnapshotIndex = -1; protected long previousSnapshotTerm = -1; + protected int dataSize = 0; public AbstractReplicatedLogImpl(long snapshotIndex, long snapshotTerm, List unAppliedEntries) { @@ -198,6 +199,7 @@ public abstract class AbstractReplicatedLogImpl implements ReplicatedLog { snapshottedJournal = null; previousSnapshotIndex = -1; previousSnapshotTerm = -1; + dataSize = 0; } @Override diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ConfigParams.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ConfigParams.java index 433c3f7e4b..4245cf10f7 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ConfigParams.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ConfigParams.java @@ -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 diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/DefaultConfigParamsImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/DefaultConfigParamsImpl.java index a2092234d5..3a6bdbf0a3 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/DefaultConfigParamsImpl.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/DefaultConfigParamsImpl.java @@ -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; diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java index 042b9fb569..3b84692077 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java @@ -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 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 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() { @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; } + } diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLog.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLog.java index 7ee85322a6..80b7ad90d0 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLog.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLog.java @@ -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(); } diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogEntry.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogEntry.java index f501c4d37f..1979609736 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogEntry.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogEntry.java @@ -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(); } diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogImplEntry.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogImplEntry.java index ceb5633d4d..986c7f382c 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogImplEntry.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogImplEntry.java @@ -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 + diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractLeader.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractLeader.java index d85ac8ef67..e5c5dc752d 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractLeader.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractLeader.java @@ -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 followerToLog = new HashMap<>(); protected final Map 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; } } diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java index 7ada8b31c5..b1c73f6f41 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java @@ -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 *

@@ -36,7 +36,8 @@ import java.util.ArrayList; * */ 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(), - 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(), + 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 index 0000000000..26fbde0711 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/SnapshotTracker.java @@ -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 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); + } + } + +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshot.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshot.java index 3c4e8117c7..6337f8f6dc 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshot.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshot.java @@ -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 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 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.absent()); + } + + public String getLeaderId() { return leaderId; } @@ -58,25 +67,38 @@ public class InstallSnapshot extends AbstractRaftRPC { return totalChunks; } - public 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 getLastChunkHashCode() { + return lastChunkHashCode; + } + public 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 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; } diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/resources/application.conf b/opendaylight/md-sal/sal-akka-raft/src/main/resources/application.conf index 9e42a13c6a..b2132b88b0 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/resources/application.conf +++ b/opendaylight/md-sal/sal-akka-raft/src/main/resources/application.conf @@ -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" + } +} + + + diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImplTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImplTest.java index 398a2e9b36..d95c9d5027 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImplTest.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImplTest.java @@ -164,6 +164,11 @@ public class AbstractReplicatedLogImplTest { this.snapshotTerm = snapshotTerm; } + @Override + public int dataSize() { + return -1; + } + public List getEntriesTill(final int index) { return journal.subList(0, index); } diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/MockRaftActorContext.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/MockRaftActorContext.java index 562ca213a9..2424d4d557 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/MockRaftActorContext.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/MockRaftActorContext.java @@ -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 { diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java index 9eb2fb757b..c833a86e9b 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java @@ -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 state; + private ActorRef roleChangeNotifier; public static final class MockRaftActorCreator implements Creator { private static final long serialVersionUID = 1L; @@ -90,25 +93,27 @@ public class RaftActorTest extends AbstractActorTest { private final String id; private final Optional config; private final DataPersistenceProvider dataPersistenceProvider; + private final ActorRef roleChangeNotifier; private MockRaftActorCreator(Map peerAddresses, String id, - Optional config, DataPersistenceProvider dataPersistenceProvider) { + Optional 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 state; - public MockRaftActor(String id, Map peerAddresses, Optional 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 peerAddresses, Optional 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 peerAddresses, Optional 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 peerAddresses, + Optional 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 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 mockActorRef = TestActorRef.create(getSystem(), MockRaftActor.props(id, + Collections.emptyMap(), Optional.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 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; diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/FollowerTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/FollowerTest.java index 83b9ad3ec7..0ee9693d32 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/FollowerTest.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/FollowerTest.java @@ -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.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 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 listMessages = (List) 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); } diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java index 0fc0b4ccfd..895fe35bff 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java @@ -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 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 followerActor = + TestActorRef.create(getSystem(), Props.create(MessageCollectorActor.class), "follower"); + + Map 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 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 followerActor = + TestActorRef.create(getSystem(), Props.create(MessageCollectorActor.class), "follower"); + + Map 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 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 index 0000000000..1b3a8f5fb5 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/SnapshotTrackerTest.java @@ -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 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.absent()); + tracker1.addChunk(2, chunk2, Optional.absent()); + tracker1.addChunk(3, chunk3, Optional.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.absent()); + tracker2.addChunk(2, chunk2, Optional.absent()); + + try { + tracker2.addChunk(3, chunk3, Optional.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.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.absent()); + + try { + tracker4.addChunk(AbstractLeader.FIRST_CHUNK_INDEX+2, chunk2, Optional.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.absent()); + // Look I can add the same chunk again + tracker5.addChunk(AbstractLeader.FIRST_CHUNK_INDEX + 1, chunk1, Optional.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.absent()); + try { + tracker1.getSnapshot(); + Assert.fail(); + } catch(IllegalStateException e){ + + } + + SnapshotTracker tracker2 = new SnapshotTracker(mock(LoggingAdapter.class), 3); + + tracker2.addChunk(1, chunk1, Optional.absent()); + tracker2.addChunk(2, chunk2, Optional.absent()); + tracker2.addChunk(3, chunk3, Optional.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.absent()); + tracker1.addChunk(2, chunk2, Optional.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 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 diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/utils/MessageCollectorActor.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/utils/MessageCollectorActor.java index 9fbdd4587f..3469a956c3 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/utils/MessageCollectorActor.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/utils/MessageCollectorActor.java @@ -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 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 index 0000000000..1faa341d45 --- /dev/null +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RegisterRoleChangeListener.java @@ -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 index 0000000000..f1d13e344f --- /dev/null +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RegisterRoleChangeListenerReply.java @@ -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 index 0000000000..de2733fc86 --- /dev/null +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RoleChangeNotification.java @@ -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 index 0000000000..a9aa56174d --- /dev/null +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RoleChangeNotifier.java @@ -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. + *

+ * The RoleChangeNotifier is instantiated by the Shard and injected into the RaftActor. + */ +public class RoleChangeNotifier extends AbstractUntypedActor implements AutoCloseable { + + private String memberId; + private Map 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() { + @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 index 0000000000..f315bfdf7a --- /dev/null +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/notifications/RoleChanged.java @@ -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; + } +} diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/raft/protobuff/client/messages/CompositeModificationPayload.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/raft/protobuff/client/messages/CompositeModificationPayload.java index aadc3625cc..075c6075a8 100644 --- a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/raft/protobuff/client/messages/CompositeModificationPayload.java +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/raft/protobuff/client/messages/CompositeModificationPayload.java @@ -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(); + } } diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/raft/protobuff/client/messages/Payload.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/raft/protobuff/client/messages/Payload.java index 502c338f22..7df5308294 100644 --- a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/raft/protobuff/client/messages/Payload.java +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/raft/protobuff/client/messages/Payload.java @@ -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(); + } diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/cluster/raft/InstallSnapshotMessages.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/cluster/raft/InstallSnapshotMessages.java index b93be3e009..de7f44e213 100644 --- a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/cluster/raft/InstallSnapshotMessages.java +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/cluster/raft/InstallSnapshotMessages.java @@ -85,6 +85,16 @@ public final class InstallSnapshotMessages { * optional int32 totalChunks = 7; */ int getTotalChunks(); + + // optional int32 lastChunkHashCode = 8; + /** + * optional int32 lastChunkHashCode = 8; + */ + boolean hasLastChunkHashCode(); + /** + * optional int32 lastChunkHashCode = 8; + */ + 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_; + /** + * optional int32 lastChunkHashCode = 8; + */ + public boolean hasLastChunkHashCode() { + return ((bitField0_ & 0x00000080) == 0x00000080); + } + /** + * optional int32 lastChunkHashCode = 8; + */ + 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_ ; + /** + * optional int32 lastChunkHashCode = 8; + */ + public boolean hasLastChunkHashCode() { + return ((bitField0_ & 0x00000080) == 0x00000080); + } + /** + * optional int32 lastChunkHashCode = 8; + */ + public int getLastChunkHashCode() { + return lastChunkHashCode_; + } + /** + * optional int32 lastChunkHashCode = 8; + */ + public Builder setLastChunkHashCode(int value) { + bitField0_ |= 0x00000080; + lastChunkHashCode_ = value; + onChanged(); + return this; + } + /** + * optional int32 lastChunkHashCode = 8; + */ + 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; } }; diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/resources/InstallSnapshot.proto b/opendaylight/md-sal/sal-clustering-commons/src/main/resources/InstallSnapshot.proto index 4198644b13..adb58ae4af 100644 --- a/opendaylight/md-sal/sal-clustering-commons/src/main/resources/InstallSnapshot.proto +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/resources/InstallSnapshot.proto @@ -12,4 +12,5 @@ message InstallSnapshot { optional bytes data = 5; optional int32 chunkIndex = 6; optional int32 totalChunks = 7; + optional int32 lastChunkHashCode = 8; } diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/TestModel.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/TestModel.java index 99df01a32e..d3abd38153 100644 --- a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/TestModel.java +++ b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/TestModel.java @@ -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 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() { diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DatastoreContext.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DatastoreContext.java index e18c00ec4b..daba3fdf8a 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DatastoreContext.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DatastoreContext.java @@ -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)); diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java index d53cb48e50..af16d02eea 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java @@ -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 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 mapPeerAddresses( @@ -196,6 +202,12 @@ public class Shard extends RaftActor { return Props.create(new ShardCreator(name, peerAddresses, datastoreContext, schemaContext)); } + private Optional createRoleChangeNotifier(String shardId) { + ActorRef shardRoleChangeNotifier = this.getContext().actorOf( + RoleChangeNotifier.getProps(shardId), shardId + "-notifier"); + return Optional.of(shardRoleChangeNotifier); + } + @Override public void postStop() { super.postStop(); @@ -259,6 +271,11 @@ public class Shard extends RaftActor { } } + @Override + protected Optional 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 diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStats.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStats.java index 9decd82822..4fc2ed2d06 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStats.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStats.java @@ -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 diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStatsMXBean.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStatsMXBean.java index 8deb0ae6db..8174727788 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStatsMXBean.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStatsMXBean.java @@ -51,4 +51,6 @@ public interface ShardStatsMXBean { int getMaxNotificationMgrListenerQueueSize(); void resetTransactionCounters(); + + long getDataSize(); } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/yang/distributed-datastore-provider.yang b/opendaylight/md-sal/sal-distributed-datastore/src/main/yang/distributed-datastore-provider.yang index 4d3d438b32..367d4f45e2 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/yang/distributed-datastore-provider.yang +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/yang/distributed-datastore-provider.yang @@ -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; diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/CompositeModificationPayloadTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/CompositeModificationPayloadTest.java index 04d889fbe0..9e02223f54 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/CompositeModificationPayloadTest.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/CompositeModificationPayloadTest.java @@ -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 index 0000000000..4e61260550 --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/RoleChangeNotifierTest.java @@ -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 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 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()); + + }}; + + } +} + + diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/MessageCollectorActor.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/MessageCollectorActor.java index f75aa5445b..4bd0ad818f 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/MessageCollectorActor.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/MessageCollectorActor.java @@ -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 getAllMessages(ActorRef actor) throws Exception { + FiniteDuration operationDuration = Duration.create(5, TimeUnit.SECONDS); + Timeout operationTimeout = new Timeout(operationDuration); + Future future = Patterns.ask(actor, "messages", operationTimeout); + + try { + return (List) 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 allMessages = getAllMessages(actor); + + for(Object message : allMessages){ + if(message.getClass().equals(clazz)){ + return message; + } + } + + return null; + } + + public static List getAllMatching(ActorRef actor, Class clazz) throws Exception { + List allMessages = getAllMessages(actor); + + List output = Lists.newArrayList(); + + for(Object message : allMessages){ + if(message.getClass().equals(clazz)){ + output.add(message); + } + } + + return output; + } + } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/programs/appendentries/Client.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/programs/appendentries/Client.java index a2b78c6c15..a3041e89db 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/programs/appendentries/Client.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/programs/appendentries/Client.java @@ -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); diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/BucketStore.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/BucketStore.java index b50dfb1ba3..6ffe147e71 100644 --- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/BucketStore.java +++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/BucketStore.java @@ -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 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 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 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() ) { diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistryTest.java b/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistryTest.java index ee96cb897f..e0d145dbe1 100644 --- a/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistryTest.java +++ b/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistryTest.java @@ -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() { - @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() { + @Override + public boolean apply(@Nullable Object input) { + if (input != null) { + return clazz.equals(input.getClass()); + } else { + return false; + } + } + }); - private List> createRouteIds() throws URISyntaxException { - QName type = new QName(new URI("/mockrpc"), "mockrpc"); - List> 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 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> createRouteIds() throws URISyntaxException { + QName type = new QName(new URI("/mockrpc"), "mockrpc"); + List> 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 index 0000000000..f4b5f7671b --- /dev/null +++ b/opendaylight/md-sal/statistics-manager-config/pom.xml @@ -0,0 +1,49 @@ + + + + + 4.0.0 + + org.opendaylight.controller + sal-parent + 1.2.0-SNAPSHOT + + + org.opendaylight.controller.md + statistics-manager-config + Configuration files for statistics manager + jar + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + + attach-artifact + + package + + + + ${project.build.directory}/classes/initial/30-statistics-manager.xml + xml + config + + + + + + + + + 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 index 0000000000..797c14e8e4 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager-config/src/main/resources/initial/30-statistics-manager.xml @@ -0,0 +1,52 @@ + + + + + + + + + + statsmanager:statistics-manager + + statistics-manager + + + binding:binding-rpc-registry + binding-rpc-broker + + + + binding:binding-async-data-broker + binding-data-broker + + + + + binding:binding-notification-service + + binding-notification-broker + + + + 3000 + 16 + + + + + + + + + urn:opendaylight:params:xml:ns:yang:controller:md:sal:statistics-manager?module=statistics-manager&revision=2014-09-25 + + + + diff --git a/opendaylight/md-sal/statistics-manager/pom.xml b/opendaylight/md-sal/statistics-manager/pom.xml index eb6c51b351..234e1084f6 100644 --- a/opendaylight/md-sal/statistics-manager/pom.xml +++ b/opendaylight/md-sal/statistics-manager/pom.xml @@ -42,6 +42,14 @@ org.osgi.core provided + + org.opendaylight.controller + sal-binding-config + + + org.opendaylight.controller + config-api + org.slf4j slf4j-log4j12 @@ -51,15 +59,43 @@ - - org.apache.felix - maven-bundle-plugin - - - org.opendaylight.controller.md.statistics.manager.StatisticsManagerActivator - - - + + org.apache.felix + maven-bundle-plugin + + + * + + + + + org.opendaylight.yangtools + yang-maven-plugin + + + config + + generate-sources + + + + + org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + ${jmxGeneratorPath} + + urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang + + + + org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl + ${salGeneratorPath} + + + true + + + + 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 index 0000000000..fb920a6692 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/config/yang/md/sal/statistics_manager/StatisticsManagerModule.java @@ -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 index 0000000000..dc374477d1 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/config/yang/md/sal/statistics_manager/StatisticsManagerModuleFactory.java @@ -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 { + +} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManager.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManager.java index 7d57067df1..831dc224d1 100644 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManager.java +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManager.java @@ -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 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 index c505af49e6..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerActivator.java +++ /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."); - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitQueue.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitQueue.java index 07e167d1e4..f5c5689b7b 100644 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitQueue.java +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatListenCommitQueue.java @@ -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 queueStatIdent = nodeIdent + final InstanceIdentifier 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 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 index 0000000000..0f56ea98f0 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatisticsManagerConfig.java @@ -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); + } + } +} diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatisticsManagerImpl.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatisticsManagerImpl.java index 396ff0e1f6..edf9fad433 100644 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatisticsManagerImpl.java +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/impl/StatisticsManagerImpl.java @@ -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 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 tableNotifCommiter; private StatNotifyCommiter 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 statCollectorsNew = new ArrayList<>(statCollectors); newCollector.connectedNodeRegistration(nodeIdent, statTypes, nrOfSwitchTables); statCollectorsNew.add(newCollector); @@ -355,5 +354,10 @@ public class StatisticsManagerImpl implements StatisticsManager, Runnable { public StatNotifyCommiter 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 index 0000000000..5f35f70d01 --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/main/yang/statistics-manager.yang @@ -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 index 6a01cd2c26..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerProvider.java +++ /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 Vaclav Demcak - * - * 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 index 7fc171c49b..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/FlowStatisticsTest.java +++ /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 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 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.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 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 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
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.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 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
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
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, 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 index 7a61bf280f..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/GroupStatisticsTest.java +++ /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 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 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 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 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 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 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 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, 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 index a0f360c475..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/MeterStatisticsTest.java +++ /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 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 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 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 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 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 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 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 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, DataObject> change) { - synchronized (waitObject) { - waitObject.notify(); - } - } - } -} - diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/NodeRegistrationTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/NodeRegistrationTest.java index 18bd2d42ef..79eb236089 100644 --- a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/NodeRegistrationTest.java +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/NodeRegistrationTest.java @@ -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 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 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 index 9f193b03d7..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/PortStatisticsTest.java +++ /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 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 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, 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 index bb9bd21134..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/QueueStatisticsTest.java +++ /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.emptyList()); - ncBuilder.setKey(new NodeConnectorKey(new NodeConnectorId("connector.1"))); - ncBuilder.addAugmentation(FlowCapableNodeConnector.class, fcncBuilder.build()); - - - final Queue queue = getQueue(); - final InstanceIdentifier queueII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) - .child(NodeConnector.class, ncBuilder.getKey()).augmentation(FlowCapableNodeConnector.class) - .child(Queue.class, queue.getKey()); - final InstanceIdentifier 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 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.emptyList()); - ncBuilder.setKey(new NodeConnectorKey(new NodeConnectorId("connector.1"))); - ncBuilder.addAugmentation(FlowCapableNodeConnector.class, fcncBuilder.build()); - - - final Queue queue = getQueue(); - final InstanceIdentifier queueII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) - .child(NodeConnector.class, ncBuilder.getKey()).augmentation(FlowCapableNodeConnector.class) - .child(Queue.class, queue.getKey()); - final InstanceIdentifier 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 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 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 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 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, 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 index 0000000000..48a993e6bd --- /dev/null +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/StatCollectorTest.java @@ -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
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
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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
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 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, 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 index f0c0fedb70..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/TableStatisticsTest.java +++ /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
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 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, DataObject> change) { - synchronized (waitObject) { - waitObject.notify(); - } - } - } -} - diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightFlowStatisticsServiceMock.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightFlowStatisticsServiceMock.java index 2628bb9f41..f483881975 100644 --- a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightFlowStatisticsServiceMock.java +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightFlowStatisticsServiceMock.java @@ -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> 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> 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> 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> 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 flowAndStatisticsMapLists = new ArrayList<>(); FlowsStatisticsUpdateBuilder flowsStatisticsUpdateBuilder = new FlowsStatisticsUpdateBuilder(); @@ -95,7 +92,7 @@ public class OpendaylightFlowStatisticsServiceMock implements OpendaylightFlowSt @Override public Future> 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 flowAndStatisticsMapLists = new ArrayList<>(); FlowsStatisticsUpdateBuilder flowsStatisticsUpdateBuilder = new FlowsStatisticsUpdateBuilder(); diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightFlowTableStatisticsServiceMock.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightFlowTableStatisticsServiceMock.java index 42be70892c..ea9f40390f 100644 --- a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightFlowTableStatisticsServiceMock.java +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightFlowTableStatisticsServiceMock.java @@ -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> 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(); diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightGroupStatisticsServiceMock.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightGroupStatisticsServiceMock.java index 7e7342f609..4b9c047d84 100644 --- a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightGroupStatisticsServiceMock.java +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightGroupStatisticsServiceMock.java @@ -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> 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 = new ArrayList<>(); GroupStatsBuilder gsBuilder = new GroupStatsBuilder(); @@ -66,7 +63,7 @@ public class OpendaylightGroupStatisticsServiceMock implements OpendaylightGroup @Override public Future> 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 = new ArrayList<>(); GroupDescStatsUpdatedBuilder gdsuBuilder = new GroupDescStatsUpdatedBuilder(); @@ -89,7 +86,7 @@ public class OpendaylightGroupStatisticsServiceMock implements OpendaylightGroup @Override public Future> 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> 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 = new ArrayList<>(); diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightMeterStatisticsServiceMock.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightMeterStatisticsServiceMock.java index 2d65d1ebed..d5f0ce5995 100644 --- a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightMeterStatisticsServiceMock.java +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightMeterStatisticsServiceMock.java @@ -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> 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 = new ArrayList<>(); MeterConfigStatsBuilder mcsBuilder = new MeterConfigStatsBuilder(); @@ -66,7 +63,7 @@ public class OpendaylightMeterStatisticsServiceMock implements OpendaylightMeter @Override public Future> 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> 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> 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())); diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightPortStatisticsServiceMock.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightPortStatisticsServiceMock.java index 7164c56c1b..c3d13f4c24 100644 --- a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightPortStatisticsServiceMock.java +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightPortStatisticsServiceMock.java @@ -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> 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> 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()); } diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightQueueStatisticsServiceMock.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightQueueStatisticsServiceMock.java index 4f6806b8ca..8908dd5c0e 100644 --- a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightQueueStatisticsServiceMock.java +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/OpendaylightQueueStatisticsServiceMock.java @@ -38,7 +38,7 @@ public class OpendaylightQueueStatisticsServiceMock implements OpendaylightQueue @Override public Future> 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> 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> 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 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 index 9b40a7684f..0000000000 --- a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/ProviderContextMock.java +++ /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 getSALService(Class service) { - if (service.equals(DataBroker.class)) { - return (T) dataBroker; - } - else if (service.equals(NotificationProviderService.class)) { - return (T) notificationProviderService; - } - return null; - } - - @Override - public BindingAwareBroker.RpcRegistration addRpcImplementation(Class serviceInterface, T implementation) throws IllegalStateException { - return null; - } - - @Override - public BindingAwareBroker.RoutedRpcRegistration addRoutedRpcImplementation(Class serviceInterface, T implementation) throws IllegalStateException { - return null; - } - - @Override - public >> ListenerRegistration registerRouteChangeListener(L listener) { - return null; - } - - @Override - public T getRpcService(Class serviceInterface) { - return rpcProviderMock.getRpcService(serviceInterface); - } -} diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/StatisticsManagerTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/StatisticsManagerTest.java index 7f266d9c3c..45765edd0e 100644 --- a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/StatisticsManagerTest.java +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/StatisticsManagerTest.java @@ -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; } diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/TestUtils.java b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/TestUtils.java index e38a25e8e9..d18dc23ad4 100644 --- a/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/TestUtils.java +++ b/opendaylight/md-sal/statistics-manager/src/test/java/test/mock/util/TestUtils.java @@ -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(); + } } diff --git a/opendaylight/netconf/netconf-tcp/src/main/java/org/opendaylight/controller/netconf/tcp/netty/ProxyServerHandler.java b/opendaylight/netconf/netconf-tcp/src/main/java/org/opendaylight/controller/netconf/tcp/netty/ProxyServerHandler.java index fa8892853b..21ec8e82d6 100644 --- a/opendaylight/netconf/netconf-tcp/src/main/java/org/opendaylight/controller/netconf/tcp/netty/ProxyServerHandler.java +++ b/opendaylight/netconf/netconf-tcp/src/main/java/org/opendaylight/controller/netconf/tcp/netty/ProxyServerHandler.java @@ -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(); } diff --git a/opendaylight/netconf/netconf-tcp/src/main/java/org/opendaylight/controller/netconf/tcp/osgi/NetconfTCPActivator.java b/opendaylight/netconf/netconf-tcp/src/main/java/org/opendaylight/controller/netconf/tcp/osgi/NetconfTCPActivator.java index bc94e596d7..355041f8df 100644 --- a/opendaylight/netconf/netconf-tcp/src/main/java/org/opendaylight/controller/netconf/tcp/osgi/NetconfTCPActivator.java +++ b/opendaylight/netconf/netconf-tcp/src/main/java/org/opendaylight/controller/netconf/tcp/osgi/NetconfTCPActivator.java @@ -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 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()); } diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/Main.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/Main.java index e36d58591e..e441c709cc 100644 --- a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/Main.java +++ b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/Main.java @@ -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 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 generated = configGenerator.generate(params.ssh, params.generateConfigBatchSize, params.generateConfigsTimeout, params.generateConfigsAddress); diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java index adcdea6073..c6cad90355 100644 --- a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java +++ b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java @@ -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); } diff --git a/opendaylight/netconf/netconf-usermanager/src/main/java/org/opendaylight/controller/netconf/auth/usermanager/AuthProviderImpl.java b/opendaylight/netconf/netconf-usermanager/src/main/java/org/opendaylight/controller/netconf/auth/usermanager/AuthProviderImpl.java index da5e2090ff..cb5874ab24 100644 --- a/opendaylight/netconf/netconf-usermanager/src/main/java/org/opendaylight/controller/netconf/auth/usermanager/AuthProviderImpl.java +++ b/opendaylight/netconf/netconf-usermanager/src/main/java/org/opendaylight/controller/netconf/auth/usermanager/AuthProviderImpl.java @@ -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 customizer = new ServiceTrackerCustomizer() { @Override public IUserManager addingService(final ServiceReference reference) { - logger.trace("UerManager {} added", reference); + LOG.trace("UerManager {} added", reference); nullableUserManager = bundleContext.getService(reference); return nullableUserManager; } @Override public void modifiedService(final ServiceReference reference, final IUserManager service) { - logger.trace("Replacing modified UerManager {}", reference); + LOG.trace("Replacing modified UerManager {}", reference); nullableUserManager = service; } @Override public void removedService(final ServiceReference 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); } diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/NetconfUtil.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/NetconfUtil.java index 0269bcccb9..5fd53dce55 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/NetconfUtil.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/NetconfUtil.java @@ -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)); } diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/MissingNameSpaceException.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/MissingNameSpaceException.java index 6cc5006aba..d2a6d2b58d 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/MissingNameSpaceException.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/MissingNameSpaceException.java @@ -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 { diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/UnexpectedElementException.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/UnexpectedElementException.java index 7b5f52e396..6d7c7ca7c4 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/UnexpectedElementException.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/UnexpectedElementException.java @@ -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 { diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/UnexpectedNamespaceException.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/UnexpectedNamespaceException.java index 582fd23e16..4a19390b36 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/UnexpectedNamespaceException.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/exception/UnexpectedNamespaceException.java @@ -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 { diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessage.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessage.java index 15223cb60b..5cd17a2331 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessage.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessage.java @@ -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} */ diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessageAdditionalHeader.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessageAdditionalHeader.java index d1e064eaeb..e50928d7bf 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessageAdditionalHeader.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessageAdditionalHeader.java @@ -9,7 +9,6 @@ package org.opendaylight.controller.netconf.util.messages; import com.google.common.base.Preconditions; - import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageHeader.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageHeader.java index fa26455c98..ac8a557d9a 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageHeader.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageHeader.java @@ -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 diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtil.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtil.java index c532b7f9a6..61b23202c3 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtil.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtil.java @@ -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; } } diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/SendErrorExceptionUtil.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/SendErrorExceptionUtil.java index 6604834fe4..fe5ed03320 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/SendErrorExceptionUtil.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/SendErrorExceptionUtil.java @@ -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); } } diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtil.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtil.java index c77e0d7da2..64aeebd542 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtil.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtil.java @@ -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); } } diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/HardcodedNamespaceResolver.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/HardcodedNamespaceResolver.java index 23fe7cdf41..87ecb2de09 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/HardcodedNamespaceResolver.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/HardcodedNamespaceResolver.java @@ -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 prefixesToNamespaces; diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XMLNetconfUtil.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XMLNetconfUtil.java index e7ce454155..eaaf320b02 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XMLNetconfUtil.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XMLNetconfUtil.java @@ -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 { diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java index 3c63204881..e17cad977c 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java @@ -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('}'); diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfValidator.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfValidator.java index 8108c8e740..bdab8c6209 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfValidator.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfValidator.java @@ -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; diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java index 9e227ee05d..68c4d9fdab 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java @@ -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.absent()); + return createTextElementWithNamespacedContent(document, qName, prefix, namespace, contentWithoutPrefix, Optional.absent()); } public static Element createTextElementWithNamespacedContent(Document document, String qName, String prefix, diff --git a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/NetconfUtilTest.java b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/NetconfUtilTest.java index 47d0d4c7cc..dc175c5733 100644 --- a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/NetconfUtilTest.java +++ b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/NetconfUtilTest.java @@ -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; diff --git a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/mapping/AbstractLastNetconfOperationTest.java b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/mapping/AbstractLastNetconfOperationTest.java index 62633dd3f2..a6d1d5b999 100644 --- a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/mapping/AbstractLastNetconfOperationTest.java +++ b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/mapping/AbstractLastNetconfOperationTest.java @@ -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 { diff --git a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperationTest.java b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperationTest.java index ea4a6e61f2..c7f6321e2c 100644 --- a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperationTest.java +++ b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperationTest.java @@ -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 { diff --git a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/mapping/AbstractSingletonNetconfOperationTest.java b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/mapping/AbstractSingletonNetconfOperationTest.java index d1310de3e2..911b73f097 100644 --- a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/mapping/AbstractSingletonNetconfOperationTest.java +++ b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/mapping/AbstractSingletonNetconfOperationTest.java @@ -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 { diff --git a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessageAdditionalHeaderTest.java b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessageAdditionalHeaderTest.java index 95c91243af..5e50eb93fb 100644 --- a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessageAdditionalHeaderTest.java +++ b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessageAdditionalHeaderTest.java @@ -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 { diff --git a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessageTest.java b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessageTest.java index 5a9d07f6b1..4e157186ff 100644 --- a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessageTest.java +++ b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessageTest.java @@ -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; diff --git a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageHeaderTest.java b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageHeaderTest.java index d5ff3380d2..05c31be395 100644 --- a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageHeaderTest.java +++ b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageHeaderTest.java @@ -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; diff --git a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtilTest.java b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtilTest.java index 2af34e957e..12769f5ed3 100644 --- a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtilTest.java +++ b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtilTest.java @@ -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 { diff --git a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/SendErrorExceptionUtilTest.java b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/SendErrorExceptionUtilTest.java index c8d562cb9c..20287741b9 100644 --- a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/SendErrorExceptionUtilTest.java +++ b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/SendErrorExceptionUtilTest.java @@ -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; diff --git a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtilTest.java b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtilTest.java index ebee41145a..1a701057aa 100644 --- a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtilTest.java +++ b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtilTest.java @@ -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; diff --git a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/XmlFileLoader.java b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/XmlFileLoader.java index 457dda3080..e1331b1380 100644 --- a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/XmlFileLoader.java +++ b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/XmlFileLoader.java @@ -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, diff --git a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/xml/XmlElementTest.java b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/xml/XmlElementTest.java index a88de956e2..22210a394e 100644 --- a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/xml/XmlElementTest.java +++ b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/xml/XmlElementTest.java @@ -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 = "" + diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/startExi.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/startExi.xml index 5e94ac6110..0af445f17d 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/startExi.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/startExi.xml @@ -6,4 +6,4 @@ - + \ No newline at end of file diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/stopExi.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/stopExi.xml index 170c753993..7f1fe849e8 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/stopExi.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/stopExi.xml @@ -1,3 +1,3 @@ - + \ No newline at end of file