Merge "Bug 2731: Discard changes only when transaction exist."
authorTony Tkacik <ttkacik@cisco.com>
Tue, 24 Feb 2015 09:39:34 +0000 (09:39 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 24 Feb 2015 09:39:34 +0000 (09:39 +0000)
239 files changed:
features/akka/pom.xml
features/config-netty/pom.xml
features/config-persister/pom.xml
features/config/pom.xml
features/extras/pom.xml
features/flow/pom.xml
features/mdsal/pom.xml
features/mdsal/src/main/resources/features.xml
features/netconf-connector/pom.xml
features/netconf-connector/src/main/resources/features.xml
features/netconf/pom.xml
features/netconf/src/main/resources/features.xml
features/protocol-framework/pom.xml
features/restconf/pom.xml
opendaylight/archetypes/opendaylight-startup/src/main/resources/META-INF/maven/archetype-metadata.xml
opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/api/.gitignore [moved from opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/__artifactId__-api/.gitignore with 100% similarity]
opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/api/pom.xml [moved from opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/__artifactId__-api/pom.xml with 100% similarity]
opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/api/src/main/yang/__artifactId__.yang [moved from opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/__artifactId__-api/src/main/yang/__artifactId__.yang with 100% similarity]
opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/artifacts/pom.xml [moved from opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/__artifactId__-artifacts/pom.xml with 100% similarity]
opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/features/pom.xml [moved from opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/__artifactId__-features/pom.xml with 97% similarity]
opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/features/src/main/features/features.xml [moved from opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/__artifactId__-features/src/main/features/features.xml with 78% similarity]
opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/impl/pom.xml [moved from opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/__artifactId__-impl/pom.xml with 80% similarity]
opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/impl/src/main/config/default-config.xml [moved from opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/__artifactId__-impl/src/main/config/default-config.xml with 96% similarity]
opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/impl/src/main/java/__packageInPathFormat__/impl/__classPrefix__Provider.java [moved from opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/__artifactId__-impl/src/main/java/__packageInPathFormat__/__classPrefix__Provider.java with 97% similarity]
opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/__artifactId__/impl/rev141210/__classPrefix__Module.java [moved from opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/__artifactId__-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/__artifactId__/impl/rev141210/__classPrefix__ImplModule.java with 55% similarity]
opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/__artifactId__/impl/rev141210/__classPrefix__ModuleFactory.java [moved from opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/__artifactId__-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/__artifactId__/impl/rev141210/__classPrefix__ImplModuleFactory.java with 80% similarity]
opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/impl/src/main/yang/__artifactId__-impl.yang [moved from opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/__artifactId__-impl/src/main/yang/__artifactId__-impl.yang with 87% similarity]
opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/impl/src/test/java/__packageInPathFormat__/impl/__classPrefix__ProviderTest.java [new file with mode: 0644]
opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/impl/src/test/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/__artifactId__/impl/rev141210/__classPrefix__ModuleFactoryTest.java [new file with mode: 0644]
opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/impl/src/test/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/__artifactId__/impl/rev141210/__classPrefix__ModuleTest.java [new file with mode: 0644]
opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/karaf/pom.xml [moved from opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/__artifactId__-karaf/pom.xml with 77% similarity]
opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/pom.xml
opendaylight/commons/opendaylight/pom.xml
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ConfigRegistry.java
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/LookupRegistry.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionLookupRegistry.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImpl.java
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/BeanReader.java [new file with mode: 0644]
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigRegistryClient.java
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigRegistryJMXClient.java
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionClient.java
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java
opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigTransactionController.java
opendaylight/config/yang-jmx-generator-plugin/pom.xml
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGenerator.java
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/TemplateFactory.java
opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java
opendaylight/md-sal/messagebus-impl/pom.xml
opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/Topic.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImpl.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ConfigParams.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/DefaultConfigParamsImpl.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImpl.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ApplyState.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractLeader.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Leader.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshot.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/MockRaftActorContext.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/TestActorFactory.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractLeaderTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehaviorTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/CandidateTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/FollowerTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/IsolatedLeaderTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/utils/ForwardMessageToBehaviorActor.java [new file with mode: 0644]
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/utils/MessageCollectorActor.java
opendaylight/md-sal/sal-akka-raft/src/test/resources/simplelogger.properties
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataObjectModification.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataTreeChangeListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataTreeChangeService.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataTreeIdentifier.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataTreeModification.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-dom-it/pom.xml
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/ConcurrentImplicitCreateTest.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/WildcardedDataChangeListenerTest.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DeleteNestedAugmentationListenParentTest.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/FlagsSerializationTest.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/PutAugmentationTest.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentListenAugmentTest.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentReadChildTest.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerMountPointTest.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerRpcTest.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/DOMRpcServiceTestBugfix560.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MessageCapturingFlowService.java
opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/akka.conf
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataNormalizer.java
opendaylight/md-sal/sal-common-impl/src/test/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataNormalizerTest.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ConcurrentDOMDataBroker.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerRegistrationProxy.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStore.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohortProxy.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionContextImpl.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionProxy.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/ActorContext.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/Dispatchers.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/MessageTracker.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerRegistrationProxyTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DatastoreContextTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohortProxyTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/TransactionProxyTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/ActorContextTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/DispatchersTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/MessageTrackerTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/resources/application-with-custom-dispatchers.conf [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/pom.xml
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataTreeIdentifier.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataTreeInaccessibleException.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataTreeListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataTreeListeningException.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataTreeLoopException.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataTreeProducer.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataTreeProducerBusyException.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataTreeProducerException.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataTreeProducerFactory.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataTreeService.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataTreeShard.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataTreeShardingConflictException.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataTreeShardingService.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/test/java/org/opendaylight/controller/md/sal/dom/api/AbstractDOMDataTreeServiceTestSuite.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/AbstractDOMForwardedTransactionFactory.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/CommitCoordinationTask.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMDataBrokerTransactionChainImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/SerializedDOMDataBroker.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/ShardRegistration.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/ShardedDOMDataTree.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/ShardedDOMDataTreeProducer.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/ShardedDOMDataWriteTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/ShardingTableEntry.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMBrokerPerformanceTest.java
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMBrokerTest.java
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMTransactionChainTest.java
opendaylight/md-sal/sal-dom-xsql/pom.xml
opendaylight/md-sal/sal-dummy-distributed-datastore/pom.xml
opendaylight/md-sal/sal-dummy-distributed-datastore/src/main/java/org/opendaylight/controller/dummy/datastore/DummyShard.java
opendaylight/md-sal/sal-dummy-distributed-datastore/src/main/resources/simplelogger.properties
opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDataStoreTest.java
opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaUpdateForTransactionTest.java
opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/TestDCLExecutorService.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NotificationHandler.java
opendaylight/md-sal/sal-test-model/src/main/yang/opendaylight-of-migration-test-model.yang [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Datastore.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/RunningDatastoreQueryStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationProvider.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceFactoryImpl.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreService.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusherImpl.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java
opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterTest.java
opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/osgi/MockedBundleContext.java
opendaylight/netconf/ietf-netconf-monitoring/src/main/yang/ietf-netconf-monitoring.yang
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/mapper/NetconfMdsalMapperModule.java
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/CurrentSchemaContext.java
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationService.java
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationServiceFactory.java
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/AbstractGet.java
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/Get.java
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/GetConfig.java
opendaylight/netconf/mdsal-netconf-connector/src/main/yang/netconf-mdsal-mapper.yang
opendaylight/netconf/mdsal-netconf-monitoring/pom.xml [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/monitoring/MonitoringToMdsalWriter.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/monitoring/NetconfMdsalMonitoringMapperModule.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/monitoring/NetconfMdsalMonitoringMapperModuleFactory.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/NetconfMonitoringOperationService.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/NetconfMonitoringOperationServiceFactory.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-monitoring/src/main/yang/netconf-mdsal-monitoring.yang [new file with mode: 0644]
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/Capability.java [moved from opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/Capability.java with 93% similarity]
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/monitoring/CapabilityListener.java [new file with mode: 0644]
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/monitoring/NetconfMonitoringService.java
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/monitoring/SessionListener.java [moved from opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/SessionMonitoringService.java with 59% similarity]
opendaylight/netconf/netconf-api/src/main/yang/netconf-northbound.yang
opendaylight/netconf/netconf-artifacts/pom.xml
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfMapperAggregatorModule.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfMapperAggregatorModuleFactory.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerDispatcherModule.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerMonitoringModule.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerMonitoringModuleFactory.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/CapabilityProviderImpl.java [deleted file]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSession.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java [deleted file]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/CapabilityProvider.java [deleted file]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/AggregatedNetconfOperationServiceFactory.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfMonitoringServiceImpl.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryListenerImpl.java [deleted file]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryTracker.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceSnapshotImpl.java [deleted file]
opendaylight/netconf/netconf-impl/src/main/yang/netconf-northbound-impl.yang
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfDispatcherImplTest.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfMonitoringServiceImplTest.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommitTest.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivatorTest.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryTrackerTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITMonitoringTest.java
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationProvider.java [deleted file]
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationService.java
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationServiceFactory.java
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationServiceFactoryListener.java [moved from opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryListener.java with 79% similarity]
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationServiceSnapshot.java [deleted file]
opendaylight/netconf/netconf-mapping-api/src/main/yang/netconf-northbound-mapper.yang
opendaylight/netconf/netconf-mdsal-config/src/main/resources/initial/08-netconf-mdsal.xml
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/GetSchema.java [moved from opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java with 75% similarity]
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringActivator.java
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringOperationService.java
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringServiceTracker.java
opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/GetSchemaTest.java [moved from opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchemaTest.java with 82% similarity]
opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringOperationServiceTest.java
opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/xml/JaxBSerializerTest.java
opendaylight/netconf/netconf-notifications-impl/src/main/java/org/opendaylight/controller/netconf/notifications/impl/osgi/Activator.java
opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/FakeModuleBuilderCapability.java
opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/ModuleBuilderCapability.java
opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java
opendaylight/netconf/pom.xml

index f804505..4185972 100644 (file)
     -->
     <!-- test to validate features.xml -->
     <dependency>
-      <groupId>org.opendaylight.yangtools</groupId>
+      <groupId>org.opendaylight.odlparent</groupId>
       <artifactId>features-test</artifactId>
-      <version>${feature.test.version}</version>
       <scope>test</scope>
     </dependency>
     <!-- dependency for opendaylight-karaf-empty for use by testing -->
                 <karaf.distro.version>${karaf.empty.version}</karaf.distro.version>
               </systemPropertyVariables>
               <dependenciesToScan>
-               <dependency>org.opendaylight.yangtools:features-test</dependency>
+               <dependency>org.opendaylight.odlparent:features-test</dependency>
               </dependenciesToScan>
             </configuration>
           </plugin>
index 0057fc0..71b2841 100644 (file)
@@ -56,7 +56,7 @@
     </dependency>
     <!-- test to validate features.xml -->
     <dependency>
-      <groupId>org.opendaylight.yangtools</groupId>
+      <groupId>org.opendaylight.odlparent</groupId>
       <artifactId>features-test</artifactId>
     </dependency>
   </dependencies>
             <karaf.distro.version>${commons.opendaylight.version}</karaf.distro.version>
           </systemPropertyVariables>
           <dependenciesToScan>
-           <dependency>org.opendaylight.yangtools:features-test</dependency>
+           <dependency>org.opendaylight.odlparent:features-test</dependency>
           </dependenciesToScan>
         </configuration>
       </plugin>
index f3b42ca..6fae0e7 100644 (file)
@@ -81,7 +81,7 @@
     </dependency>
     <!-- test to validate features.xml -->
     <dependency>
-      <groupId>org.opendaylight.yangtools</groupId>
+      <groupId>org.opendaylight.odlparent</groupId>
       <artifactId>features-test</artifactId>
     </dependency>
   </dependencies>
             <karaf.distro.version>${commons.opendaylight.version}</karaf.distro.version>
           </systemPropertyVariables>
           <dependenciesToScan>
-           <dependency>org.opendaylight.yangtools:features-test</dependency>
+           <dependency>org.opendaylight.odlparent:features-test</dependency>
           </dependenciesToScan>
         </configuration>
       </plugin>
index 1fa2486..683ce3d 100644 (file)
@@ -88,7 +88,7 @@
     </dependency>
     <!-- test the features.xml -->
     <dependency>
-      <groupId>org.opendaylight.yangtools</groupId>
+      <groupId>org.opendaylight.odlparent</groupId>
       <artifactId>features-test</artifactId>
     </dependency>
   </dependencies>
             <karaf.distro.version>${commons.opendaylight.version}</karaf.distro.version>
           </systemPropertyVariables>
           <dependenciesToScan>
-           <dependency>org.opendaylight.yangtools:features-test</dependency>
+           <dependency>org.opendaylight.odlparent:features-test</dependency>
           </dependenciesToScan>
         </configuration>
       </plugin>
index 20089c7..6ac5872 100644 (file)
@@ -23,7 +23,6 @@
         <branding.version>1.1.0-SNAPSHOT</branding.version>
         <karaf.resources.version>1.5.0-SNAPSHOT</karaf.resources.version>
         <karaf.version>3.0.1</karaf.version>
-        <feature.test.version>0.7.0-SNAPSHOT</feature.test.version>
         <karaf.empty.version>1.5.0-SNAPSHOT</karaf.empty.version>
         <surefire.version>2.16</surefire.version>
     </properties>
@@ -34,9 +33,8 @@
             <version>${jolokia.version}</version>
         </dependency>
         <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
+            <groupId>org.opendaylight.odlparent</groupId>
             <artifactId>features-test</artifactId>
-            <version>${feature.test.version}</version>
             <scope>test</scope>
         </dependency>
         <!-- dependency for opendaylight-karaf-empty for use by testing -->
                         <karaf.distro.version>${karaf.empty.version}</karaf.distro.version>
                     </systemPropertyVariables>
                     <dependenciesToScan>
-                        <dependency>org.opendaylight.yangtools:features-test</dependency>
+                        <dependency>org.opendaylight.odlparent:features-test</dependency>
                     </dependenciesToScan>
                 </configuration>
             </plugin>
index 53b45d2..ad513e5 100644 (file)
@@ -74,7 +74,7 @@
     </dependency>
     <!-- test to validate features.xml -->
     <dependency>
-      <groupId>org.opendaylight.yangtools</groupId>
+      <groupId>org.opendaylight.odlparent</groupId>
       <artifactId>features-test</artifactId>
     </dependency>
   </dependencies>
             <karaf.distro.version>${commons.opendaylight.version}</karaf.distro.version>
           </systemPropertyVariables>
           <dependenciesToScan>
-           <dependency>org.opendaylight.yangtools:features-test</dependency>
+           <dependency>org.opendaylight.odlparent:features-test</dependency>
           </dependenciesToScan>
         </configuration>
       </plugin>
index c63b39c..35edb28 100644 (file)
       <artifactId>sal-inmemory-datastore</artifactId>
     </dependency>
 
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>mdsal-netconf-connector</artifactId>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>mdsal-netconf-monitoring</artifactId>
+      </dependency>
+
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-netconf-connector</artifactId>
 
     <!-- test to validate features.xml -->
     <dependency>
-      <groupId>org.opendaylight.yangtools</groupId>
+      <groupId>org.opendaylight.odlparent</groupId>
       <artifactId>features-test</artifactId>
-      <version>0.7.0-SNAPSHOT</version>
     </dependency>
   </dependencies>
 
             <karaf.distro.version>${commons.opendaylight.version}</karaf.distro.version>
           </systemPropertyVariables>
           <dependenciesToScan>
-           <dependency>org.opendaylight.yangtools:features-test</dependency>
+           <dependency>org.opendaylight.odlparent:features-test</dependency>
           </dependenciesToScan>
         </configuration>
       </plugin>
index 5b9f4a6..4b9f8c2 100644 (file)
     </feature>
 
     <!-- TODO move to netconf features, however there are some weird dependencies on features-config-persister all over that cause cyclic dependencies-->
-    <feature name='odl-netconf-mdsal' version='${project.version}' description="OpenDaylight :: Netconf :: All">
+    <!-- TODO when installing this in pure karaf distro, many optimistic lock exceptions are thrown from config manager -->
+    <feature name='odl-netconf-mdsal' version='${project.version}' description="OpenDaylight :: Netconf :: Mdsal">
         <feature version='${config.version}'>odl-config-all</feature>
         <feature version='${netconf.version}'>odl-netconf-all</feature>
         <bundle>mvn:org.opendaylight.controller/netconf-ssh/${netconf.version}</bundle>
         <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
         <bundle>mvn:org.opendaylight.controller/mdsal-netconf-connector/${netconf.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller/mdsal-netconf-monitoring/${netconf.version}</bundle>
         <!-- TODO 01-netconf.xml file requires netconf-config-dispatcher to be present and its part of netconf-connector features. Clean Up-->
         <bundle>mvn:org.opendaylight.controller/netconf-config-dispatcher/${config.version}</bundle>
         <configfile finalname='${config.configfile.directory}/${config.netconf.client.configfile}'>mvn:org.opendaylight.controller/netconf-config/${netconf.version}/xml/config</configfile>
index 4e94996..9cb2b1e 100644 (file)
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>netconf-config-dispatcher</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>mdsal-netconf-connector</artifactId>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>netconf-tcp</artifactId>
     <!-- test to validate features.xml -->
    <!--FIXME BUG-2195 When running single feature tests for netconf connector, features including ssh proxy server always fail (this behavior does not appear when running karaf distro directly)-->
     <dependency>
-      <groupId>org.opendaylight.yangtools</groupId>
+      <groupId>org.opendaylight.odlparent</groupId>
       <artifactId>features-test</artifactId>
-      <version>${yangtools.version}</version>
       <scope>test</scope>
     </dependency>
     <!-- dependency for opendaylight-karaf-empty for use by testing -->
                 <karaf.distro.version>${commons.opendaylight.version}</karaf.distro.version>
               </systemPropertyVariables>
               <dependenciesToScan>
-               <dependency>org.opendaylight.yangtools:features-test</dependency>
+               <dependency>org.opendaylight.odlparent:features-test</dependency>
               </dependenciesToScan>
             </configuration>
           </plugin>
index 92e6507..7cabbb4 100644 (file)
     </feature>
     <feature name='odl-netconf-ssh' version='${netconf.version}' description="OpenDaylight :: Netconf Connector :: SSH">
         <feature version='${netconf.version}'>odl-netconf-tcp</feature>
+        <feature version='${config.version}'>odl-config-netty</feature>
         <!-- FIXME: This introduces cycle between projects, which makes version updates
                     harder. Should be moved to different.
         -->
index 4edd936..b28a53b 100644 (file)
     </dependency>
     <!-- test to validate features.xml -->
     <dependency>
-      <groupId>org.opendaylight.yangtools</groupId>
+      <groupId>org.opendaylight.odlparent</groupId>
       <artifactId>features-test</artifactId>
-      <version>${yangtools.version}</version>
       <scope>test</scope>
     </dependency>
     <!-- dependency for opendaylight-karaf-empty for use by testing -->
             <karaf.distro.version>${commons.opendaylight.version}</karaf.distro.version>
           </systemPropertyVariables>
           <dependenciesToScan>
-            <dependency>org.opendaylight.yangtools:features-test</dependency>
+            <dependency>org.opendaylight.odlparent:features-test</dependency>
           </dependenciesToScan>
         </configuration>
       </plugin>
index a655021..aa8287d 100644 (file)
@@ -27,6 +27,7 @@
     <bundle>mvn:org.opendaylight.controller/ietf-netconf-monitoring-extension/${project.version}</bundle>
     <bundle>mvn:org.opendaylight.yangtools.model/ietf-inet-types/${ietf-inet-types.version}</bundle>
     <bundle>mvn:org.opendaylight.yangtools.model/ietf-yang-types/${ietf-yang-types.version}</bundle>
+    <bundle>mvn:org.opendaylight.yangtools.model/ietf-yang-types-20130715/2013.07.15.7-SNAPSHOT</bundle>
   </feature>
   <feature name='odl-netconf-mapping-api' version='${project.version}' description="OpenDaylight :: Netconf :: Mapping API">
     <feature version='${project.version}'>odl-netconf-api</feature>
index d5387b4..f663c1c 100644 (file)
@@ -28,7 +28,7 @@
     </dependency>
     <!-- test to validate features.xml -->
     <dependency>
-      <groupId>org.opendaylight.yangtools</groupId>
+      <groupId>org.opendaylight.odlparent</groupId>
       <artifactId>features-test</artifactId>
     </dependency>
   </dependencies>
@@ -86,7 +86,7 @@
             <karaf.distro.version>${commons.opendaylight.version}</karaf.distro.version>
           </systemPropertyVariables>
           <dependenciesToScan>
-           <dependency>org.opendaylight.yangtools:features-test</dependency>
+           <dependency>org.opendaylight.odlparent:features-test</dependency>
           </dependenciesToScan>
         </configuration>
       </plugin>
index 632b4cd..347a19a 100644 (file)
     -->
     <!-- test to validate features.xml -->
     <dependency>
-      <groupId>org.opendaylight.yangtools</groupId>
+      <groupId>org.opendaylight.odlparent</groupId>
       <artifactId>features-test</artifactId>
-      <version>${yangtools.version}</version>
       <scope>test</scope>
     </dependency>
     <!-- dependency for opendaylight-karaf-empty for use by testing -->
                 <karaf.distro.version>${commons.opendaylight.version}</karaf.distro.version>
               </systemPropertyVariables>
               <dependenciesToScan>
-               <dependency>org.opendaylight.yangtools:features-test</dependency>
+               <dependency>org.opendaylight.odlparent:features-test</dependency>
               </dependenciesToScan>
             </configuration>
           </plugin>
index 7057a86..6eab884 100644 (file)
@@ -28,7 +28,7 @@
 
     <!-- karaf distro -->
     <fileSet filtered="true" encoding="UTF-8">
-        <directory>__artifactId__-karaf</directory>
+        <directory>karaf</directory>
         <includes>
             <include>pom.xml</include>
         </includes>
     <!-- features -->
 
     <fileSet filtered="true" encoding="UTF-8">
-        <directory>__artifactId__-features</directory>
+        <directory>features</directory>
         <includes>
             <include>pom.xml</include>
         </includes>
     </fileSet>
     <fileSet filtered="true" encoding="UTF-8">
-        <directory>__artifactId__-features/src/main/features</directory>
+        <directory>features/src/main/features</directory>
         <includes>
             <include>**/*.xml</include>
           </includes>
     <!-- impl -->
 
     <fileSet filtered="true" encoding="UTF-8">
-        <directory>__artifactId__-impl</directory>
+        <directory>impl</directory>
         <includes>
             <include>pom.xml</include>
         </includes>
     </fileSet>
     <fileSet filtered="true" encoding="UTF-8">
-        <directory>__artifactId__-impl/src/main/java</directory>
+        <directory>impl/src/main/java</directory>
         <includes>
             <include>**/*.java</include>
          </includes>
     </fileSet>
     <fileSet filtered="true" encoding="UTF-8">
-        <directory>__artifactId__-impl/src/main/config</directory>
+        <directory>impl/src/test/java</directory>
+        <includes>
+            <include>**/*.java</include>
+         </includes>
+    </fileSet>
+    <fileSet filtered="true" encoding="UTF-8">
+        <directory>impl/src/main/config</directory>
         <includes>
             <include>**/*.xml</include>
          </includes>
     </fileSet>
     <fileSet filtered="true" encoding="UTF-8">
-       <directory>__artifactId__-impl/src/main/yang</directory>
+       <directory>impl/src/main/yang</directory>
        <includes>
          <include>**/*.yang</include>
        </includes>
      <!-- api -->
 
      <fileSet filtered="true" encoding="UTF-8">
-       <directory>__artifactId__-api</directory>
+       <directory>api</directory>
        <includes>
          <include>pom.xml</include>
        </includes>
      </fileSet>
      <fileSet filtered="true" encoding="UTF-8">
-       <directory>__artifactId__-api/src/main/yang</directory>
+       <directory>api/src/main/yang</directory>
        <includes>
          <include>**/*.yang</include>
        </includes>
@@ -93,7 +99,7 @@
 
      <!-- artifacts -->
      <fileSet filtered="true" encoding="UTF-8">
-       <directory>__artifactId__-artifacts</directory>
+       <directory>artifacts</directory>
        <includes>
          <include>pom.xml</include>
        </includes>
@@ -26,6 +26,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
   <properties>
     <mdsal.version>1.2.0-SNAPSHOT</mdsal.version>
     <yangtools.version>0.7.0-SNAPSHOT</yangtools.version>
+    <configfile.directory>etc/opendaylight/karaf</configfile.directory>
   </properties>
   <dependencyManagement>
     <dependencies>
@@ -16,22 +16,22 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
   <repository>mvn:org.opendaylight.yangtools/features-yangtools/${symbol_dollar}{yangtools.version}/xml/features</repository>
   <repository>mvn:org.opendaylight.controller/features-mdsal/${symbol_dollar}{mdsal.version}/xml/features</repository>
   <repository>mvn:org.opendaylight.controller/features-restconf/${symbol_dollar}{mdsal.version}/xml/features</repository>
-  <feature name='odl-${artifactId}-api' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId} :: api '>
+  <feature name='odl-${artifactId}-api' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId} :: api'>
     <feature version='${symbol_dollar}{yangtools.version}'>odl-yangtools-models</feature>
     <bundle>mvn:${groupId}/${artifactId}-api/${symbol_dollar}{project.version}</bundle>
   </feature>
-  <feature name='odl-${artifactId}-impl' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId} :: impl '>
+  <feature name='odl-${artifactId}' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId}'>
     <feature version='${symbol_dollar}{mdsal.version}'>odl-mdsal-broker</feature>
     <feature version='${symbol_dollar}{project.version}'>odl-${artifactId}-api</feature>
     <bundle>mvn:${groupId}/${artifactId}-impl/${symbol_dollar}{project.version}</bundle>
-    <configfile finalname="${artifactId}-impl-default-config.xml">mvn:${groupId}/${artifactId}-impl/${symbol_dollar}{project.version}/xml/config</configfile>
+    <configfile finalname="${configfile.directory}/${artifactId}.xml">mvn:${groupId}/${artifactId}-impl/${symbol_dollar}{project.version}/xml/config</configfile>
   </feature>
-  <feature name='odl-${artifactId}-impl-rest' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId} :: impl :: REST '>
-    <feature version="${symbol_dollar}{project.version}">odl-${artifactId}-impl</feature>
+  <feature name='odl-${artifactId}-rest' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId} :: REST'>
+    <feature version="${symbol_dollar}{project.version}">odl-${artifactId}</feature>
     <feature version="${symbol_dollar}{mdsal.version}">odl-restconf</feature>
   </feature>
-  <feature name='odl-${artifactId}-impl-ui' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId} :: impl :: UI'>
-    <feature version="${symbol_dollar}{project.version}">odl-${artifactId}-impl-rest</feature>
+  <feature name='odl-${artifactId}-ui' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId} :: UI'>
+    <feature version="${symbol_dollar}{project.version}">odl-${artifactId}-rest</feature>
     <feature version="${symbol_dollar}{mdsal.version}">odl-mdsal-apidocs</feature>
     <feature version="${symbol_dollar}{mdsal.version}">odl-mdsal-xsql</feature>
   </feature>
@@ -29,6 +29,19 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <artifactId>${artifactId}-api</artifactId>
       <version>${symbol_dollar}{project.version}</version>
     </dependency>
+
+    <!-- Testing Dependencies -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
 </project>
@@ -20,7 +20,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
       <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
         <module>
-          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:${artifactId}:impl">prefix:${artifactId}-impl</type>
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:${artifactId}:impl">prefix:${artifactId}</type>
           <name>${artifactId}-default</name>
           <broker>
             <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
@@ -8,7 +8,7 @@
  * 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 ${package};
+package ${package}.impl;
 
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
  */
 package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${artifactId}.impl.rev141210;
 
-import ${package}.${classPrefix}Provider;
+import ${package}.impl.${classPrefix}Provider;
 
-public class ${classPrefix}ImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${artifactId}.impl.rev141210.Abstract${classPrefix}ImplModule {
-    public ${classPrefix}ImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+public class ${classPrefix}Module extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${artifactId}.impl.rev141210.Abstract${classPrefix}Module {
+    public ${classPrefix}Module(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
         super(identifier, dependencyResolver);
     }
 
-    public ${classPrefix}ImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${artifactId}.impl.rev141210.${classPrefix}ImplModule oldModule, java.lang.AutoCloseable oldInstance) {
+    public ${classPrefix}Module(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${artifactId}.impl.rev141210.${classPrefix}Module oldModule, java.lang.AutoCloseable oldInstance) {
         super(identifier, dependencyResolver, oldModule, oldInstance);
     }
 
@@ -18,6 +18,6 @@
 * Do not modify this file unless it is present under src/main directory
 */
 package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${artifactId}.impl.rev141210;
-public class ${classPrefix}ImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${artifactId}.impl.rev141210.Abstract${classPrefix}ImplModuleFactory {
+public class ${classPrefix}ModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${artifactId}.impl.rev141210.Abstract${classPrefix}ModuleFactory {
 
 }
@@ -14,14 +14,14 @@ module ${artifactId}-impl {
             "Initial revision";
     }
 
-    identity ${artifactId}-impl {
+    identity ${artifactId} {
         base config:module-type;
-        config:java-name-prefix ${classPrefix}Impl;
+        config:java-name-prefix ${classPrefix};
     }
 
     augment "/config:modules/config:module/config:configuration" {
-        case ${artifactId}-impl {
-            when "/config:modules/config:module/config:type = '${artifactId}-impl'";
+        case ${artifactId} {
+            when "/config:modules/config:module/config:type = '${artifactId}'";
             container broker {
                 uses config:service-ref {
                     refine type {
diff --git a/opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/impl/src/test/java/__packageInPathFormat__/impl/__classPrefix__ProviderTest.java b/opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/impl/src/test/java/__packageInPathFormat__/impl/__classPrefix__ProviderTest.java
new file mode 100644 (file)
index 0000000..09b3dc4
--- /dev/null
@@ -0,0 +1,37 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+#set( $provider = "${classPrefix}Provider" )
+/*
+ * ${copyright} 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 ${package}.impl;
+
+import org.junit.Test;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+
+import static org.mockito.Mockito.mock;
+
+public class ${classPrefix}ProviderTest {
+    @Test
+    public void testOnSessionInitiated() {
+        ${provider} provider = new ${provider}();
+
+        // ensure no exceptions
+        // currently this method is empty
+        provider.onSessionInitiated(mock(BindingAwareBroker.ProviderContext.class));
+    }
+
+    @Test
+    public void testClose() throws Exception {
+        ${provider} provider = new ${provider}();
+
+        // ensure no exceptions
+        // currently this method is empty
+        provider.close();
+    }
+}
diff --git a/opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/impl/src/test/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/__artifactId__/impl/rev141210/__classPrefix__ModuleFactoryTest.java b/opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/impl/src/test/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/__artifactId__/impl/rev141210/__classPrefix__ModuleFactoryTest.java
new file mode 100644 (file)
index 0000000..9f8991f
--- /dev/null
@@ -0,0 +1,22 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+#set( $factory = "${classPrefix}ModuleFactory" )
+/*
+ * ${copyright} 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${artifactId}.impl.rev141210;
+
+import org.junit.Test;
+
+public class ${classPrefix}ModuleFactoryTest {
+    @Test
+    public void testFactoryConstructor() {
+        // ensure no exceptions on construction
+        new ${factory}();
+    }
+}
diff --git a/opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/impl/src/test/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/__artifactId__/impl/rev141210/__classPrefix__ModuleTest.java b/opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/impl/src/test/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/__artifactId__/impl/rev141210/__classPrefix__ModuleTest.java
new file mode 100644 (file)
index 0000000..bbef4d8
--- /dev/null
@@ -0,0 +1,58 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+#set( $module = "${classPrefix}Module" )
+/*
+ * ${copyright} 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${artifactId}.impl.rev141210;
+
+import org.junit.Test;
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.JmxAttribute;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import ${package}.impl.${classPrefix}Provider;
+
+import javax.management.ObjectName;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class ${classPrefix}ModuleTest {
+    @Test
+    public void testCustomValidation() {
+        ${module} module = new ${module}(mock(ModuleIdentifier.class), mock(DependencyResolver.class));
+
+        // ensure no exceptions on validation
+        // currently this method is empty
+        module.customValidation();
+    }
+
+    @Test
+    public void testCreateInstance() throws Exception {
+        // configure mocks
+        DependencyResolver dependencyResolver = mock(DependencyResolver.class);
+        BindingAwareBroker broker = mock(BindingAwareBroker.class);
+        when(dependencyResolver.resolveInstance(eq(BindingAwareBroker.class), any(ObjectName.class), any(JmxAttribute.class))).thenReturn(broker);
+
+        // create instance of module with injected mocks
+        ${module} module = new ${module}(mock(ModuleIdentifier.class), dependencyResolver);
+
+        // getInstance calls resolveInstance to get the broker dependency and then calls createInstance
+        AutoCloseable closeable = module.getInstance();
+
+        // verify that the module registered the returned provider with the broker
+        verify(broker).registerProvider((${classPrefix}Provider)closeable);
+
+        // ensure no exceptions on close
+        closeable.close();
+    }
+}
@@ -24,7 +24,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
     <maven>3.1.1</maven>
   </prerequisites>
   <properties>
-    <karaf.localFeature>odl-${artifactId}-impl-ui</karaf.localFeature>
+    <karaf.localFeature>odl-${artifactId}-ui</karaf.localFeature>
   </properties>
   <dependencyManagement>
     <dependencies>
@@ -54,4 +54,23 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
       <scope>runtime</scope>
     </dependency>
   </dependencies>
+  <!-- DO NOT install or deploy the karaf artifact -->
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-deploy-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-install-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
 </project>
index 3221efd..616704a 100644 (file)
@@ -9,18 +9,18 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
   <groupId>${groupId}</groupId>
   <artifactId>${artifactId}-aggregator</artifactId>
   <version>${version}</version>
-  <name>${project.artifactId}</name>
+  <name>${artifactId}</name>
   <packaging>pom</packaging>
   <modelVersion>4.0.0</modelVersion>
   <prerequisites>
     <maven>3.1.1</maven>
   </prerequisites>
   <modules>
-    <module>${artifactId}-api</module>
-    <module>${artifactId}-impl</module>
-    <module>${artifactId}-karaf</module>
-    <module>${artifactId}-features</module>
-    <module>${artifactId}-artifacts</module>
+    <module>api</module>
+    <module>impl</module>
+    <module>karaf</module>
+    <module>features</module>
+    <module>artifacts</module>
   </modules>
   <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
   <build>
@@ -41,4 +41,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
       </plugin>
     </plugins>
   </build>
+
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/${artifactId}.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/${artifactId}.git</developerConnection>
+    <tag>HEAD</tag>
+    <url>https://wiki.opendaylight.org/view/${artifactId}:Main</url>
+  </scm>
 </project>
index 9a88e61..7a977f9 100644 (file)
@@ -15,7 +15,7 @@
 
   <properties>
 
-    <akka.version>2.3.4</akka.version>
+    <akka.version>2.3.9</akka.version>
     <appauth.version>0.5.0-SNAPSHOT</appauth.version>
     <archetype-app-northbound>0.1.0-SNAPSHOT</archetype-app-northbound>
     <arphandler.version>0.6.0-SNAPSHOT</arphandler.version>
@@ -81,6 +81,7 @@
     <!-- OpenEXI third party lib for netconf-->
     <exi.nagasena.version>0000.0002.0038.0</exi.nagasena.version>
     <felix.util.version>1.6.0</felix.util.version>
+    <features.test.version>1.5.0-SNAPSHOT</features.test.version>
     <filtervalve.version>1.5.0-SNAPSHOT</filtervalve.version>
     <findbugs.maven.plugin.version>2.4.0</findbugs.maven.plugin.version>
     <flowprogrammer.northbound.version>0.5.0-SNAPSHOT</flowprogrammer.northbound.version>
     <jmxGeneratorPath>src/main/yang-gen-config</jmxGeneratorPath>
     <jolokia-bridge.version>0.1.0-SNAPSHOT</jolokia-bridge.version>
     <jolokia.version>1.1.4</jolokia.version>
-    <jsr305.api.version>2.0.1</jsr305.api.version>
     <jsr311.api.version>1.1.1</jsr311.api.version>
     <jsr311.v2.api.version>2.0</jsr311.v2.api.version>
     <karaf.branding.version>1.1.0-SNAPSHOT</karaf.branding.version>
         <artifactId>java-concurrent-hash-trie-map</artifactId>
         <version>${ctrie.version}</version>
       </dependency>
-      <dependency>
-        <groupId>com.google.code.findbugs</groupId>
-        <artifactId>jsr305</artifactId>
-        <version>${jsr305.api.version}</version>
-      </dependency>
       <dependency>
         <groupId>com.google.code.gson</groupId>
         <artifactId>gson</artifactId>
 
       <!-- 3rd party dependencies needed by config-->
       <dependency>
-        <groupId>com.jcabi</groupId>
-        <artifactId>jcabi-maven-slf4j</artifactId>
-        <version>0.8</version>
+        <groupId>org.apache.maven</groupId>
+        <artifactId>maven-core</artifactId>
+        <version>3.1.1</version>
+        <scope>provided</scope>
       </dependency>
 
       <dependency>
         <version>${yangtools.version}</version>
         <scope>test</scope>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.odlparent</groupId>
+        <artifactId>features-test</artifactId>
+        <version>${features.test.version}</version>
+        <scope>test</scope>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.yangtools</groupId>
         <artifactId>features-yangtools</artifactId>
index 5c9ed87..3d72114 100644 (file)
@@ -66,23 +66,4 @@ public interface ConfigRegistry extends LookupRegistry, ServiceReferenceReadable
     Set<String> getAvailableModuleNames();
 
 
-
-    /**
-     * Find all runtime beans
-     *
-     * @return objectNames
-     */
-    Set<ObjectName> lookupRuntimeBeans();
-
-    /**
-     * Find all runtime of specified module
-     *
-     * @param moduleName
-     *            of bean
-     * @param instanceName
-     *            of bean
-     * @return objectNames
-     */
-    Set<ObjectName> lookupRuntimeBeans(String moduleName, String instanceName);
-
 }
index b90fc9c..5d615c2 100644 (file)
@@ -71,4 +71,21 @@ public interface LookupRegistry {
      */
     Set<String> getAvailableModuleFactoryQNames();
 
+    /**
+     * Find all runtime beans
+     *
+     * @return objectNames
+     */
+    Set<ObjectName> lookupRuntimeBeans();
+
+    /**
+     * Find all runtime of specified module
+     *
+     * @param moduleName
+     *            of bean
+     * @param instanceName
+     *            of bean
+     * @return objectNames
+     */
+    Set<ObjectName> lookupRuntimeBeans(String moduleName, String instanceName);
 }
index 37c2e2d..186a721 100644 (file)
@@ -482,6 +482,25 @@ class ConfigTransactionControllerImpl implements
     public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException {
         txLookupRegistry.checkConfigBeanExists(objectName);
     }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Set<ObjectName> lookupRuntimeBeans() {
+        return txLookupRegistry.lookupRuntimeBeans();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Set<ObjectName> lookupRuntimeBeans(String moduleName,
+                                              String instanceName) {
+        return txLookupRegistry.lookupRuntimeBeans(moduleName, instanceName);
+    }
+
     // --
 
     /**
index f9a3801..a0138b2 100644 (file)
@@ -116,6 +116,26 @@ class ConfigTransactionLookupRegistry  implements LookupRegistry, Closeable {
         return ModuleQNameUtil.getQNames(allCurrentFactories);
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Set<ObjectName> lookupRuntimeBeans() {
+        return lookupRuntimeBeans("*", "*");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Set<ObjectName> lookupRuntimeBeans(String moduleName,
+                                              String instanceName) {
+        String finalModuleName = moduleName == null ? "*" : moduleName;
+        String finalInstanceName = instanceName == null ? "*" : instanceName;
+        ObjectName namePattern = ObjectNameUtil.createRuntimeBeanPattern(
+                finalModuleName, finalInstanceName);
+        return transactionJMXRegistrator.queryNames(namePattern, null);
+    }
 
     @Override
     public String toString() {
index 27f0d5c..dd6c2b9 100644 (file)
@@ -97,6 +97,16 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe
                 throw new UnsupportedOperationException();
             }
 
+            @Override
+            public Set<ObjectName> lookupRuntimeBeans() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public Set<ObjectName> lookupRuntimeBeans(final String moduleName, final String instanceName) {
+                throw new UnsupportedOperationException();
+            }
+
             @Override
             public String toString() {
                 return "initial";
diff --git a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/BeanReader.java b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/BeanReader.java
new file mode 100644 (file)
index 0000000..de9baa6
--- /dev/null
@@ -0,0 +1,10 @@
+package org.opendaylight.controller.config.util;
+
+import javax.management.ObjectName;
+
+/**
+ * Created by mmarsale on 20.2.2015.
+ */
+public interface BeanReader {
+    Object getAttributeCurrentValue(ObjectName on, String attributeName);
+}
index 99d46cb..d384ae5 100644 (file)
@@ -10,7 +10,7 @@ package org.opendaylight.controller.config.util;
 import javax.management.ObjectName;
 import org.opendaylight.controller.config.api.jmx.ConfigRegistryMXBean;
 
-public interface ConfigRegistryClient extends ConfigRegistryMXBean {
+public interface ConfigRegistryClient extends ConfigRegistryMXBean, BeanReader {
 
     ConfigTransactionClient createTransaction();
 
@@ -23,6 +23,4 @@ public interface ConfigRegistryClient extends ConfigRegistryMXBean {
     Object invokeMethod(ObjectName on, String name, Object[] params,
             String[] signature);
 
-    Object getAttributeCurrentValue(ObjectName on, String attributeName);
-
 }
index 099d010..a39111a 100644 (file)
@@ -211,7 +211,7 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient {
         } catch (AttributeNotFoundException | InstanceNotFoundException
                 | MBeanException | ReflectionException e) {
             throw new RuntimeException("Unable to get attribute "
-                    + attributeName + " for " + on, e);
+                    + attributeName + " for " + on + ". Available beans: " + lookupConfigBeans(), e);
         }
     }
 
index 359035d..c7c072d 100644 (file)
@@ -16,7 +16,7 @@ import org.opendaylight.controller.config.api.jmx.CommitStatus;
 import org.opendaylight.controller.config.api.jmx.ConfigTransactionControllerMXBean;
 
 public interface ConfigTransactionClient extends
-        ConfigTransactionControllerMXBean {
+        ConfigTransactionControllerMXBean, BeanReader {
 
     CommitStatus commit() throws ConflictingVersionException,
             ValidationException;
@@ -47,7 +47,7 @@ public interface ConfigTransactionClient extends
      * @param on - ObjectName of the Object from which the attribute should be read
      * @param jmxName - name of the attribute to be read
      *
-     * @return Attribute of Object on with attribute name jmxName
+     * @return Object of Object on with attribute name jmxName
      */
     Attribute getAttribute(ObjectName on, String jmxName);
 }
index a0af197..26ca139 100644 (file)
@@ -240,6 +240,26 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient {
         configTransactionControllerMXBeanProxy.checkServiceReferenceExists(objectName);
     }
 
+    @Override
+    public Attribute getAttribute(ObjectName on, String attrName) {
+        if (ObjectNameUtil.getTransactionName(on) == null) {
+            throw new IllegalArgumentException("Not in transaction instance "
+                    + on + ", no transaction name present");
+        }
+
+        try {
+            return new Attribute(attrName, configMBeanServer.getAttribute(on,attrName));
+        } catch (JMException e) {
+            throw new IllegalStateException("Unable to get attribute "
+                    + attrName + " for " + on, e);
+        }
+    }
+
+    @Override
+    public Object getAttributeCurrentValue(ObjectName on, String attrName) {
+        return getAttribute(on, attrName).getValue();
+    }
+
     @Override
     public void validateBean(ObjectName configBeanON)
             throws ValidationException {
@@ -273,22 +293,17 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient {
     }
 
     @Override
-    public Attribute getAttribute(ObjectName on, String attrName) {
-        if (ObjectNameUtil.getTransactionName(on) == null) {
-            throw new IllegalArgumentException("Not in transaction instance "
-                    + on + ", no transaction name present");
-        }
+    public Set<String> getAvailableModuleFactoryQNames() {
+        return configTransactionControllerMXBeanProxy.getAvailableModuleFactoryQNames();
+    }
 
-        try {
-            return new Attribute(attrName, configMBeanServer.getAttribute(on,attrName));
-        } catch (JMException e) {
-            throw new IllegalStateException("Unable to get attribute "
-                    + attrName + " for " + on, e);
-        }
+    @Override
+    public Set<ObjectName> lookupRuntimeBeans() {
+        return configTransactionControllerMXBeanProxy.lookupRuntimeBeans();
     }
 
     @Override
-    public Set<String> getAvailableModuleFactoryQNames() {
-        return configTransactionControllerMXBeanProxy.getAvailableModuleFactoryQNames();
+    public Set<ObjectName> lookupRuntimeBeans(final String moduleName, final String instanceName) {
+        return configTransactionControllerMXBeanProxy.lookupRuntimeBeans(moduleName, instanceName);
     }
 }
index e1138ad..e690194 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.controller.config.util;
 
 import com.google.common.collect.Sets;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
@@ -184,6 +185,16 @@ public class TestingConfigTransactionController implements
         return Sets.newHashSet("availableModuleFactoryQNames");
     }
 
+    @Override
+    public Set<ObjectName> lookupRuntimeBeans() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public Set<ObjectName> lookupRuntimeBeans(final String moduleName, final String instanceName) {
+        return Collections.emptySet();
+    }
+
     @Override
     public ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException {
         return conf3;
index 6c8a591..ae19084 100644 (file)
       <artifactId>guava</artifactId>
     </dependency>
 
-    <dependency>
-      <groupId>com.jcabi</groupId>
-      <artifactId>jcabi-maven-slf4j</artifactId>
-    </dependency>
-
     <dependency>
       <groupId>commons-io</groupId>
       <artifactId>commons-io</artifactId>
       <artifactId>commons-lang3</artifactId>
     </dependency>
 
-    <dependency>
-      <groupId>org.codehaus.gmaven.runtime</groupId>
-      <artifactId>gmaven-runtime-2.0</artifactId>
-      <exclusions>
-        <exclusion>
-          <groupId>org.sonatype.gossip</groupId>
-          <artifactId>gossip</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>yang-jmx-generator</artifactId>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-maven-plugin-spi</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-core</artifactId>
+    </dependency>
 
     <dependency>
       <groupId>org.slf4j</groupId>
index 9ad8d28..1f1776f 100644 (file)
@@ -23,7 +23,6 @@ import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import org.apache.commons.io.FileUtils;
-import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.project.MavenProject;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
@@ -35,42 +34,54 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang2sources.spi.CodeGenerator;
+import org.opendaylight.yangtools.yang2sources.spi.BasicCodeGenerator;
+import org.opendaylight.yangtools.yang2sources.spi.MavenProjectAware;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.slf4j.impl.StaticLoggerBinder;
 
 /**
  * This class interfaces with yang-maven-plugin. Gets parsed yang modules in
  * {@link SchemaContext}, and parameters form the plugin configuration, and
  * writes service interfaces and/or modules.
  */
-public class JMXGenerator implements CodeGenerator {
+public class JMXGenerator implements BasicCodeGenerator, MavenProjectAware {
+    private static final class NamespaceMapping {
+        private final String namespace, packageName;
 
+        public NamespaceMapping(final String namespace, final String packagename) {
+            this.namespace = namespace;
+            this.packageName = packagename;
+        }
+    }
+
+    @VisibleForTesting
     static final String NAMESPACE_TO_PACKAGE_DIVIDER = "==";
+    @VisibleForTesting
     static final String NAMESPACE_TO_PACKAGE_PREFIX = "namespaceToPackage";
+    @VisibleForTesting
     static final String MODULE_FACTORY_FILE_BOOLEAN = "moduleFactoryFile";
 
+    private static final Logger LOG = LoggerFactory.getLogger(JMXGenerator.class);
+    private static final Pattern NAMESPACE_MAPPING_PATTERN = Pattern.compile("(.+)" + NAMESPACE_TO_PACKAGE_DIVIDER + "(.+)");
+
     private PackageTranslator packageTranslator;
     private final CodeWriter codeWriter;
-    private static final Logger LOG = LoggerFactory
-            .getLogger(JMXGenerator.class);
     private Map<String, String> namespaceToPackageMapping;
     private File resourceBaseDir;
     private File projectBaseDir;
     private boolean generateModuleFactoryFile = true;
 
     public JMXGenerator() {
-        this.codeWriter = new CodeWriter();
+        this(new CodeWriter());
     }
 
-    public JMXGenerator(CodeWriter codeWriter) {
+    public JMXGenerator(final CodeWriter codeWriter) {
         this.codeWriter = codeWriter;
     }
 
     @Override
-    public Collection<File> generateSources(SchemaContext context,
-                                            File outputBaseDir, Set<Module> yangModulesInCurrentMavenModule) {
+    public Collection<File> generateSources(final SchemaContext context,
+                                            final File outputBaseDir, final Set<Module> yangModulesInCurrentMavenModule) {
 
         Preconditions.checkArgument(context != null, "Null context received");
         Preconditions.checkArgument(outputBaseDir != null,
@@ -173,7 +184,8 @@ public class JMXGenerator implements CodeGenerator {
         return generatedFiles.getFiles();
     }
 
-    static File concatFolders(File projectBaseDir, String... folderNames) {
+    @VisibleForTesting
+    static File concatFolders(final File projectBaseDir, final String... folderNames) {
         StringBuilder b = new StringBuilder();
         for (String folder : folderNames) {
             b.append(folder);
@@ -183,18 +195,14 @@ public class JMXGenerator implements CodeGenerator {
     }
 
     @Override
-    public void setAdditionalConfig(Map<String, String> additionalCfg) {
-        if (LOG != null) {
-            LOG.debug(getClass().getCanonicalName(),
-                    ": Additional configuration received: ",
-                    additionalCfg.toString());
-        }
+    public void setAdditionalConfig(final Map<String, String> additionalCfg) {
+        LOG.debug("{}: Additional configuration received: {}", getClass().getCanonicalName(), additionalCfg);
         this.namespaceToPackageMapping = extractNamespaceMapping(additionalCfg);
         this.generateModuleFactoryFile = extractModuleFactoryBoolean(additionalCfg);
     }
 
     private boolean extractModuleFactoryBoolean(
-            Map<String, String> additionalCfg) {
+            final Map<String, String> additionalCfg) {
         String bool = additionalCfg.get(MODULE_FACTORY_FILE_BOOLEAN);
         if (bool == null) {
             return true;
@@ -205,13 +213,8 @@ public class JMXGenerator implements CodeGenerator {
         return true;
     }
 
-    @Override
-    public void setLog(Log log) {
-        StaticLoggerBinder.getSingleton().setMavenLog(log);
-    }
-
     private static Map<String, String> extractNamespaceMapping(
-            Map<String, String> additionalCfg) {
+            final Map<String, String> additionalCfg) {
         Map<String, String> namespaceToPackage = Maps.newHashMap();
         for (String key : additionalCfg.keySet()) {
             if (key.startsWith(NAMESPACE_TO_PACKAGE_PREFIX)) {
@@ -224,46 +227,30 @@ public class JMXGenerator implements CodeGenerator {
         return namespaceToPackage;
     }
 
-    static Pattern namespaceMappingPattern = Pattern.compile("(.+)"
-            + NAMESPACE_TO_PACKAGE_DIVIDER + "(.+)");
-
-    private static NamespaceMapping extractNamespaceMapping(String mapping) {
-        Matcher matcher = namespaceMappingPattern.matcher(mapping);
-        Preconditions
-                .checkArgument(matcher.matches(), String.format("Namespace to package mapping:%s is in invalid " +
-                        "format, requested format is: %s", mapping, namespaceMappingPattern));
+    private static NamespaceMapping extractNamespaceMapping(final String mapping) {
+        Matcher matcher = NAMESPACE_MAPPING_PATTERN.matcher(mapping);
+        Preconditions.checkArgument(matcher.matches(),
+            "Namespace to package mapping:%s is in invalid format, requested format is: %s",
+            mapping, NAMESPACE_MAPPING_PATTERN);
         return new NamespaceMapping(matcher.group(1), matcher.group(2));
     }
 
-    private static class NamespaceMapping {
-        public NamespaceMapping(String namespace, String packagename) {
-            this.namespace = namespace;
-            this.packageName = packagename;
-        }
-
-        private final String namespace, packageName;
-    }
-
     @Override
-    public void setResourceBaseDir(File resourceDir) {
+    public void setResourceBaseDir(final File resourceDir) {
         this.resourceBaseDir = resourceDir;
     }
 
     @Override
-    public void setMavenProject(MavenProject project) {
+    public void setMavenProject(final MavenProject project) {
         this.projectBaseDir = project.getBasedir();
-
-        if (LOG != null) {
-            LOG.debug(getClass().getCanonicalName(), " project base dir: ",
-                    projectBaseDir);
-        }
+        LOG.debug("{}: project base dir: {}", getClass().getCanonicalName(), projectBaseDir);
     }
 
     @VisibleForTesting
     static class GeneratedFilesTracker {
         private final Set<File> files = Sets.newHashSet();
 
-        void addFile(File file) {
+        void addFile(final File file) {
             if (files.contains(file)) {
                 List<File> undeletedFiles = Lists.newArrayList();
                 for (File presentFile : files) {
@@ -283,7 +270,7 @@ public class JMXGenerator implements CodeGenerator {
             files.add(file);
         }
 
-        void addFile(Collection<File> files) {
+        void addFile(final Collection<File> files) {
             for (File file : files) {
                 addFile(file);
             }
index 19e875f..00454d8 100644 (file)
@@ -48,9 +48,9 @@ import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Meth
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.MethodDefinition;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.ModuleField;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.FullyQualifiedNameHelper;
-import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
 import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
 
 public class TemplateFactory {
 
@@ -59,7 +59,7 @@ public class TemplateFactory {
      * bean as value that should be persisted from this instance.
      */
     public static Map<String, FtlTemplate> getTOAndMXInterfaceFtlFiles(
-            RuntimeBeanEntry entry) {
+            final RuntimeBeanEntry entry) {
         Map<String, FtlTemplate> result = new HashMap<>();
         { // create GeneralInterfaceFtlFile for runtime MXBean. Attributes will
           // be transformed to getter methods
@@ -109,7 +109,7 @@ public class TemplateFactory {
     }
 
     // FIXME: put into Type.toString
-    static String serializeType(Type type, boolean addWildcards) {
+    static String serializeType(final Type type, final boolean addWildcards) {
         if (type instanceof ParameterizedType){
             ParameterizedType parameterizedType = (ParameterizedType) type;
             StringBuilder sb = new StringBuilder();
@@ -131,11 +131,11 @@ public class TemplateFactory {
         }
     }
 
-    static String serializeType(Type type) {
+    static String serializeType(final Type type) {
         return serializeType(type, false);
     }
 
-    private static String getReturnType(AttributeIfc attributeIfc) {
+    private static String getReturnType(final AttributeIfc attributeIfc) {
         String returnType;
         if (attributeIfc instanceof TypedAttribute) {
             Type type = ((TypedAttribute) attributeIfc).getType();
@@ -151,7 +151,7 @@ public class TemplateFactory {
     }
 
     public static GeneralInterfaceTemplate serviceInterfaceFromSie(
-            ServiceInterfaceEntry sie) {
+            final ServiceInterfaceEntry sie) {
 
         List<String> extendedInterfaces = Lists
                 .newArrayList(AbstractServiceInterface.class.getCanonicalName());
@@ -177,7 +177,7 @@ public class TemplateFactory {
     }
 
     public static AbstractFactoryTemplate abstractFactoryTemplateFromMbe(
-            ModuleMXBeanEntry mbe) {
+            final ModuleMXBeanEntry mbe) {
         AbstractFactoryAttributesProcessor attrProcessor = new AbstractFactoryAttributesProcessor();
         attrProcessor.processAttributes(mbe.getAttributes(),
                 mbe.getPackageName());
@@ -191,7 +191,7 @@ public class TemplateFactory {
     }
 
     public static AbstractModuleTemplate abstractModuleTemplateFromMbe(
-            ModuleMXBeanEntry mbe) {
+            final ModuleMXBeanEntry mbe) {
         AbstractModuleAttributesProcessor attrProcessor = new AbstractModuleAttributesProcessor(mbe.getAttributes());
 
         List<ModuleField> moduleFields = attrProcessor.getModuleFields();
@@ -234,7 +234,7 @@ public class TemplateFactory {
     }
 
     public static StubFactoryTemplate stubFactoryTemplateFromMbe(
-            ModuleMXBeanEntry mbe) {
+            final ModuleMXBeanEntry mbe) {
         return new StubFactoryTemplate(getHeaderFromEntry(mbe),
                 mbe.getPackageName(), mbe.getStubFactoryName(),
                 mbe.getFullyQualifiedName(mbe.getAbstractFactoryName())
@@ -242,7 +242,7 @@ public class TemplateFactory {
     }
 
     public static GeneralInterfaceTemplate mXBeanInterfaceTemplateFromMbe(
-            ModuleMXBeanEntry mbe) {
+            final ModuleMXBeanEntry mbe) {
         MXBeanInterfaceAttributesProcessor attrProcessor = new MXBeanInterfaceAttributesProcessor();
         attrProcessor.processAttributes(mbe.getAttributes());
         GeneralInterfaceTemplate ifcTemplate = new GeneralInterfaceTemplate(
@@ -254,7 +254,7 @@ public class TemplateFactory {
     }
 
     public static Map<String, GeneralClassTemplate> tOsFromMbe(
-            ModuleMXBeanEntry mbe) {
+            final ModuleMXBeanEntry mbe) {
         Map<String, GeneralClassTemplate> retVal = Maps.newHashMap();
         TOAttributesProcessor processor = new TOAttributesProcessor();
         processor.processAttributes(mbe.getAttributes());
@@ -275,7 +275,7 @@ public class TemplateFactory {
     }
 
     public static Map<String, GeneralClassTemplate> tOsFromRbe(
-            RuntimeBeanEntry rbe) {
+            final RuntimeBeanEntry rbe) {
         Map<String, GeneralClassTemplate> retVal = Maps.newHashMap();
         TOAttributesProcessor processor = new TOAttributesProcessor();
         Map<String, AttributeIfc> yangPropertiesToTypesMap = Maps.newHashMap(rbe.getYangPropertiesToTypesMap());
@@ -316,7 +316,7 @@ public class TemplateFactory {
         return retVal;
     }
 
-    private static Header getHeaderFromEntry(AbstractEntry mbe) {
+    private static Header getHeaderFromEntry(final AbstractEntry mbe) {
         return new Header(mbe.getYangModuleName(), mbe.getYangModuleLocalname());
     }
 
@@ -326,7 +326,7 @@ public class TemplateFactory {
 
         private final List<TOInternal> tos = Lists.newArrayList();
 
-        void processAttributes(Map<String, AttributeIfc> attributes) {
+        void processAttributes(final Map<String, AttributeIfc> attributes) {
             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
                 AttributeIfc attributeIfc = attrEntry.getValue();
                 if (attributeIfc instanceof TOAttribute) {
@@ -342,7 +342,7 @@ public class TemplateFactory {
             }
         }
 
-        private void createTOInternal(TOAttribute toAttribute) {
+        private void createTOInternal(final TOAttribute toAttribute) {
 
             Map<String, AttributeIfc> attrs = toAttribute.getCapitalizedPropertiesToTypesMap();
             // recursive processing of TO's attributes
@@ -360,12 +360,12 @@ public class TemplateFactory {
             private List<Field> fields;
             private List<MethodDefinition> methods;
 
-            public TOInternal(Type type, Map<String, AttributeIfc> attrs) {
+            public TOInternal(final Type type, final Map<String, AttributeIfc> attrs) {
                 this(type.getFullyQualifiedName(), type.getName(), attrs, type.getPackageName());
             }
 
-            public TOInternal(String fullyQualifiedName, String name,
-                    Map<String, AttributeIfc> attrs, String packageName) {
+            public TOInternal(final String fullyQualifiedName, final String name,
+                    final Map<String, AttributeIfc> attrs, final String packageName) {
                 this.fullyQualifiedName = fullyQualifiedName;
                 this.name = name;
                 processAttrs(attrs, packageName);
@@ -374,7 +374,7 @@ public class TemplateFactory {
             private final static String dependencyResolverVarName = "dependencyResolver";
             private final static String dependencyResolverInjectMethodName = "injectDependencyResolver";
 
-            private void processAttrs(Map<String, AttributeIfc> attrs, String packageName) {
+            private void processAttrs(final Map<String, AttributeIfc> attrs, final String packageName) {
                 fields = Lists.newArrayList();
                 methods = Lists.newArrayList();
 
@@ -386,8 +386,7 @@ public class TemplateFactory {
 
                 for (Entry<String, AttributeIfc> attrEntry : attrs.entrySet()) {
                     String innerName = attrEntry.getKey();
-                    String varName = BindingGeneratorUtil
-                            .parseToValidParamName(attrEntry.getKey());
+                    String varName = BindingMapping.getPropertyName(attrEntry.getKey());
 
                     String fullyQualifiedName, nullableDefault = null;
                     if (attrEntry.getValue() instanceof TypedAttribute) {
@@ -449,7 +448,7 @@ public class TemplateFactory {
     private static class MXBeanInterfaceAttributesProcessor {
         private final List<MethodDeclaration> methods = Lists.newArrayList();
 
-        void processAttributes(Map<String, AttributeIfc> attributes) {
+        void processAttributes(final Map<String, AttributeIfc> attributes) {
             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
                 String returnType;
                 AttributeIfc attributeIfc = attrEntry.getValue();
@@ -473,8 +472,7 @@ public class TemplateFactory {
                 MethodDeclaration getter = new MethodDeclaration(returnType,
                         getterName, Collections.<Field> emptyList());
 
-                String varName = BindingGeneratorUtil
-                        .parseToValidParamName(attrEntry.getKey());
+                String varName = BindingMapping.getPropertyName(attrEntry.getKey());
                 String setterName = "set"
                         + attributeIfc.getUpperCaseCammelCase();
                 MethodDeclaration setter = new MethodDeclaration("void",
@@ -519,8 +517,8 @@ public class TemplateFactory {
 
         private final List<Field> fields = Lists.newArrayList();
 
-        void processAttributes(Map<String, AttributeIfc> attributes,
-                String packageName) {
+        void processAttributes(final Map<String, AttributeIfc> attributes,
+                final String packageName) {
             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
                 String type;
                 String nullableDefaultWrapped = null;
@@ -550,7 +548,7 @@ public class TemplateFactory {
             private final List<ModuleField> moduleFields;
             private final List<MethodDefinition> methods;
 
-            private Holder(List<ModuleField> moduleFields, List<MethodDefinition> methods) {
+            private Holder(final List<ModuleField> moduleFields, final List<MethodDefinition> methods) {
                 this.moduleFields = Collections.unmodifiableList(moduleFields);
                 this.methods = Collections.unmodifiableList(methods);
             }
@@ -559,11 +557,11 @@ public class TemplateFactory {
         private final Holder holder;
 
 
-        private AbstractModuleAttributesProcessor(Map<String, AttributeIfc> attributes) {
+        private AbstractModuleAttributesProcessor(final Map<String, AttributeIfc> attributes) {
             this.holder = processAttributes(attributes);
         }
 
-        private static Holder processAttributes(Map<String, AttributeIfc> attributes) {
+        private static Holder processAttributes(final Map<String, AttributeIfc> attributes) {
             List<ModuleField> moduleFields = new ArrayList<>();
             List<MethodDefinition> methods = new ArrayList<>();
             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
@@ -607,8 +605,7 @@ public class TemplateFactory {
                     }
                 }
 
-                String varName = BindingGeneratorUtil
-                        .parseToValidParamName(attrEntry.getKey());
+                String varName = BindingMapping.getPropertyName(attrEntry.getKey());
 
                 ModuleField field;
                 if (isIdentity) {
@@ -689,7 +686,7 @@ public class TemplateFactory {
     }
 
 
-    private static boolean needsDepResolver(AttributeIfc value) {
+    private static boolean needsDepResolver(final AttributeIfc value) {
         if(value instanceof TOAttribute) {
             return true;
         }
@@ -701,7 +698,7 @@ public class TemplateFactory {
         return false;
     }
 
-    private static String getInnerTypeFromIdentity(Type type) {
+    private static String getInnerTypeFromIdentity(final Type type) {
         Preconditions.checkArgument(type instanceof ParameterizedType);
         Type[] args = ((ParameterizedType) type).getActualTypeArguments();
         Preconditions.checkArgument(args.length ==1);
index a6cfc58..3dae004 100644 (file)
@@ -16,11 +16,8 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
-
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.Lists;
@@ -42,7 +39,6 @@ import java.util.Set;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import org.apache.commons.io.FileUtils;
-import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.project.MavenProject;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.compiler.IProblem;
@@ -124,13 +120,6 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
         File targetDir = new File(generatorOutputPath, "target");
         generatedResourcesDir = new File(targetDir, "generated-resources");
         jmxGenerator.setResourceBaseDir(generatedResourcesDir);
-        Log mockedLog = mock(Log.class);
-        doReturn(false).when(mockedLog).isDebugEnabled();
-        doNothing().when(mockedLog).debug(any(CharSequence.class));
-        doNothing().when(mockedLog).info(any(CharSequence.class));
-        doNothing().when(mockedLog).error(any(CharSequence.class),
-                any(Throwable.class));
-        jmxGenerator.setLog(mockedLog);
         MavenProject project = mock(MavenProject.class);
         doReturn(generatorOutputPath).when(project).getBasedir();
         jmxGenerator.setMavenProject(project);
@@ -158,18 +147,19 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
         verifyModuleFactoryFile(false);
     }
 
-    private void verifyModuleFactoryFile(boolean shouldBePresent) {
+    private void verifyModuleFactoryFile(final boolean shouldBePresent) {
         File factoryFile = new File(generatedResourcesDir, "META-INF"
                 + File.separator + "services" + File.separator
                 + ModuleFactory.class.getName());
-        if (!shouldBePresent)
+        if (!shouldBePresent) {
             assertFalse("Factory file should not be generated",
                     factoryFile.exists());
-        else
+        } else {
             assertTrue("Factory file should be generated", factoryFile.exists());
+        }
     }
 
-    public static List<String> toFileNames(Collection<File> files) {
+    public static List<String> toFileNames(final Collection<File> files) {
         List<String> result = new ArrayList<>();
         for (File f : files) {
             result.add(f.getName());
@@ -279,7 +269,7 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
                 new Predicate<File>() {
 
                     @Override
-                    public boolean apply(File input) {
+                    public boolean apply(final File input) {
                         return input.getName().endsWith("xml");
                     }
                 });
@@ -288,7 +278,7 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
                 new Predicate<File>() {
 
                     @Override
-                    public boolean apply(File input) {
+                    public boolean apply(final File input) {
                         return input.getName().endsWith("java");
                     }
                 });
@@ -303,16 +293,21 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
             String name = file.getName();
             MbeASTVisitor visitor = new MbeASTVisitor();
             verifiers.put(name, visitor);
-            if (name.equals("AbstractDynamicThreadPoolModule.java"))
+            if (name.equals("AbstractDynamicThreadPoolModule.java")) {
                 abstractDynamicThreadPoolModuleVisitor = visitor;
-            if (name.equals("AsyncEventBusModuleMXBean.java"))
+            }
+            if (name.equals("AsyncEventBusModuleMXBean.java")) {
                 asyncEventBusModuleMXBeanVisitor = visitor;
-            if (name.equals("AbstractNamingThreadFactoryModuleFactory.java"))
+            }
+            if (name.equals("AbstractNamingThreadFactoryModuleFactory.java")) {
                 abstractNamingThreadFactoryModuleFactoryVisitor = visitor;
-            if (name.equals("AsyncEventBusModule.java"))
+            }
+            if (name.equals("AsyncEventBusModule.java")) {
                 asyncEventBusModuleVisitor = visitor;
-            if (name.equals("EventBusModuleFactory.java"))
+            }
+            if (name.equals("EventBusModuleFactory.java")) {
                 eventBusModuleFactoryVisitor = visitor;
+            }
         }
 
         processGeneratedCode(javaFiles, verifiers);
@@ -348,25 +343,25 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
 
     }
 
-    private void verifyXmlFiles(Collection<File> xmlFiles) throws Exception {
+    private void verifyXmlFiles(final Collection<File> xmlFiles) throws Exception {
         ErrorHandler errorHandler = new ErrorHandler() {
 
             @Override
-            public void warning(SAXParseException exception)
+            public void warning(final SAXParseException exception)
                     throws SAXException {
                 fail("Generated blueprint xml is not well formed "
                         + exception.getMessage());
             }
 
             @Override
-            public void fatalError(SAXParseException exception)
+            public void fatalError(final SAXParseException exception)
                     throws SAXException {
                 fail("Generated blueprint xml is not well formed "
                         + exception.getMessage());
             }
 
             @Override
-            public void error(SAXParseException exception) throws SAXException {
+            public void error(final SAXParseException exception) throws SAXException {
                 fail("Generated blueprint xml is not well formed "
                         + exception.getMessage());
             }
@@ -386,7 +381,7 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
 
     }
 
-    private void assertEventBusModuleFactory(MbeASTVisitor visitor) {
+    private void assertEventBusModuleFactory(final MbeASTVisitor visitor) {
         assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
                 + ".threads.java", visitor.packageName);
         assertEquals("EventBusModuleFactory", visitor.type);
@@ -406,7 +401,7 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
                 visitor.methodJavadoc.size());
     }
 
-    private void assertAsyncEventBusModule(MbeASTVisitor visitor) {
+    private void assertAsyncEventBusModule(final MbeASTVisitor visitor) {
         assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
                 + ".threads.java", visitor.packageName);
         assertEquals("AsyncEventBusModule", visitor.type);
@@ -427,7 +422,7 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
     }
 
     private void assertAbstractNamingThreadFactoryModuleFactory(
-            MbeASTVisitor visitor) {
+            final MbeASTVisitor visitor) {
         assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
                 + ".threads.java", visitor.packageName);
         assertEquals("AbstractNamingThreadFactoryModuleFactory", visitor.type);
@@ -450,7 +445,7 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
 
     }
 
-    private void assertFactoryMethods(Set<String> methods, int expectedSize) {
+    private void assertFactoryMethods(final Set<String> methods, final int expectedSize) {
 
         List<ArgumentAssertion> args = Lists.newArrayList();
         ArgumentAssertion oldInstanceArg = new ArgumentAssertion(DynamicMBeanWithInstance.class.getCanonicalName(), "old");
@@ -496,12 +491,12 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
 
     }
 
-    private void assertMethodPresent(Set<String> methods, MethodAssertion methodAssertion) {
+    private void assertMethodPresent(final Set<String> methods, final MethodAssertion methodAssertion) {
         assertTrue(String.format("Generated methods did not contain %s, generated methods: %s",
                 methodAssertion.toString(), methods), methods.contains(methodAssertion.toString()));
     }
 
-    private void assertAsyncEventBusModuleMXBean(MbeASTVisitor visitor) {
+    private void assertAsyncEventBusModuleMXBean(final MbeASTVisitor visitor) {
         assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
                 + ".threads.java", visitor.packageName);
         assertEquals("AsyncEventBusModuleMXBean", visitor.type);
@@ -511,7 +506,7 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
 
     }
 
-    private void assertAbstractDynamicThreadPoolModule(MbeASTVisitor visitor) {
+    private void assertAbstractDynamicThreadPoolModule(final MbeASTVisitor visitor) {
         assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
                 + ".threads.java", visitor.packageName);
         assertNotNull(visitor.javadoc);
@@ -557,8 +552,8 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
                 visitor.methodJavadoc.get("void setMaximumSize(java.lang.Long maximumSize)"));
     }
 
-    private void assertDeclaredField(Set<String> fieldDeclarations,
-            String declaration) {
+    private void assertDeclaredField(final Set<String> fieldDeclarations,
+            final String declaration) {
         assertTrue("Missing field " + declaration + ", got: "
                 + fieldDeclarations,
                 fieldDeclarations.contains(declaration + ";\n"));
@@ -570,13 +565,13 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
         protected Map<String, String> methodDescriptions = Maps.newHashMap();
 
         @Override
-        public boolean visit(PackageDeclaration node) {
+        public boolean visit(final PackageDeclaration node) {
             packageName = node.getName().toString();
             return super.visit(node);
         }
 
         @Override
-        public boolean visit(NormalAnnotation node) {
+        public boolean visit(final NormalAnnotation node) {
             if (node.getTypeName().toString()
                     .equals(Description.class.getCanonicalName())) {
                 if (node.getParent() instanceof TypeDeclaration) {
@@ -604,7 +599,7 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
         }
 
         @Override
-        public boolean visit(TypeDeclaration node) {
+        public boolean visit(final TypeDeclaration node) {
             javadoc = node.getJavadoc() == null ? null : node.getJavadoc()
                     .toString();
             type = node.getName().toString();
@@ -624,7 +619,7 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
         private final Map<String, String> methodJavadoc = Maps.newHashMap();
 
         @Override
-        public boolean visit(NormalAnnotation node) {
+        public boolean visit(final NormalAnnotation node) {
             boolean result = super.visit(node);
             if (node.getTypeName().toString()
                     .equals(RequireInterface.class.getCanonicalName())
@@ -638,16 +633,16 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
         }
 
         @Override
-        public boolean visit(FieldDeclaration node) {
+        public boolean visit(final FieldDeclaration node) {
             fieldDeclarations.add(node.toString());
             return super.visit(node);
         }
 
         @Override
-        public boolean visit(MethodDeclaration node) {
-            if (node.isConstructor())
+        public boolean visit(final MethodDeclaration node) {
+            if (node.isConstructor()) {
                 constructors.add(node.toString());
-            else {
+            else {
                 String methodSignature = node.getReturnType2() + " " + node.getName() + "(";
                 boolean first = true;
                 for (Object o : node.parameters()) {
@@ -668,7 +663,7 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
         }
 
         @Override
-        public boolean visit(TypeDeclaration node) {
+        public boolean visit(final TypeDeclaration node) {
             boolean visit = super.visit(node);
             List<?> superIfcs = node.superInterfaceTypes();
             implmts = superIfcs != null && !superIfcs.isEmpty() ? superIfcs
@@ -680,14 +675,14 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
 
     }
 
-    private void assertContains(String source, String... contained) {
+    private void assertContains(final String source, final String... contained) {
         for (String string : contained) {
             assertThat(source, containsString(string));
         }
     }
 
-    private void processGeneratedCode(Collection<File> files,
-            Map<String, ASTVisitor> verifiers) throws IOException {
+    private void processGeneratedCode(final Collection<File> files,
+            final Map<String, ASTVisitor> verifiers) throws IOException {
         ASTParser parser = ASTParser.newParser(AST.JLS3);
         Map<?, ?> options = JavaCore.getOptions();
         JavaCore.setComplianceOptions(JavaCore.VERSION_1_7, options);
@@ -705,27 +700,31 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
             for (IProblem c : cu.getProblems()) {
                 // 1610613332 = Syntax error, annotations are only available if
                 // source level is 5.0
-                if (c.getID() == 1610613332)
+                if (c.getID() == 1610613332) {
                     continue;
+                }
                 // 1610613332 = Syntax error, parameterized types are only
                 // available if source level is 5.0
-                if (c.getID() == 1610613329)
+                if (c.getID() == 1610613329) {
                     continue;
-                if (c.getID() == 1610613328) // 'for each' statements are only available if source level is 5.0
+                }
+                if (c.getID() == 1610613328) {
                     continue;
+                }
                 fail("Error in generated source code " + file + ":"
                         + c.getSourceLineNumber() + " id: " + c.getID() + " message:"  + c.toString());
             }
 
             ASTVisitor visitor = verifiers.get(file.getName());
-            if (visitor == null)
+            if (visitor == null) {
                 fail("Unknown generated file " + file.getName());
+            }
             cu.accept(visitor);
 
         }
     }
 
-    public static char[] readFileAsChars(File file) throws IOException {
+    public static char[] readFileAsChars(final File file) throws IOException {
         List<String> readLines = Files
                 .readLines(file, Charset.forName("utf-8"));
         char[] retVal = new char[0];
@@ -741,15 +740,15 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
 
     private static class MethodAssertion extends ArgumentAssertion{
 
-        private List<ArgumentAssertion> arguments;
+        private final List<ArgumentAssertion> arguments;
 
 
-        MethodAssertion(String type, String name, List<ArgumentAssertion> arguments) {
+        MethodAssertion(final String type, final String name, final List<ArgumentAssertion> arguments) {
             super(type, name);
             this.arguments = arguments;
         }
 
-        MethodAssertion(String type, String name) {
+        MethodAssertion(final String type, final String name) {
             this(type, name, Collections.<ArgumentAssertion>emptyList());
         }
 
@@ -763,8 +762,9 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
             for (ArgumentAssertion argument : arguments) {
                 sb.append(argument.type).append(' ');
                 sb.append(argument.name);
-                if(++i != arguments.size())
+                if(++i != arguments.size()) {
                     sb.append(',');
+                }
             }
             sb.append(')');
             return sb.toString();
@@ -775,7 +775,7 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
 
         protected final String type, name;
 
-        private ArgumentAssertion(String type, String name) {
+        private ArgumentAssertion(final String type, final String name) {
             this.type = type;
             this.name = name;
         }
index 8e088ba..ccb7219 100644 (file)
@@ -19,7 +19,6 @@
         <dependency>\r
             <groupId>org.opendaylight.controller</groupId>\r
             <artifactId>ietf-netconf-notifications</artifactId>\r
-            <version>0.3.0-SNAPSHOT</version>\r
         </dependency>\r
         <dependency>\r
             <groupId>org.opendaylight.controller</groupId>\r
@@ -95,7 +94,6 @@
             <plugin>\r
                 <groupId>org.codehaus.mojo</groupId>\r
                 <artifactId>build-helper-maven-plugin</artifactId>\r
-                <version>1.8</version>\r
                 <executions>\r
                     <execution>\r
                         <id>add-source</id>\r
index aebde0c..a324130 100644 (file)
@@ -63,10 +63,7 @@ public class Topic implements DataChangeListener {
     public void notifyNode(final NodeId nodeId) {
         JoinTopicInput jti = getJoinTopicInputArgument(nodeId);
         EventSourceService ess = mdSal.getRpcService(EventSourceService.class);
-
-        if (ess == null) {
-            throw new IllegalStateException("EventSourceService is not registered.");
-        }
+        Preconditions.checkState(ess != null, "EventSourceService is not registered");
 
         ess.joinTopic(jti);
     }
index e2aa169..1aecc89 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.cluster.raft;
 
+import com.google.common.base.Preconditions;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -187,9 +188,14 @@ public abstract class AbstractReplicatedLogImpl implements ReplicatedLog {
 
     @Override
     public void snapshotPreCommit(long snapshotCapturedIndex, long snapshotCapturedTerm) {
+        Preconditions.checkArgument(snapshotCapturedIndex >= snapshotIndex,
+                "snapshotCapturedIndex must be greater than or equal to snapshotIndex");
+
         snapshottedJournal = new ArrayList<>(journal.size());
 
-        snapshottedJournal.addAll(journal.subList(0, (int)(snapshotCapturedIndex - snapshotIndex)));
+        List<ReplicatedLogEntry> snapshotJournalEntries = journal.subList(0, (int) (snapshotCapturedIndex - snapshotIndex));
+
+        snapshottedJournal.addAll(snapshotJournalEntries);
         clear(0, (int) (snapshotCapturedIndex - snapshotIndex));
 
         previousSnapshotIndex = snapshotIndex;
index 78a1335..fd49737 100644 (file)
@@ -75,7 +75,7 @@ public interface ConfigParams {
      * The interval in which the leader needs to check itself if its isolated
      * @return FiniteDuration
      */
-    FiniteDuration getIsolatedCheckInterval();
+    long getIsolatedCheckIntervalInMillis();
 
 
     /**
index 86867e1..3e6742c 100644 (file)
@@ -42,8 +42,7 @@ public class DefaultConfigParamsImpl implements ConfigParams {
     private FiniteDuration heartBeatInterval = HEART_BEAT_INTERVAL;
     private long snapshotBatchCount = SNAPSHOT_BATCH_COUNT;
     private int journalRecoveryLogBatchSize = JOURNAL_RECOVERY_LOG_BATCH_SIZE;
-    private FiniteDuration isolatedLeaderCheckInterval =
-        new FiniteDuration(HEART_BEAT_INTERVAL.length() * 1000, HEART_BEAT_INTERVAL.unit());
+    private long isolatedLeaderCheckInterval = HEART_BEAT_INTERVAL.$times(1000).toMillis();
 
     // 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
@@ -68,7 +67,7 @@ public class DefaultConfigParamsImpl implements ConfigParams {
     }
 
     public void setIsolatedLeaderCheckInterval(FiniteDuration isolatedLeaderCheckInterval) {
-        this.isolatedLeaderCheckInterval = isolatedLeaderCheckInterval;
+        this.isolatedLeaderCheckInterval = isolatedLeaderCheckInterval.toMillis();
     }
 
     public void setElectionTimeoutFactor(long electionTimeoutFactor){
@@ -112,7 +111,7 @@ public class DefaultConfigParamsImpl implements ConfigParams {
     }
 
     @Override
-    public FiniteDuration getIsolatedCheckInterval() {
+    public long getIsolatedCheckIntervalInMillis() {
         return isolatedLeaderCheckInterval;
     }
 
index 935c4f0..04b9f16 100644 (file)
@@ -100,4 +100,16 @@ public class FollowerLogInformationImpl implements FollowerLogInformation {
     public long timeSinceLastActivity() {
         return stopwatch.elapsed(TimeUnit.MILLISECONDS);
     }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("FollowerLogInformationImpl [id=").append(id).append(", nextIndex=").append(nextIndex)
+                .append(", matchIndex=").append(matchIndex).append(", stopwatch=")
+                .append(stopwatch.elapsed(TimeUnit.MILLISECONDS))
+                .append(", followerTimeoutMillis=").append(followerTimeoutMillis).append("]");
+        return builder.toString();
+    }
+
+
 }
index 854ceb2..285be39 100644 (file)
@@ -22,6 +22,7 @@ import com.google.common.base.Stopwatch;
 import com.google.protobuf.ByteString;
 import java.io.Serializable;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 import org.opendaylight.controller.cluster.DataPersistenceProvider;
 import org.opendaylight.controller.cluster.common.actor.AbstractUntypedPersistentActor;
 import org.opendaylight.controller.cluster.notifications.RoleChanged;
@@ -82,6 +83,9 @@ import org.slf4j.LoggerFactory;
  * </ul>
  */
 public abstract class RaftActor extends AbstractUntypedPersistentActor {
+
+    private static final long APPLY_STATE_DELAY_THRESHOLD_IN_NANOS = TimeUnit.MILLISECONDS.toNanos(50L); // 50 millis
+
     protected final Logger LOG = LoggerFactory.getLogger(getClass());
 
     /**
@@ -278,6 +282,12 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor {
         if (message instanceof ApplyState){
             ApplyState applyState = (ApplyState) message;
 
+            long elapsedTime = (System.nanoTime() - applyState.getStartTime());
+            if(elapsedTime >= APPLY_STATE_DELAY_THRESHOLD_IN_NANOS){
+                LOG.warn("ApplyState took more time than expected. Elapsed Time = {} ms ApplyState = {}",
+                        TimeUnit.NANOSECONDS.toMillis(elapsedTime), applyState);
+            }
+
             if(LOG.isDebugEnabled()) {
                 LOG.debug("{}: Applying state for log index {} data {}",
                     persistenceId(), applyState.getReplicatedLogEntry().getIndex(),
@@ -667,12 +677,22 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor {
             context.getReplicatedLog().snapshotPreCommit(captureSnapshot.getLastAppliedIndex(),
                     captureSnapshot.getLastAppliedTerm());
 
-        } else {
+            getCurrentBehavior().setReplicatedToAllIndex(captureSnapshot.getReplicatedToAllIndex());
+        } else if(captureSnapshot.getReplicatedToAllIndex() != -1){
             // clear the log based on replicatedToAllIndex
             context.getReplicatedLog().snapshotPreCommit(captureSnapshot.getReplicatedToAllIndex(),
                     captureSnapshot.getReplicatedToAllTerm());
+
+            getCurrentBehavior().setReplicatedToAllIndex(captureSnapshot.getReplicatedToAllIndex());
+        } else {
+            // The replicatedToAllIndex was not found in the log
+            // This means that replicatedToAllIndex never moved beyond -1 or that it is already in the snapshot.
+            // In this scenario we may need to save the snapshot to the akka persistence
+            // snapshot for recovery but we do not need to do the replicated log trimming.
+            context.getReplicatedLog().snapshotPreCommit(replicatedLog.getSnapshotIndex(),
+                    replicatedLog.getSnapshotTerm());
         }
-        getCurrentBehavior().setReplicatedToAllIndex(captureSnapshot.getReplicatedToAllIndex());
+
 
         LOG.info("{}: Removed in-memory snapshotted entries, adjusted snaphsotIndex:{} " +
             "and term:{}", persistenceId(), captureSnapshot.getLastAppliedIndex(),
@@ -788,7 +808,9 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor {
 
                             dataSizeSinceLastSnapshot = 0;
 
-                            LOG.info("{}: Initiating Snapshot Capture..", persistenceId());
+                            LOG.info("{}: Initiating Snapshot Capture, journalSize = {}, dataSizeForCheck = {}," +
+                                " dataThreshold = {}", persistenceId(), journalSize, dataSizeForCheck, dataThreshold);
+
                             long lastAppliedIndex = -1;
                             long lastAppliedTerm = -1;
 
index 0a7a632..9299e75 100644 (file)
@@ -9,21 +9,22 @@
 package org.opendaylight.controller.cluster.raft.base.messages;
 
 import akka.actor.ActorRef;
-import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
-
 import java.io.Serializable;
+import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
 
 public class ApplyState implements Serializable {
     private static final long serialVersionUID = 1L;
     private final ActorRef clientActor;
     private final String identifier;
     private final ReplicatedLogEntry replicatedLogEntry;
+    private final long startTime;
 
     public ApplyState(ActorRef clientActor, String identifier,
         ReplicatedLogEntry replicatedLogEntry) {
         this.clientActor = clientActor;
         this.identifier = identifier;
         this.replicatedLogEntry = replicatedLogEntry;
+        this.startTime = System.nanoTime();
     }
 
     public ActorRef getClientActor() {
@@ -37,4 +38,17 @@ public class ApplyState implements Serializable {
     public ReplicatedLogEntry getReplicatedLogEntry() {
         return replicatedLogEntry;
     }
+
+    public long getStartTime() {
+        return startTime;
+    }
+
+    @Override
+    public String toString() {
+        return "ApplyState{" +
+                "identifier='" + identifier + '\'' +
+                ", replicatedLogEntry.index =" + replicatedLogEntry.getIndex() +
+                ", startTime=" + startTime +
+                '}';
+    }
 }
index b2bb127..be51ba0 100644 (file)
@@ -126,6 +126,9 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior {
         // (heartbeat) to each server; repeat during idle periods to
         // prevent election timeouts (§5.2)
         sendAppendEntries(0, false);
+
+        // It is important to schedule this heartbeat here
+        scheduleHeartBeat(context.getConfigParams().getHeartBeatInterval());
     }
 
     /**
@@ -171,6 +174,14 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior {
             return this;
         }
 
+        if(followerLogInformation.timeSinceLastActivity() >
+                context.getConfigParams().getElectionTimeOutInterval().toMillis()) {
+            LOG.error("{} : handleAppendEntriesReply delayed beyond election timeout, " +
+                            "appendEntriesReply : {}, timeSinceLastActivity : {}, lastApplied : {}, commitIndex : {}",
+                    logName(), appendEntriesReply, followerLogInformation.timeSinceLastActivity(),
+                    context.getLastApplied(), context.getCommitIndex());
+        }
+
         followerLogInformation.markFollowerActive();
 
         if (appendEntriesReply.isSuccess()) {
@@ -273,6 +284,8 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior {
         return this;
     }
 
+    protected void beforeSendHeartbeat(){}
+
     @Override
     public RaftActorBehavior handleMessage(ActorRef sender, Object originalMessage) {
         Preconditions.checkNotNull(sender, "sender should not be null");
@@ -294,27 +307,26 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior {
             }
         }
 
-        try {
-            if (message instanceof SendHeartBeat) {
-                sendHeartBeat();
-                return this;
+        if (message instanceof SendHeartBeat) {
+            beforeSendHeartbeat();
+            sendHeartBeat();
+            scheduleHeartBeat(context.getConfigParams().getHeartBeatInterval());
+            return this;
 
-            } else if(message instanceof SendInstallSnapshot) {
-                // received from RaftActor
-                setSnapshot(Optional.of(((SendInstallSnapshot) message).getSnapshot()));
-                sendInstallSnapshot();
+        } else if(message instanceof SendInstallSnapshot) {
+            // received from RaftActor
+            setSnapshot(Optional.of(((SendInstallSnapshot) message).getSnapshot()));
+            sendInstallSnapshot();
 
-            } else if (message instanceof Replicate) {
-                replicate((Replicate) message);
+        } else if (message instanceof Replicate) {
+            replicate((Replicate) message);
 
-            } else if (message instanceof InstallSnapshotReply){
-                handleInstallSnapshotReply((InstallSnapshotReply) message);
+        } else if (message instanceof InstallSnapshotReply){
+            handleInstallSnapshotReply((InstallSnapshotReply) message);
 
-            }
-        } finally {
-            scheduleHeartBeat(context.getConfigParams().getHeartBeatInterval());
         }
 
+
         return super.handleMessage(sender, message);
     }
 
index 1e4fcf7..c799441 100644 (file)
@@ -10,7 +10,6 @@ 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;
@@ -330,12 +329,13 @@ public class Follower extends AbstractRaftActorBehavior {
         }
     }
 
-    @Override public void close() throws Exception {
+    @Override
+    public void close() throws Exception {
         stopElection();
     }
 
     @VisibleForTesting
-    ByteString getSnapshotChunksCollected(){
-        return snapshotTracker != null ? snapshotTracker.getCollectedChunks() : ByteString.EMPTY;
+    SnapshotTracker getSnapshotTracker(){
+        return snapshotTracker;
     }
 }
index 7a94c0c..ebcdcd4 100644 (file)
@@ -8,12 +8,12 @@
 package org.opendaylight.controller.cluster.raft.behaviors;
 
 import akka.actor.ActorRef;
-import akka.actor.Cancellable;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
+import com.google.common.base.Stopwatch;
+import java.util.concurrent.TimeUnit;
 import org.opendaylight.controller.cluster.raft.RaftActorContext;
 import org.opendaylight.controller.cluster.raft.base.messages.IsolatedLeaderCheck;
-import scala.concurrent.duration.FiniteDuration;
 
 /**
  * The behavior of a RaftActor when it is in the Leader state
@@ -38,15 +38,12 @@ import scala.concurrent.duration.FiniteDuration;
  * set commitIndex = N (§5.3, §5.4).
  */
 public class Leader extends AbstractLeader {
-    private Cancellable installSnapshotSchedule = null;
-    private Cancellable isolatedLeaderCheckSchedule = null;
+    private static final IsolatedLeaderCheck ISOLATED_LEADER_CHECK = new IsolatedLeaderCheck();
+    private final Stopwatch isolatedLeaderCheck;
 
     public Leader(RaftActorContext context) {
         super(context);
-
-        scheduleIsolatedLeaderCheck(
-            new FiniteDuration(context.getConfigParams().getHeartBeatInterval().length() * 10,
-                context.getConfigParams().getHeartBeatInterval().unit()));
+        isolatedLeaderCheck = Stopwatch.createStarted();
     }
 
     @Override public RaftActorBehavior handleMessage(ActorRef sender, Object originalMessage) {
@@ -54,8 +51,9 @@ public class Leader extends AbstractLeader {
 
         if (originalMessage instanceof IsolatedLeaderCheck) {
             if (isLeaderIsolated()) {
-                LOG.info("{}: At least {} followers need to be active, Switching {} from Leader to IsolatedLeader",
+                LOG.warn("{}: At least {} followers need to be active, Switching {} from Leader to IsolatedLeader",
                         context.getId(), minIsolatedLeaderPeerCount, leaderId);
+
                 return switchBehavior(new IsolatedLeader(context));
             }
         }
@@ -63,21 +61,17 @@ public class Leader extends AbstractLeader {
         return super.handleMessage(sender, originalMessage);
     }
 
-    protected void stopIsolatedLeaderCheckSchedule() {
-        if (isolatedLeaderCheckSchedule != null && !isolatedLeaderCheckSchedule.isCancelled()) {
-            isolatedLeaderCheckSchedule.cancel();
+    @Override
+    protected void beforeSendHeartbeat(){
+        if(isolatedLeaderCheck.elapsed(TimeUnit.MILLISECONDS) > context.getConfigParams().getIsolatedCheckIntervalInMillis()){
+            context.getActor().tell(ISOLATED_LEADER_CHECK, context.getActor());
+            isolatedLeaderCheck.reset().start();
         }
-    }
 
-    protected void scheduleIsolatedLeaderCheck(FiniteDuration isolatedCheckInterval) {
-        isolatedLeaderCheckSchedule = context.getActorSystem().scheduler().schedule(isolatedCheckInterval, isolatedCheckInterval,
-            context.getActor(), new IsolatedLeaderCheck(),
-            context.getActorSystem().dispatcher(), context.getActor());
     }
 
     @Override
     public void close() throws Exception {
-        stopIsolatedLeaderCheckSchedule();
         super.close();
     }
 
index 119b43c..13636f3 100644 (file)
@@ -73,6 +73,7 @@ public class InstallSnapshot extends AbstractRaftRPC {
 
     public <T extends Object> Object toSerializable(){
         InstallSnapshotMessages.InstallSnapshot.Builder builder = InstallSnapshotMessages.InstallSnapshot.newBuilder()
+                .setTerm(this.getTerm())
                 .setLeaderId(this.getLeaderId())
                 .setChunkIndex(this.getChunkIndex())
                 .setData(this.getData())
index 4d33152..297d781 100644 (file)
@@ -53,7 +53,7 @@ public class MockRaftActorContext implements RaftActorContext {
              * Identifier of the actor whose election term information this is
              */
             private final String id = id1;
-            private long currentTerm = 0;
+            private long currentTerm = 1;
             private String votedFor = "";
 
             @Override
@@ -88,8 +88,9 @@ public class MockRaftActorContext implements RaftActorContext {
 
     public void initReplicatedLog(){
         this.replicatedLog = new SimpleReplicatedLog();
-        this.replicatedLog.append(new MockReplicatedLogEntry(1, 0, new MockPayload("1")));
-        this.replicatedLog.append(new MockReplicatedLogEntry(1, 1, new MockPayload("2")));
+        long term = getTermInformation().getCurrentTerm();
+        this.replicatedLog.append(new MockReplicatedLogEntry(term, 0, new MockPayload("1")));
+        this.replicatedLog.append(new MockReplicatedLogEntry(term, 1, new MockPayload("2")));
     }
 
     @Override public ActorRef actorOf(Props props) {
@@ -133,6 +134,16 @@ public class MockRaftActorContext implements RaftActorContext {
     }
 
     @Override
+    // FIXME : A lot of tests try to manipulate the replicated log by setting it using this method
+    // This is OK to do if the underlyingActor is not RafActor or a derived class. If not then you should not
+    // used this way to manipulate the log because the RaftActor actually has a field replicatedLog
+    // which it creates internally and sets on the RaftActorContext
+    // The only right way to manipulate the replicated log therefore is to get it from either the RaftActor
+    // or the RaftActorContext and modify the entries in there instead of trying to replace it by using this setter
+    // Simple assertion that will fail if you do so
+    // ReplicatedLog log = new ReplicatedLogImpl();
+    // raftActor.underlyingActor().getRaftActorContext().setReplicatedLog(log);
+    // assertEquals(log, raftActor.underlyingActor().getReplicatedLog())
     public void setReplicatedLog(ReplicatedLog replicatedLog) {
         this.replicatedLog = replicatedLog;
     }
@@ -255,6 +266,36 @@ public class MockRaftActorContext implements RaftActorContext {
         public String toString() {
             return value;
         }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((value == null) ? 0 : value.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            MockPayload other = (MockPayload) obj;
+            if (value == null) {
+                if (other.value != null) {
+                    return false;
+                }
+            } else if (!value.equals(other.value)) {
+                return false;
+            }
+            return true;
+        }
     }
 
     public static class MockReplicatedLogEntry implements ReplicatedLogEntry, Serializable {
@@ -287,6 +328,52 @@ public class MockRaftActorContext implements RaftActorContext {
         public int size() {
             return getData().size();
         }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((data == null) ? 0 : data.hashCode());
+            result = prime * result + (int) (index ^ (index >>> 32));
+            result = prime * result + (int) (term ^ (term >>> 32));
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            MockReplicatedLogEntry other = (MockReplicatedLogEntry) obj;
+            if (data == null) {
+                if (other.data != null) {
+                    return false;
+                }
+            } else if (!data.equals(other.data)) {
+                return false;
+            }
+            if (index != other.index) {
+                return false;
+            }
+            if (term != other.term) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("MockReplicatedLogEntry [term=").append(term).append(", index=").append(index)
+                    .append(", data=").append(data).append("]");
+            return builder.toString();
+        }
     }
 
     public static class MockReplicatedLogBuilder {
index 1cd8550..56bfc21 100644 (file)
@@ -552,7 +552,6 @@ public class RaftActorTest extends AbstractActorTest {
                 assertNotEquals("voted for", "foobar", mockRaftActor.getRaftActorContext().getTermInformation().getVotedFor());
 
                 mockRaftActor.onReceiveRecover(mock(RecoveryCompleted.class));
-
             }};
     }
 
@@ -576,12 +575,12 @@ public class RaftActorTest extends AbstractActorTest {
 
                 MockRaftActor mockRaftActor = mockActorRef.underlyingActor();
 
+                mockRaftActor.waitForInitializeBehaviorComplete();
+
                 mockRaftActor.getRaftActorContext().getTermInformation().updateAndPersist(10, "foobar");
 
                 assertEquals("Persist called", true, persistLatch.await(5, TimeUnit.SECONDS));
-
             }
-
         };
     }
 
@@ -602,14 +601,14 @@ public class RaftActorTest extends AbstractActorTest {
 
                 MockRaftActor mockRaftActor = mockActorRef.underlyingActor();
 
+                mockRaftActor.waitForInitializeBehaviorComplete();
+
                 MockRaftActorContext.MockReplicatedLogEntry logEntry = new MockRaftActorContext.MockReplicatedLogEntry(10, 10, mock(Payload.class));
 
                 mockRaftActor.getRaftActorContext().getReplicatedLog().appendAndPersist(logEntry);
 
                 verify(dataPersistenceProvider).persist(eq(logEntry), any(Procedure.class));
-
             }
-
         };
     }
 
@@ -630,14 +629,14 @@ public class RaftActorTest extends AbstractActorTest {
 
                 MockRaftActor mockRaftActor = mockActorRef.underlyingActor();
 
+                mockRaftActor.waitForInitializeBehaviorComplete();
+
                 mockRaftActor.getReplicatedLog().appendAndPersist(new MockRaftActorContext.MockReplicatedLogEntry(1, 0, mock(Payload.class)));
 
                 mockRaftActor.getRaftActorContext().getReplicatedLog().removeFromAndPersist(0);
 
                 verify(dataPersistenceProvider, times(2)).persist(anyObject(), any(Procedure.class));
-
             }
-
         };
     }
 
@@ -658,6 +657,8 @@ public class RaftActorTest extends AbstractActorTest {
 
                 MockRaftActor mockRaftActor = mockActorRef.underlyingActor();
 
+                mockRaftActor.waitForInitializeBehaviorComplete();
+
                 mockRaftActor.onReceiveCommand(new ApplyLogEntries(10));
 
                 verify(dataPersistenceProvider, times(1)).persist(anyObject(), any(Procedure.class));
@@ -685,6 +686,8 @@ public class RaftActorTest extends AbstractActorTest {
 
                 MockRaftActor mockRaftActor = mockActorRef.underlyingActor();
 
+                mockRaftActor.waitForInitializeBehaviorComplete();
+
                 ByteString snapshotBytes = fromObject(Arrays.asList(
                         new MockRaftActorContext.MockPayload("A"),
                         new MockRaftActorContext.MockPayload("B"),
@@ -722,6 +725,8 @@ public class RaftActorTest extends AbstractActorTest {
 
                 MockRaftActor mockRaftActor = mockActorRef.underlyingActor();
 
+                mockRaftActor.waitForInitializeBehaviorComplete();
+
                 mockRaftActor.getReplicatedLog().append(new MockRaftActorContext.MockReplicatedLogEntry(1, 0, mock(Payload.class)));
                 mockRaftActor.getReplicatedLog().append(new MockRaftActorContext.MockReplicatedLogEntry(1, 1, mock(Payload.class)));
                 mockRaftActor.getReplicatedLog().append(new MockRaftActorContext.MockReplicatedLogEntry(1, 2, mock(Payload.class)));
@@ -783,6 +788,8 @@ public class RaftActorTest extends AbstractActorTest {
 
                 MockRaftActor mockRaftActor = mockActorRef.underlyingActor();
 
+                mockRaftActor.waitForInitializeBehaviorComplete();
+
                 ReplicatedLogEntry entry = new MockRaftActorContext.MockReplicatedLogEntry(1, 5,
                         new MockRaftActorContext.MockPayload("F"));
 
@@ -811,6 +818,8 @@ public class RaftActorTest extends AbstractActorTest {
 
                 MockRaftActor mockRaftActor = mockActorRef.underlyingActor();
 
+                mockRaftActor.waitForInitializeBehaviorComplete();
+
                 ReplicatedLog oldReplicatedLog = mockRaftActor.getReplicatedLog();
 
                 oldReplicatedLog.append(new MockRaftActorContext.MockReplicatedLogEntry(1, 0, mock(Payload.class)));
@@ -864,6 +873,8 @@ public class RaftActorTest extends AbstractActorTest {
 
                 MockRaftActor mockRaftActor = mockActorRef.underlyingActor();
 
+                mockRaftActor.waitForInitializeBehaviorComplete();
+
                 ByteString snapshotBytes = fromObject(Arrays.asList(
                         new MockRaftActorContext.MockPayload("A"),
                         new MockRaftActorContext.MockPayload("B"),
@@ -892,33 +903,44 @@ public class RaftActorTest extends AbstractActorTest {
     public void testRaftRoleChangeNotifier() throws Exception {
         new JavaTestKit(getSystem()) {{
             ActorRef notifierActor = factory.createActor(Props.create(MessageCollectorActor.class));
+            MessageCollectorActor.waitUntilReady(notifierActor);
+
             DefaultConfigParamsImpl config = new DefaultConfigParamsImpl();
+            long heartBeatInterval = 100;
+            config.setHeartBeatInterval(FiniteDuration.create(heartBeatInterval, TimeUnit.MILLISECONDS));
+            config.setElectionTimeoutFactor(1);
+
             String persistenceId = factory.generateActorId("notifier-");
 
             factory.createTestActor(MockRaftActor.props(persistenceId,
                     Collections.<String, String>emptyMap(), Optional.<ConfigParams>of(config), notifierActor), persistenceId);
 
-            // sleeping for a minimum of 2 seconds, if it spans more its fine.
-            Uninterruptibles.sleepUninterruptibly(2, TimeUnit.SECONDS);
+            List<RoleChanged> matches =  null;
+            for(int i = 0; i < 5000 / heartBeatInterval; i++) {
+                matches = MessageCollectorActor.getAllMatching(notifierActor, RoleChanged.class);
+                assertNotNull(matches);
+                if(matches.size() == 3) {
+                    break;
+                }
+                Uninterruptibles.sleepUninterruptibly(heartBeatInterval, TimeUnit.MILLISECONDS);
+            }
 
-            List<Object> matches = MessageCollectorActor.getAllMatching(notifierActor, RoleChanged.class);
-            assertNotNull(matches);
             assertEquals(3, matches.size());
 
             // check if the notifier got a role change from null to Follower
-            RoleChanged raftRoleChanged = (RoleChanged) matches.get(0);
+            RoleChanged raftRoleChanged = matches.get(0);
             assertEquals(persistenceId, raftRoleChanged.getMemberId());
             assertNull(raftRoleChanged.getOldRole());
             assertEquals(RaftState.Follower.name(), raftRoleChanged.getNewRole());
 
             // check if the notifier got a role change from Follower to Candidate
-            raftRoleChanged = (RoleChanged) matches.get(1);
+            raftRoleChanged = matches.get(1);
             assertEquals(persistenceId, 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(2);
+            raftRoleChanged = matches.get(2);
             assertEquals(persistenceId, raftRoleChanged.getMemberId());
             assertEquals(RaftState.Candidate.name(), raftRoleChanged.getOldRole());
             assertEquals(RaftState.Leader.name(), raftRoleChanged.getNewRole());
@@ -944,11 +966,12 @@ public class RaftActorTest extends AbstractActorTest {
                 Map<String, String> peerAddresses = new HashMap<>();
                 peerAddresses.put(follower1Id, followerActor1.path().toString());
 
-                TestActorRef<MockRaftActor> mockActorRef = TestActorRef.create(getSystem(),
+                TestActorRef<MockRaftActor> mockActorRef = factory.createTestActor(
                         MockRaftActor.props(persistenceId, peerAddresses,
                                 Optional.<ConfigParams>of(config), dataPersistenceProvider), persistenceId);
 
                 MockRaftActor leaderActor = mockActorRef.underlyingActor();
+
                 leaderActor.getRaftActorContext().setCommitIndex(4);
                 leaderActor.getRaftActorContext().setLastApplied(4);
                 leaderActor.getRaftActorContext().getTermInformation().update(1, persistenceId);
@@ -1034,7 +1057,7 @@ public class RaftActorTest extends AbstractActorTest {
                 Map<String, String> peerAddresses = new HashMap<>();
                 peerAddresses.put(leaderId, leaderActor1.path().toString());
 
-                TestActorRef<MockRaftActor> mockActorRef = TestActorRef.create(getSystem(),
+                TestActorRef<MockRaftActor> mockActorRef = factory.createTestActor(
                         MockRaftActor.props(persistenceId, peerAddresses,
                                 Optional.<ConfigParams>of(config), dataPersistenceProvider), persistenceId);
 
@@ -1204,6 +1227,128 @@ public class RaftActorTest extends AbstractActorTest {
         };
     }
 
+
+    private static class NonPersistentProvider implements DataPersistenceProvider {
+        @Override
+        public boolean isRecoveryApplicable() {
+            return false;
+        }
+
+        @Override
+        public <T> void persist(T o, Procedure<T> procedure) {
+            try {
+                procedure.apply(o);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        @Override
+        public void saveSnapshot(Object o) {
+
+        }
+
+        @Override
+        public void deleteSnapshots(SnapshotSelectionCriteria criteria) {
+
+        }
+
+        @Override
+        public void deleteMessages(long sequenceNumber) {
+
+        }
+    }
+
+    @Test
+    public void testRealSnapshotWhenReplicatedToAllIndexMinusOne() throws Exception {
+        new JavaTestKit(getSystem()) {{
+            String persistenceId = factory.generateActorId("leader-");
+            DefaultConfigParamsImpl config = new DefaultConfigParamsImpl();
+            config.setHeartBeatInterval(new FiniteDuration(1, TimeUnit.DAYS));
+            config.setIsolatedLeaderCheckInterval(new FiniteDuration(1, TimeUnit.DAYS));
+            config.setSnapshotBatchCount(5);
+
+            DataPersistenceProvider dataPersistenceProvider = new NonPersistentProvider();
+
+            Map<String, String> peerAddresses = new HashMap<>();
+
+            TestActorRef<MockRaftActor> mockActorRef = factory.createTestActor(
+                    MockRaftActor.props(persistenceId, peerAddresses,
+                            Optional.<ConfigParams>of(config), dataPersistenceProvider), persistenceId);
+
+            MockRaftActor leaderActor = mockActorRef.underlyingActor();
+            leaderActor.getRaftActorContext().setCommitIndex(3);
+            leaderActor.getRaftActorContext().setLastApplied(3);
+            leaderActor.getRaftActorContext().getTermInformation().update(1, persistenceId);
+
+            leaderActor.waitForInitializeBehaviorComplete();
+            for(int i=0;i< 4;i++) {
+                leaderActor.getReplicatedLog()
+                        .append(new MockRaftActorContext.MockReplicatedLogEntry(1, i,
+                                new MockRaftActorContext.MockPayload("A")));
+            }
+
+            Leader leader = new Leader(leaderActor.getRaftActorContext());
+            leaderActor.setCurrentBehavior(leader);
+            assertEquals(RaftState.Leader, leaderActor.getCurrentBehavior().state());
+
+            // Persist another entry (this will cause a CaptureSnapshot to be triggered
+            leaderActor.persistData(mockActorRef, "x", new MockRaftActorContext.MockPayload("duh"));
+
+            // Now send a CaptureSnapshotReply
+            mockActorRef.tell(new CaptureSnapshotReply(fromObject("foo").toByteArray()), mockActorRef);
+
+            // Trimming log in this scenario is a no-op
+            assertEquals(-1, leaderActor.getReplicatedLog().getSnapshotIndex());
+            assertFalse(leaderActor.getRaftActorContext().isSnapshotCaptureInitiated());
+            assertEquals(-1, leader.getReplicatedToAllIndex());
+
+        }};
+    }
+
+    @Test
+    public void testRealSnapshotWhenReplicatedToAllIndexNotInReplicatedLog() throws Exception {
+        new JavaTestKit(getSystem()) {{
+            String persistenceId = factory.generateActorId("leader-");
+            DefaultConfigParamsImpl config = new DefaultConfigParamsImpl();
+            config.setHeartBeatInterval(new FiniteDuration(1, TimeUnit.DAYS));
+            config.setIsolatedLeaderCheckInterval(new FiniteDuration(1, TimeUnit.DAYS));
+            config.setSnapshotBatchCount(5);
+
+            DataPersistenceProvider dataPersistenceProvider = new NonPersistentProvider();
+
+            Map<String, String> peerAddresses = new HashMap<>();
+
+            TestActorRef<MockRaftActor> mockActorRef = factory.createTestActor(
+                    MockRaftActor.props(persistenceId, peerAddresses,
+                            Optional.<ConfigParams>of(config), dataPersistenceProvider), persistenceId);
+
+            MockRaftActor leaderActor = mockActorRef.underlyingActor();
+            leaderActor.getRaftActorContext().setCommitIndex(3);
+            leaderActor.getRaftActorContext().setLastApplied(3);
+            leaderActor.getRaftActorContext().getTermInformation().update(1, persistenceId);
+            leaderActor.getReplicatedLog().setSnapshotIndex(3);
+
+            leaderActor.waitForInitializeBehaviorComplete();
+            Leader leader = new Leader(leaderActor.getRaftActorContext());
+            leaderActor.setCurrentBehavior(leader);
+            leader.setReplicatedToAllIndex(3);
+            assertEquals(RaftState.Leader, leaderActor.getCurrentBehavior().state());
+
+            // Persist another entry (this will cause a CaptureSnapshot to be triggered
+            leaderActor.persistData(mockActorRef, "x", new MockRaftActorContext.MockPayload("duh"));
+
+            // Now send a CaptureSnapshotReply
+            mockActorRef.tell(new CaptureSnapshotReply(fromObject("foo").toByteArray()), mockActorRef);
+
+            // Trimming log in this scenario is a no-op
+            assertEquals(3, leaderActor.getReplicatedLog().getSnapshotIndex());
+            assertFalse(leaderActor.getRaftActorContext().isSnapshotCaptureInitiated());
+            assertEquals(3, leader.getReplicatedToAllIndex());
+
+        }};
+    }
+
     private ByteString fromObject(Object snapshot) throws Exception {
         ByteArrayOutputStream b = null;
         ObjectOutputStream o = null;
index 6872c8f..b47df13 100644 (file)
@@ -21,6 +21,7 @@ import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
 import akka.actor.PoisonPill;
 import akka.actor.Props;
+import akka.testkit.JavaTestKit;
 import akka.testkit.TestActorRef;
 import java.util.LinkedList;
 import java.util.List;
@@ -108,10 +109,14 @@ public class TestActorFactory implements AutoCloseable {
     }
 
     @Override
-    public void close() throws Exception {
-        for(ActorRef actor : createdActors){
-            LOG.info("Killing actor {}", actor);
-            actor.tell(PoisonPill.getInstance(), null);
-        }
+    public void close() {
+        new JavaTestKit(system) {{
+            for(ActorRef actor : createdActors) {
+                watch(actor);
+                LOG.info("Killing actor {}", actor);
+                actor.tell(PoisonPill.getInstance(), ActorRef.noSender());
+                expectTerminated(duration("5 seconds"), actor);
+            }
+        }};
     }
 }
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractLeaderTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractLeaderTest.java
new file mode 100644 (file)
index 0000000..dd3ed23
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015 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 static org.junit.Assert.assertTrue;
+import akka.actor.ActorRef;
+import akka.testkit.JavaTestKit;
+import akka.testkit.TestActorRef;
+import com.google.common.util.concurrent.Uninterruptibles;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
+import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
+import org.opendaylight.controller.cluster.raft.base.messages.SendHeartBeat;
+import org.opendaylight.controller.cluster.raft.utils.ForwardMessageToBehaviorActor;
+import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
+import scala.concurrent.duration.FiniteDuration;
+
+public abstract class AbstractLeaderTest extends AbstractRaftActorBehaviorTest{
+
+    /**
+     * When we removed scheduling of heartbeat in the AbstractLeader constructor we ended up with a situation where
+     * if no follower responded to an initial AppendEntries heartbeats would not be sent to it. This test verifies
+     * that regardless of whether followers respond or not we schedule heartbeats.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testLeaderSchedulesHeartbeatsEvenWhenNoFollowersRespondToInitialAppendEntries() throws Exception {
+        logStart("testLeaderSchedulesHeartbeatsEvenWhenNoFollowersRespondToInitialAppendEntries");
+        new JavaTestKit(getSystem()) {{
+            String leaderActorId = actorFactory.generateActorId("leader");
+            String follower1ActorId = actorFactory.generateActorId("follower");
+            String follower2ActorId = actorFactory.generateActorId("follower");
+
+            TestActorRef<ForwardMessageToBehaviorActor> leaderActor =
+                    actorFactory.createTestActor(ForwardMessageToBehaviorActor.props(), leaderActorId);
+            ActorRef follower1Actor = actorFactory.createActor(MessageCollectorActor.props(), follower1ActorId);
+            ActorRef follower2Actor = actorFactory.createActor(MessageCollectorActor.props(), follower2ActorId);
+
+            MockRaftActorContext leaderActorContext =
+                    new MockRaftActorContext(leaderActorId, getSystem(), leaderActor);
+
+            DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
+            configParams.setHeartBeatInterval(new FiniteDuration(200, TimeUnit.MILLISECONDS));
+            configParams.setIsolatedLeaderCheckInterval(new FiniteDuration(10, TimeUnit.SECONDS));
+
+            leaderActorContext.setConfigParams(configParams);
+
+            leaderActorContext.setReplicatedLog(
+                    new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(1,5,1).build());
+
+            Map<String, String> peerAddresses = new HashMap<>();
+            peerAddresses.put(follower1ActorId,
+                    follower1Actor.path().toString());
+            peerAddresses.put(follower2ActorId,
+                    follower2Actor.path().toString());
+
+
+            leaderActorContext.setPeerAddresses(peerAddresses);
+
+            RaftActorBehavior leader = createBehavior(leaderActorContext);
+
+            leaderActor.underlyingActor().setBehavior(leader);
+
+            Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
+
+            List<SendHeartBeat> allMessages = MessageCollectorActor.getAllMatching(leaderActor, SendHeartBeat.class);
+
+            // Need more than 1 heartbeat to be delivered because we waited for 1 second with heartbeat interval 200ms
+            assertTrue(String.format("%s messages is less than expected", allMessages.size()),
+                    allMessages.size() > 1);
+
+        }};
+    }
+
+}
index c133c06..f56755b 100644 (file)
@@ -1,30 +1,52 @@
 package org.opendaylight.controller.cluster.raft.behaviors;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import akka.actor.ActorRef;
 import akka.actor.Props;
-import akka.testkit.JavaTestKit;
+import akka.testkit.TestActorRef;
+import com.google.protobuf.ByteString;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import org.junit.After;
+import org.junit.Assert;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.raft.AbstractActorTest;
 import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
 import org.opendaylight.controller.cluster.raft.RaftActorContext;
+import org.opendaylight.controller.cluster.raft.RaftState;
 import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
 import org.opendaylight.controller.cluster.raft.SerializationUtils;
+import org.opendaylight.controller.cluster.raft.TestActorFactory;
 import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
 import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
 import org.opendaylight.controller.cluster.raft.messages.RaftRPC;
 import org.opendaylight.controller.cluster.raft.messages.RequestVote;
 import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
 import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
-import org.opendaylight.controller.cluster.raft.utils.DoNothingActor;
+import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
+import org.slf4j.LoggerFactory;
 
 public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest {
 
-    private final ActorRef behaviorActor = getSystem().actorOf(Props.create(
-        DoNothingActor.class));
+    protected final TestActorFactory actorFactory = new TestActorFactory(getSystem());
+
+    private final TestActorRef<MessageCollectorActor> behaviorActor = actorFactory.createTestActor(
+            Props.create(MessageCollectorActor.class), actorFactory.generateActorId("behavior"));
+
+    RaftActorBehavior behavior;
+
+    @After
+    public void tearDown() throws Exception {
+        if(behavior != null) {
+            behavior.close();
+        }
+
+        actorFactory.close();
+    }
 
     /**
      * This test checks that when a new Raft RPC message is received with a newer
@@ -34,22 +56,19 @@ public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest {
      */
     @Test
     public void testHandleRaftRPCWithNewerTerm() throws Exception {
-        new JavaTestKit(getSystem()) {{
+        RaftActorContext actorContext = createActorContext();
 
-            assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(getTestActor(),
+        assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(actorContext, behaviorActor,
                 createAppendEntriesWithNewerTerm());
 
-            assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(getTestActor(),
+        assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(actorContext, behaviorActor,
                 createAppendEntriesReplyWithNewerTerm());
 
-            assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(getTestActor(),
+        assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(actorContext, behaviorActor,
                 createRequestVoteWithNewerTerm());
 
-            assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(getTestActor(),
+        assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(actorContext, behaviorActor,
                 createRequestVoteReplyWithNewerTerm());
-
-
-        }};
     }
 
 
@@ -61,144 +80,95 @@ public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest {
      * @throws Exception
      */
     @Test
-    public void testHandleAppendEntriesSenderTermLessThanReceiverTerm()
-        throws Exception {
-        new JavaTestKit(getSystem()) {{
-
-            MockRaftActorContext context = (MockRaftActorContext)
-                createActorContext();
+    public void testHandleAppendEntriesSenderTermLessThanReceiverTerm() throws Exception {
+            MockRaftActorContext context = createActorContext();
 
             // First set the receivers term to a high number (1000)
             context.getTermInformation().update(1000, "test");
 
-            AppendEntries appendEntries =
-                new AppendEntries(100, "leader-1", 0, 0, null, 101, -1);
+            AppendEntries appendEntries = new AppendEntries(100, "leader-1", 0, 0, null, 101, -1);
 
-            RaftActorBehavior behavior = createBehavior(context);
+            behavior = createBehavior(context);
 
             // Send an unknown message so that the state of the RaftActor remains unchanged
-            RaftActorBehavior expected = behavior.handleMessage(getRef(), "unknown");
+            RaftActorBehavior expected = behavior.handleMessage(behaviorActor, "unknown");
 
-            RaftActorBehavior raftBehavior =
-                behavior.handleMessage(getRef(), appendEntries);
+            RaftActorBehavior raftBehavior = behavior.handleMessage(behaviorActor, appendEntries);
 
-            assertEquals(expected, raftBehavior);
+            assertEquals("Raft state", expected.state(), raftBehavior.state());
 
             // Also expect an AppendEntriesReply to be sent where success is false
-            final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"),
-                "AppendEntriesReply") {
-                // do not put code outside this method, will run afterwards
-                protected Boolean match(Object in) {
-                    if (in instanceof AppendEntriesReply) {
-                        AppendEntriesReply reply = (AppendEntriesReply) in;
-                        return reply.isSuccess();
-                    } else {
-                        throw noMatch();
-                    }
-                }
-            }.get();
-
-            assertEquals(false, out);
-
-
-        }};
-    }
 
+            AppendEntriesReply reply = MessageCollectorActor.expectFirstMatching(
+                    behaviorActor, AppendEntriesReply.class);
 
-    @Test
-    public void testHandleAppendEntriesAddSameEntryToLog(){
-        new JavaTestKit(getSystem()) {
-            {
+            assertEquals("isSuccess", false, reply.isSuccess());
+    }
 
-                MockRaftActorContext context = (MockRaftActorContext)
-                    createActorContext();
 
-                // First set the receivers term to lower number
-                context.getTermInformation().update(2, "test");
+    @Test
+    public void testHandleAppendEntriesAddSameEntryToLog() throws Exception {
+        MockRaftActorContext context = createActorContext();
 
-                // Prepare the receivers log
-                MockRaftActorContext.SimpleReplicatedLog log =
-                    new MockRaftActorContext.SimpleReplicatedLog();
-                log.append(
-                    new MockRaftActorContext.MockReplicatedLogEntry(1, 0, new MockRaftActorContext.MockPayload("zero")));
+        context.getTermInformation().update(2, "test");
 
-                context.setReplicatedLog(log);
+        // Prepare the receivers log
+        MockRaftActorContext.MockPayload payload = new MockRaftActorContext.MockPayload("zero");
+        setLastLogEntry(context, 2, 0, payload);
 
-                List<ReplicatedLogEntry> entries = new ArrayList<>();
-                entries.add(
-                    new MockRaftActorContext.MockReplicatedLogEntry(1, 0, new MockRaftActorContext.MockPayload("zero")));
+        List<ReplicatedLogEntry> entries = new ArrayList<>();
+        entries.add(new MockRaftActorContext.MockReplicatedLogEntry(2, 0, payload));
 
-                AppendEntries appendEntries =
-                    new AppendEntries(2, "leader-1", -1, 1, entries, 0, -1);
+        AppendEntries appendEntries = new AppendEntries(2, "leader-1", -1, -1, entries, 2, -1);
 
-                RaftActorBehavior behavior = createBehavior(context);
+        behavior = createBehavior(context);
 
-                if (AbstractRaftActorBehaviorTest.this instanceof CandidateTest) {
-                    // Resetting the Candidates term to make sure it will match
-                    // the term sent by AppendEntries. If this was not done then
-                    // the test will fail because the Candidate will assume that
-                    // the message was sent to it from a lower term peer and will
-                    // thus respond with a failure
-                    context.getTermInformation().update(2, "test");
-                }
+        if (behavior instanceof Candidate) {
+            // Resetting the Candidates term to make sure it will match
+            // the term sent by AppendEntries. If this was not done then
+            // the test will fail because the Candidate will assume that
+            // the message was sent to it from a lower term peer and will
+            // thus respond with a failure
+            context.getTermInformation().update(2, "test");
+        }
 
-                // Send an unknown message so that the state of the RaftActor remains unchanged
-                RaftActorBehavior expected = behavior.handleMessage(getRef(), "unknown");
+        // Send an unknown message so that the state of the RaftActor remains unchanged
+        RaftActorBehavior expected = behavior.handleMessage(behaviorActor, "unknown");
 
-                RaftActorBehavior raftBehavior =
-                    behavior.handleMessage(getRef(), appendEntries);
+        RaftActorBehavior raftBehavior = behavior.handleMessage(behaviorActor, appendEntries);
 
-                assertEquals(expected, raftBehavior);
+        assertEquals("Raft state", expected.state(), raftBehavior.state());
 
-                assertEquals(1, log.size());
+        assertEquals("ReplicatedLog size", 1, context.getReplicatedLog().size());
 
+        handleAppendEntriesAddSameEntryToLogReply(behaviorActor);
+    }
 
-            }};
+    protected void handleAppendEntriesAddSameEntryToLogReply(TestActorRef<MessageCollectorActor> replyActor)
+            throws Exception {
+        AppendEntriesReply reply = MessageCollectorActor.getFirstMatching(replyActor, AppendEntriesReply.class);
+        Assert.assertNull("Expected no AppendEntriesReply", reply);
     }
 
     /**
      * This test verifies that when a RequestVote is received by the RaftActor
-     * with a term which is greater than the RaftActors' currentTerm and the
-     * senders' log is more upto date than the receiver that the receiver grants
-     * the vote to the sender
+     * with the senders' log is more up to date than the receiver that the receiver grants
+     * the vote to the sender.
      */
     @Test
-    public void testHandleRequestVoteWhenSenderTermGreaterThanCurrentTermAndSenderLogMoreUpToDate() {
-        new JavaTestKit(getSystem()) {{
-
-            new Within(duration("1 seconds")) {
-                protected void run() {
-
-                    RaftActorBehavior behavior = createBehavior(
-                        createActorContext(behaviorActor));
-
-                    RaftActorBehavior raftBehavior = behavior.handleMessage(getTestActor(),
-                        new RequestVote(1000, "test", 10000, 999));
-
-                    if(!(behavior instanceof Follower)){
-                        assertTrue(raftBehavior instanceof Follower);
-                    } else {
-
-                        final Boolean out =
-                            new ExpectMsg<Boolean>(duration("1 seconds"),
-                                "RequestVoteReply") {
-                                // do not put code outside this method, will run afterwards
-                                protected Boolean match(Object in) {
-                                    if (in instanceof RequestVoteReply) {
-                                        RequestVoteReply reply =
-                                            (RequestVoteReply) in;
-                                        return reply.isVoteGranted();
-                                    } else {
-                                        throw noMatch();
-                                    }
-                                }
-                            }.get();
-
-                        assertEquals(true, out);
-                    }
-                }
-            };
-        }};
+    public void testHandleRequestVoteWhenSenderLogMoreUpToDate() {
+        MockRaftActorContext context = createActorContext();
+
+        behavior = createBehavior(context);
+
+        context.getTermInformation().update(1, "test");
+
+        behavior.handleMessage(behaviorActor, new RequestVote(context.getTermInformation().getCurrentTerm(),
+                "test", 10000, 999));
+
+        RequestVoteReply reply = MessageCollectorActor.expectFirstMatching(behaviorActor,
+                RequestVoteReply.class);
+        assertEquals("isVoteGranted", true, reply.isVoteGranted());
     }
 
     /**
@@ -207,51 +177,24 @@ public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest {
      * log then the receiving RaftActor will not grant the vote to the sender
      */
     @Test
-    public void testHandleRequestVoteWhenSenderTermGreaterThanCurrentTermButSenderLogLessUptoDate() {
-        new JavaTestKit(getSystem()) {{
-
-            new Within(duration("1 seconds")) {
-                protected void run() {
-
-                    RaftActorContext actorContext =
-                        createActorContext(behaviorActor);
-
-                    MockRaftActorContext.SimpleReplicatedLog
-                        log = new MockRaftActorContext.SimpleReplicatedLog();
-                    log.append(
-                        new MockRaftActorContext.MockReplicatedLogEntry(20000,
-                            1000000, new MockRaftActorContext.MockPayload("")));
-
-                    ((MockRaftActorContext) actorContext).setReplicatedLog(log);
-
-                    RaftActorBehavior behavior = createBehavior(actorContext);
-
-                    RaftActorBehavior raftBehavior = behavior.handleMessage(getTestActor(),
-                        new RequestVote(1000, "test", 10000, 999));
-
-                    if(!(behavior instanceof Follower)){
-                        assertTrue(raftBehavior instanceof Follower);
-                    } else {
-                        final Boolean out =
-                            new ExpectMsg<Boolean>(duration("1 seconds"),
-                                "RequestVoteReply") {
-                                // do not put code outside this method, will run afterwards
-                                protected Boolean match(Object in) {
-                                    if (in instanceof RequestVoteReply) {
-                                        RequestVoteReply reply =
-                                            (RequestVoteReply) in;
-                                        return reply.isVoteGranted();
-                                    } else {
-                                        throw noMatch();
-                                    }
-                                }
-                            }.get();
-
-                        assertEquals(false, out);
-                    }
-                }
-            };
-        }};
+    public void testHandleRequestVoteWhenSenderLogLessUptoDate() {
+        MockRaftActorContext context = createActorContext();
+
+        behavior = createBehavior(context);
+
+        context.getTermInformation().update(1, "test");
+
+        int index = 2000;
+        setLastLogEntry(context, context.getTermInformation().getCurrentTerm(), index,
+                new MockRaftActorContext.MockPayload(""));
+
+        behavior.handleMessage(behaviorActor, new RequestVote(
+                context.getTermInformation().getCurrentTerm(), "test",
+                index - 1, context.getTermInformation().getCurrentTerm()));
+
+        RequestVoteReply reply = MessageCollectorActor.expectFirstMatching(behaviorActor,
+                RequestVoteReply.class);
+        assertEquals("isVoteGranted", false, reply.isVoteGranted());
     }
 
 
@@ -263,40 +206,17 @@ public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest {
      */
     @Test
     public void testHandleRequestVoteWhenSenderTermLessThanCurrentTerm() {
-        new JavaTestKit(getSystem()) {{
-
-            new Within(duration("1 seconds")) {
-                protected void run() {
-
-                    RaftActorContext context =
-                        createActorContext(behaviorActor);
-
-                    context.getTermInformation().update(1000, null);
-
-                    RaftActorBehavior follower = createBehavior(context);
-
-                    follower.handleMessage(getTestActor(),
-                        new RequestVote(999, "test", 10000, 999));
-
-                    final Boolean out =
-                        new ExpectMsg<Boolean>(duration("1 seconds"),
-                            "RequestVoteReply") {
-                            // do not put code outside this method, will run afterwards
-                            protected Boolean match(Object in) {
-                                if (in instanceof RequestVoteReply) {
-                                    RequestVoteReply reply =
-                                        (RequestVoteReply) in;
-                                    return reply.isVoteGranted();
-                                } else {
-                                    throw noMatch();
-                                }
-                            }
-                        }.get();
-
-                    assertEquals(false, out);
-                }
-            };
-        }};
+        RaftActorContext context = createActorContext();
+
+        context.getTermInformation().update(1000, null);
+
+        behavior = createBehavior(context);
+
+        behavior.handleMessage(behaviorActor, new RequestVote(999, "test", 10000, 999));
+
+        RequestVoteReply reply = MessageCollectorActor.expectFirstMatching(behaviorActor,
+                RequestVoteReply.class);
+        assertEquals("isVoteGranted", false, reply.isVoteGranted());
     }
 
     @Test
@@ -346,18 +266,21 @@ public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest {
     }
 
 
-    protected void assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(
-        ActorRef actorRef, RaftRPC rpc) {
+    protected void assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(RaftActorContext actorContext,
+            ActorRef actorRef, RaftRPC rpc) throws Exception {
 
-        RaftActorContext actorContext = createActorContext();
         Payload p = new MockRaftActorContext.MockPayload("");
-        setLastLogEntry(
-            (MockRaftActorContext) actorContext, 0, 0, p);
+        setLastLogEntry((MockRaftActorContext) actorContext, 1, 0, p);
+        actorContext.getTermInformation().update(1, "test");
+
+        RaftActorBehavior origBehavior = createBehavior(actorContext);
+        RaftActorBehavior raftBehavior = origBehavior.handleMessage(actorRef, rpc);
 
-        RaftActorBehavior raftBehavior = createBehavior(actorContext)
-            .handleMessage(actorRef, rpc);
+        assertEquals("New raft state", RaftState.Follower, raftBehavior.state());
+        assertEquals("New election term", rpc.getTerm(), actorContext.getTermInformation().getCurrentTerm());
 
-        assertTrue(raftBehavior instanceof Follower);
+        origBehavior.close();
+        raftBehavior.close();
     }
 
     protected MockRaftActorContext.SimpleReplicatedLog setLastLogEntry(
@@ -366,10 +289,9 @@ public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest {
             new MockRaftActorContext.MockReplicatedLogEntry(term, index, data));
     }
 
-    protected MockRaftActorContext.SimpleReplicatedLog setLastLogEntry(
-        MockRaftActorContext actorContext, ReplicatedLogEntry logEntry) {
-        MockRaftActorContext.SimpleReplicatedLog
-            log = new MockRaftActorContext.SimpleReplicatedLog();
+    protected MockRaftActorContext.SimpleReplicatedLog setLastLogEntry(MockRaftActorContext actorContext,
+            ReplicatedLogEntry logEntry) {
+        MockRaftActorContext.SimpleReplicatedLog log = new MockRaftActorContext.SimpleReplicatedLog();
         log.append(logEntry);
         actorContext.setReplicatedLog(log);
 
@@ -383,11 +305,11 @@ public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest {
         return createBehavior(createActorContext());
     }
 
-    protected RaftActorContext createActorContext() {
+    protected MockRaftActorContext createActorContext() {
         return new MockRaftActorContext();
     }
 
-    protected RaftActorContext createActorContext(ActorRef actor) {
+    protected MockRaftActorContext createActorContext(ActorRef actor) {
         return new MockRaftActorContext("test", getSystem(), actor);
     }
 
@@ -410,4 +332,18 @@ public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest {
     protected Object fromSerializableMessage(Object serializable){
         return SerializationUtils.fromSerializable(serializable);
     }
+
+    protected ByteString toByteString(Map<String, String> state) {
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        try(ObjectOutputStream oos = new ObjectOutputStream(bos)) {
+            oos.writeObject(state);
+            return ByteString.copyFrom(bos.toByteArray());
+        } catch (IOException e) {
+            throw new AssertionError("IOException occurred converting Map to Bytestring", e);
+        }
+    }
+
+    protected void logStart(String name) {
+        LoggerFactory.getLogger(LeaderTest.class).info("Starting " + name);
+    }
 }
index 0dc68c2..60f4552 100644 (file)
@@ -1,68 +1,48 @@
 package org.opendaylight.controller.cluster.raft.behaviors;
 
+import static org.junit.Assert.assertEquals;
 import akka.actor.ActorRef;
 import akka.actor.Props;
-import akka.testkit.JavaTestKit;
+import akka.testkit.TestActorRef;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
-import org.junit.Assert;
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
-import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
 import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
 import org.opendaylight.controller.cluster.raft.RaftActorContext;
+import org.opendaylight.controller.cluster.raft.RaftState;
 import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
 import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout;
 import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
 import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
+import org.opendaylight.controller.cluster.raft.messages.RaftRPC;
 import org.opendaylight.controller.cluster.raft.messages.RequestVote;
 import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
-import org.opendaylight.controller.cluster.raft.utils.DoNothingActor;
-
-import static org.junit.Assert.assertEquals;
+import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
 
 public class CandidateTest extends AbstractRaftActorBehaviorTest {
 
-    private final ActorRef candidateActor = getSystem().actorOf(Props.create(
-        DoNothingActor.class));
-
-    private final ActorRef peerActor1 = getSystem().actorOf(Props.create(
-        DoNothingActor.class));
+    private final TestActorRef<MessageCollectorActor> candidateActor = actorFactory.createTestActor(
+            Props.create(MessageCollectorActor.class), actorFactory.generateActorId("candidate"));
 
-    private final ActorRef peerActor2 = getSystem().actorOf(Props.create(
-        DoNothingActor.class));
+    private TestActorRef<MessageCollectorActor>[] peerActors;
 
-    private final ActorRef peerActor3 = getSystem().actorOf(Props.create(
-        DoNothingActor.class));
-
-    private final ActorRef peerActor4 = getSystem().actorOf(Props.create(
-        DoNothingActor.class));
-
-    private final Map<String, String> onePeer = new HashMap<>();
-    private final Map<String, String> twoPeers = new HashMap<>();
-    private final Map<String, String> fourPeers = new HashMap<>();
+    private RaftActorBehavior candidate;
 
     @Before
     public void setUp(){
-        onePeer.put(peerActor1.path().toString(),
-            peerActor1.path().toString());
-
-        twoPeers.put(peerActor1.path().toString(),
-            peerActor1.path().toString());
-        twoPeers.put(peerActor2.path().toString(),
-            peerActor2.path().toString());
-
-        fourPeers.put(peerActor1.path().toString(),
-            peerActor1.path().toString());
-        fourPeers.put(peerActor2.path().toString(),
-            peerActor2.path().toString());
-        fourPeers.put(peerActor3.path().toString(),
-            peerActor3.path().toString());
-        fourPeers.put(peerActor4.path().toString(),
-            peerActor3.path().toString());
+    }
 
+    @Override
+    @After
+    public void tearDown() throws Exception {
+        if(candidate != null) {
+            candidate.close();
+        }
 
+        super.tearDown();
     }
 
     @Test
@@ -70,230 +50,167 @@ public class CandidateTest extends AbstractRaftActorBehaviorTest {
         RaftActorContext raftActorContext = createActorContext();
         long expectedTerm = raftActorContext.getTermInformation().getCurrentTerm();
 
-        new Candidate(raftActorContext);
+        candidate = new Candidate(raftActorContext);
 
-        assertEquals(expectedTerm+1, raftActorContext.getTermInformation().getCurrentTerm());
-        assertEquals(raftActorContext.getId(), raftActorContext.getTermInformation().getVotedFor());
+        assertEquals("getCurrentTerm", expectedTerm+1, raftActorContext.getTermInformation().getCurrentTerm());
+        assertEquals("getVotedFor", raftActorContext.getId(), raftActorContext.getTermInformation().getVotedFor());
     }
 
     @Test
     public void testThatAnElectionTimeoutIsTriggered(){
-        new JavaTestKit(getSystem()) {{
-
-            new Within(DefaultConfigParamsImpl.HEART_BEAT_INTERVAL.$times(6)) {
-                protected void run() {
-
-                    Candidate candidate = new Candidate(createActorContext(getTestActor()));
-
-                    final Boolean out = new ExpectMsg<Boolean>(DefaultConfigParamsImpl.HEART_BEAT_INTERVAL.$times(6), "ElectionTimeout") {
-                        // do not put code outside this method, will run afterwards
-                        protected Boolean match(Object in) {
-                            if (in instanceof ElectionTimeout) {
-                                 return true;
-                            } else {
-                                throw noMatch();
-                            }
-                        }
-                    }.get();
-
-                    assertEquals(true, out);
-                }
-            };
-        }};
+         MockRaftActorContext actorContext = createActorContext();
+         candidate = new Candidate(actorContext);
+
+         MessageCollectorActor.expectFirstMatching(candidateActor, ElectionTimeout.class,
+                 actorContext.getConfigParams().getElectionTimeOutInterval().$times(6).toMillis());
     }
 
     @Test
     public void testHandleElectionTimeoutWhenThereAreZeroPeers(){
         RaftActorContext raftActorContext = createActorContext();
-        Candidate candidate =
-            new Candidate(raftActorContext);
+        candidate = new Candidate(raftActorContext);
 
-        RaftActorBehavior raftBehavior =
+        RaftActorBehavior newBehavior =
             candidate.handleMessage(candidateActor, new ElectionTimeout());
 
-        Assert.assertTrue(raftBehavior instanceof Leader);
+        assertEquals("Behavior", RaftState.Leader, newBehavior.state());
     }
 
     @Test
-    public void testHandleElectionTimeoutWhenThereAreTwoNodesInCluster(){
-        MockRaftActorContext raftActorContext =
-            (MockRaftActorContext) createActorContext();
-        raftActorContext.setPeerAddresses(onePeer);
-        Candidate candidate =
-            new Candidate(raftActorContext);
-
-        RaftActorBehavior raftBehavior =
-            candidate.handleMessage(candidateActor, new ElectionTimeout());
+    public void testHandleElectionTimeoutWhenThereAreTwoNodeCluster(){
+        MockRaftActorContext raftActorContext = createActorContext();
+        raftActorContext.setPeerAddresses(setupPeers(1));
+        candidate = new Candidate(raftActorContext);
+
+        candidate = candidate.handleMessage(candidateActor, new ElectionTimeout());
 
-        Assert.assertTrue(raftBehavior instanceof Candidate);
+        assertEquals("Behavior", RaftState.Candidate, candidate.state());
     }
 
     @Test
-    public void testBecomeLeaderOnReceivingMajorityVotesInThreeNodesInCluster(){
-        MockRaftActorContext raftActorContext =
-            (MockRaftActorContext) createActorContext();
-        raftActorContext.setPeerAddresses(twoPeers);
-        Candidate candidate =
-            new Candidate(raftActorContext);
-
-        RaftActorBehavior behaviorOnFirstVote = candidate.handleMessage(peerActor1, new RequestVoteReply(0, true));
+    public void testBecomeLeaderOnReceivingMajorityVotesInThreeNodeCluster(){
+        MockRaftActorContext raftActorContext = createActorContext();
+        raftActorContext.setPeerAddresses(setupPeers(2));
+        candidate = new Candidate(raftActorContext);
 
-        Assert.assertTrue(behaviorOnFirstVote instanceof Leader);
+        candidate = candidate.handleMessage(peerActors[0], new RequestVoteReply(1, true));
 
+        assertEquals("Behavior", RaftState.Leader, candidate.state());
     }
 
     @Test
-    public void testBecomeLeaderOnReceivingMajorityVotesInFiveNodesInCluster(){
-        MockRaftActorContext raftActorContext =
-            (MockRaftActorContext) createActorContext();
-        raftActorContext.setPeerAddresses(fourPeers);
-        Candidate candidate =
-            new Candidate(raftActorContext);
+    public void testBecomeLeaderOnReceivingMajorityVotesInFiveNodeCluster(){
+        MockRaftActorContext raftActorContext = createActorContext();
+        raftActorContext.setPeerAddresses(setupPeers(4));
+        candidate = new Candidate(raftActorContext);
 
-        RaftActorBehavior behaviorOnFirstVote = candidate.handleMessage(peerActor1, new RequestVoteReply(0, true));
+        // First peers denies the vote.
+        candidate = candidate.handleMessage(peerActors[0], new RequestVoteReply(1, false));
 
-        RaftActorBehavior behaviorOnSecondVote = candidate.handleMessage(peerActor2, new RequestVoteReply(0, true));
+        assertEquals("Behavior", RaftState.Candidate, candidate.state());
 
-        Assert.assertTrue(behaviorOnFirstVote instanceof Candidate);
-        Assert.assertTrue(behaviorOnSecondVote instanceof Leader);
+        candidate = candidate.handleMessage(peerActors[1], new RequestVoteReply(1, true));
 
-    }
+        assertEquals("Behavior", RaftState.Candidate, candidate.state());
 
-    @Test
-    public void testResponseToAppendEntriesWithLowerTerm(){
-        new JavaTestKit(getSystem()) {{
-
-            new Within(duration("1 seconds")) {
-                protected void run() {
-
-                    Candidate candidate = new Candidate(createActorContext(getTestActor()));
-
-                    candidate.handleMessage(getTestActor(), new AppendEntries(0, "test", 0,0,Collections.<ReplicatedLogEntry>emptyList(), 0, -1));
-
-                    final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"), "AppendEntriesResponse") {
-                        // do not put code outside this method, will run afterwards
-                        protected Boolean match(Object in) {
-                            if (in instanceof AppendEntriesReply) {
-                                AppendEntriesReply reply = (AppendEntriesReply) in;
-                                return reply.isSuccess();
-                            } else {
-                                throw noMatch();
-                            }
-                        }
-                    }.get();
-
-                    assertEquals(false, out);
-                }
-            };
-        }};
+        candidate = candidate.handleMessage(peerActors[2], new RequestVoteReply(1, true));
+
+        assertEquals("Behavior", RaftState.Leader, candidate.state());
     }
 
     @Test
-    public void testResponseToRequestVoteWithLowerTerm(){
-        new JavaTestKit(getSystem()) {{
-
-            new Within(duration("1 seconds")) {
-                protected void run() {
-
-                    Candidate candidate = new Candidate(createActorContext(getTestActor()));
-
-                    candidate.handleMessage(getTestActor(), new RequestVote(0, "test", 0, 0));
-
-                    final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"), "AppendEntriesResponse") {
-                        // do not put code outside this method, will run afterwards
-                        protected Boolean match(Object in) {
-                            if (in instanceof RequestVoteReply) {
-                                RequestVoteReply reply = (RequestVoteReply) in;
-                                return reply.isVoteGranted();
-                            } else {
-                                throw noMatch();
-                            }
-                        }
-                    }.get();
-
-                    assertEquals(false, out);
-                }
-            };
-        }};
+    public void testResponseToHandleAppendEntriesWithLowerTerm() {
+        candidate = new Candidate(createActorContext());
+
+        setupPeers(1);
+        candidate.handleMessage(peerActors[0], new AppendEntries(1, "test", 0, 0,
+                Collections.<ReplicatedLogEntry>emptyList(), 0, -1));
+
+        AppendEntriesReply reply = MessageCollectorActor.expectFirstMatching(
+                peerActors[0], AppendEntriesReply.class);
+        assertEquals("isSuccess", false, reply.isSuccess());
+        assertEquals("getTerm", 2, reply.getTerm());
     }
 
     @Test
-    public void testHandleRequestVoteWhenSenderTermEqualToCurrentTermAndVotedForIsNull(){
-        new JavaTestKit(getSystem()) {{
-
-            new Within(duration("1 seconds")) {
-                protected void run() {
-
-                    RaftActorContext context = createActorContext(getTestActor());
-
-                    context.getTermInformation().update(1000, null);
-
-                    // Once a candidate is created it will immediately increment the current term so after
-                    // construction the currentTerm should be 1001
-                    RaftActorBehavior follower = createBehavior(context);
-
-                    follower.handleMessage(getTestActor(), new RequestVote(1001, "test", 10000, 999));
-
-                    final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"), "RequestVoteReply") {
-                        // do not put code outside this method, will run afterwards
-                        protected Boolean match(Object in) {
-                            if (in instanceof RequestVoteReply) {
-                                RequestVoteReply reply = (RequestVoteReply) in;
-                                return reply.isVoteGranted();
-                            } else {
-                                throw noMatch();
-                            }
-                        }
-                    }.get();
-
-                    assertEquals(true, out);
-                }
-            };
-        }};
+    public void testResponseToRequestVoteWithLowerTerm() {
+        candidate = new Candidate(createActorContext());
+
+        setupPeers(1);
+        candidate.handleMessage(peerActors[0], new RequestVote(1, "test", 0, 0));
+
+        RequestVoteReply reply = MessageCollectorActor.expectFirstMatching(
+                peerActors[0], RequestVoteReply.class);
+        assertEquals("isVoteGranted", false, reply.isVoteGranted());
+        assertEquals("getTerm", 2, reply.getTerm());
     }
 
     @Test
-    public void testHandleRequestVoteWhenSenderTermEqualToCurrentTermAndVotedForIsNotTheSameAsCandidateId(){
-        new JavaTestKit(getSystem()) {{
+    public void testHandleRequestVoteWhenSenderTermEqualToCurrentTermAndVotedForMatches() {
+        MockRaftActorContext context = createActorContext();
+        context.getTermInformation().update(1000, null);
 
-            new Within(duration("1 seconds")) {
-                protected void run() {
+        // Once a candidate is created it will immediately increment the current term so after
+        // construction the currentTerm should be 1001
+        candidate = new Candidate(context);
 
-                    RaftActorContext context = createActorContext(getTestActor());
+        setupPeers(1);
+        candidate.handleMessage(peerActors[0], new RequestVote(1001, context.getId(), 10000, 999));
 
-                    context.getTermInformation().update(1000, "test");
+        RequestVoteReply reply = MessageCollectorActor.expectFirstMatching(
+                peerActors[0], RequestVoteReply.class);
+        assertEquals("isVoteGranted", true, reply.isVoteGranted());
+        assertEquals("getTerm", 1001, reply.getTerm());
+    }
+
+    @Test
+    public void testHandleRequestVoteWhenSenderTermEqualToCurrentTermAndVotedForDoesNotMatch() {
+        MockRaftActorContext context = createActorContext();
+        context.getTermInformation().update(1000, null);
 
-                    RaftActorBehavior follower = createBehavior(context);
+        // Once a candidate is created it will immediately increment the current term so after
+        // construction the currentTerm should be 1001
+        candidate = new Candidate(context);
 
-                    follower.handleMessage(getTestActor(), new RequestVote(1001, "candidate", 10000, 999));
+        setupPeers(1);
 
-                    final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"), "RequestVoteReply") {
-                        // do not put code outside this method, will run afterwards
-                        protected Boolean match(Object in) {
-                            if (in instanceof RequestVoteReply) {
-                                RequestVoteReply reply = (RequestVoteReply) in;
-                                return reply.isVoteGranted();
-                            } else {
-                                throw noMatch();
-                            }
-                        }
-                    }.get();
+        // RequestVote candidate ID ("candidate2") does not match this candidate's votedFor
+        // (it votes for itself)
+        candidate.handleMessage(peerActors[0], new RequestVote(1001, "candidate2", 10000, 999));
 
-                    assertEquals(false, out);
-                }
-            };
-        }};
+        RequestVoteReply reply = MessageCollectorActor.expectFirstMatching(
+                peerActors[0], RequestVoteReply.class);
+        assertEquals("isVoteGranted", false, reply.isVoteGranted());
+        assertEquals("getTerm", 1001, reply.getTerm());
     }
 
 
 
-    @Override protected RaftActorBehavior createBehavior(RaftActorContext actorContext) {
+    @Override
+    protected RaftActorBehavior createBehavior(RaftActorContext actorContext) {
         return new Candidate(actorContext);
     }
 
-    @Override protected RaftActorContext createActorContext() {
-        return new MockRaftActorContext("test", getSystem(), candidateActor);
+    @Override protected MockRaftActorContext createActorContext() {
+        return new MockRaftActorContext("candidate", getSystem(), candidateActor);
     }
 
+    private Map<String, String> setupPeers(int count) {
+        Map<String, String> peerMap = new HashMap<>();
+        peerActors = new TestActorRef[count];
+        for(int i = 0; i < count; i++) {
+            peerActors[i] = actorFactory.createTestActor(Props.create(MessageCollectorActor.class),
+                    actorFactory.generateActorId("peer"));
+            peerMap.put("peer" + (i+1), peerActors[i].path().toString());
+        }
 
+        return peerMap;
+    }
+
+    @Override
+    protected void assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(RaftActorContext actorContext,
+            ActorRef actorRef, RaftRPC rpc) throws Exception {
+        super.assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(actorContext, actorRef, rpc);
+        assertEquals("New votedFor", null, actorContext.getTermInformation().getVotedFor());
+    }
 }
index 719a825..4e8e7fe 100644 (file)
 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 akka.testkit.TestActorRef;
 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.After;
+import org.junit.Assert;
 import org.junit.Test;
-import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
 import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
 import org.opendaylight.controller.cluster.raft.RaftActorContext;
 import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
+import org.opendaylight.controller.cluster.raft.Snapshot;
 import org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot;
 import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout;
 import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
 import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
 import org.opendaylight.controller.cluster.raft.messages.InstallSnapshot;
 import org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply;
+import org.opendaylight.controller.cluster.raft.messages.RaftRPC;
 import org.opendaylight.controller.cluster.raft.messages.RequestVote;
 import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
-import org.opendaylight.controller.cluster.raft.utils.DoNothingActor;
 import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
 
 public class FollowerTest extends AbstractRaftActorBehaviorTest {
 
-    private final ActorRef followerActor = getSystem().actorOf(Props.create(
-        DoNothingActor.class));
+    private final TestActorRef<MessageCollectorActor> followerActor = actorFactory.createTestActor(
+            Props.create(MessageCollectorActor.class), actorFactory.generateActorId("follower"));
 
+    private final TestActorRef<MessageCollectorActor> leaderActor = actorFactory.createTestActor(
+            Props.create(MessageCollectorActor.class), actorFactory.generateActorId("leader"));
 
-    @Override protected RaftActorBehavior createBehavior(RaftActorContext actorContext) {
+    private RaftActorBehavior follower;
+
+    @Override
+    @After
+    public void tearDown() throws Exception {
+        if(follower != null) {
+            follower.close();
+        }
+
+        super.tearDown();
+    }
+
+    @Override
+    protected RaftActorBehavior createBehavior(RaftActorContext actorContext) {
         return new Follower(actorContext);
     }
 
-    @Override protected  RaftActorContext createActorContext() {
+    @Override
+    protected  MockRaftActorContext createActorContext() {
         return createActorContext(followerActor);
     }
 
-    protected  RaftActorContext createActorContext(ActorRef actorRef){
-        return new MockRaftActorContext("test", getSystem(), actorRef);
+    @Override
+    protected  MockRaftActorContext createActorContext(ActorRef actorRef){
+        return new MockRaftActorContext("follower", getSystem(), actorRef);
     }
 
     @Test
     public void testThatAnElectionTimeoutIsTriggered(){
-        new JavaTestKit(getSystem()) {{
-
-            new Within(DefaultConfigParamsImpl.HEART_BEAT_INTERVAL.$times(6)) {
-                protected void run() {
-
-                    Follower follower = new Follower(createActorContext(getTestActor()));
-
-                    final Boolean out = new ExpectMsg<Boolean>(DefaultConfigParamsImpl.HEART_BEAT_INTERVAL.$times(6), "ElectionTimeout") {
-                        // do not put code outside this method, will run afterwards
-                        protected Boolean match(Object in) {
-                            if (in instanceof ElectionTimeout) {
-                                return true;
-                            } else {
-                                throw noMatch();
-                            }
-                        }
-                    }.get();
-
-                    assertEquals(true, out);
-                }
-            };
-        }};
+        MockRaftActorContext actorContext = createActorContext();
+        follower = new Follower(actorContext);
+
+        MessageCollectorActor.expectFirstMatching(followerActor, ElectionTimeout.class,
+                actorContext.getConfigParams().getElectionTimeOutInterval().$times(6).toMillis());
     }
 
     @Test
     public void testHandleElectionTimeout(){
-        RaftActorContext raftActorContext = createActorContext();
-        Follower follower =
-            new Follower(raftActorContext);
+        logStart("testHandleElectionTimeout");
 
-        RaftActorBehavior raftBehavior =
-            follower.handleMessage(followerActor, new ElectionTimeout());
+        follower = new Follower(createActorContext());
+
+        RaftActorBehavior raftBehavior = follower.handleMessage(followerActor, new ElectionTimeout());
 
         assertTrue(raftBehavior instanceof Candidate);
     }
 
     @Test
     public void testHandleRequestVoteWhenSenderTermEqualToCurrentTermAndVotedForIsNull(){
-        new JavaTestKit(getSystem()) {{
-
-            new Within(duration("1 seconds")) {
-                protected void run() {
-
-                    RaftActorContext context = createActorContext(getTestActor());
+        logStart("testHandleRequestVoteWhenSenderTermEqualToCurrentTermAndVotedForIsNull");
 
-                    context.getTermInformation().update(1000, null);
+        RaftActorContext context = createActorContext();
+        long term = 1000;
+        context.getTermInformation().update(term, null);
 
-                    RaftActorBehavior follower = createBehavior(context);
+        follower = createBehavior(context);
 
-                    follower.handleMessage(getTestActor(), new RequestVote(1000, "test", 10000, 999));
+        follower.handleMessage(leaderActor, new RequestVote(term, "test", 10000, 999));
 
-                    final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"), "RequestVoteReply") {
-                        // do not put code outside this method, will run afterwards
-                        protected Boolean match(Object in) {
-                            if (in instanceof RequestVoteReply) {
-                                RequestVoteReply reply = (RequestVoteReply) in;
-                                return reply.isVoteGranted();
-                            } else {
-                                throw noMatch();
-                            }
-                        }
-                    }.get();
+        RequestVoteReply reply = MessageCollectorActor.expectFirstMatching(leaderActor, RequestVoteReply.class);
 
-                    assertEquals(true, out);
-                }
-            };
-        }};
+        assertEquals("isVoteGranted", true, reply.isVoteGranted());
+        assertEquals("getTerm", term, reply.getTerm());
     }
 
     @Test
     public void testHandleRequestVoteWhenSenderTermEqualToCurrentTermAndVotedForIsNotTheSameAsCandidateId(){
-        new JavaTestKit(getSystem()) {{
-
-            new Within(duration("1 seconds")) {
-                protected void run() {
-
-                    RaftActorContext context = createActorContext(getTestActor());
+        logStart("testHandleRequestVoteWhenSenderTermEqualToCurrentTermAndVotedForIsNotTheSameAsCandidateId");
 
-                    context.getTermInformation().update(1000, "test");
+        RaftActorContext context = createActorContext();
+        long term = 1000;
+        context.getTermInformation().update(term, "test");
 
-                    RaftActorBehavior follower = createBehavior(context);
+        follower = createBehavior(context);
 
-                    follower.handleMessage(getTestActor(), new RequestVote(1000, "candidate", 10000, 999));
+        follower.handleMessage(leaderActor, new RequestVote(term, "candidate", 10000, 999));
 
-                    final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"), "RequestVoteReply") {
-                        // do not put code outside this method, will run afterwards
-                        protected Boolean match(Object in) {
-                            if (in instanceof RequestVoteReply) {
-                                RequestVoteReply reply = (RequestVoteReply) in;
-                                return reply.isVoteGranted();
-                            } else {
-                                throw noMatch();
-                            }
-                        }
-                    }.get();
+        RequestVoteReply reply = MessageCollectorActor.expectFirstMatching(leaderActor, RequestVoteReply.class);
 
-                    assertEquals(false, out);
-                }
-            };
-        }};
+        assertEquals("isVoteGranted", false, reply.isVoteGranted());
     }
 
     /**
@@ -163,32 +128,25 @@ public class FollowerTest extends AbstractRaftActorBehaviorTest {
      */
     @Test
     public void testHandleAppendEntriesWithNewerCommitIndex() throws Exception {
-        new JavaTestKit(getSystem()) {{
+        logStart("testHandleAppendEntriesWithNewerCommitIndex");
 
-            RaftActorContext context =
-                createActorContext();
+        MockRaftActorContext context = createActorContext();
 
-            context.setLastApplied(100);
-            setLastLogEntry((MockRaftActorContext) context, 1, 100,
+        context.setLastApplied(100);
+        setLastLogEntry(context, 1, 100,
                 new MockRaftActorContext.MockPayload(""));
-            ((MockRaftActorContext) context).getReplicatedLog().setSnapshotIndex(99);
+        context.getReplicatedLog().setSnapshotIndex(99);
 
-            List<ReplicatedLogEntry> entries =
-                Arrays.asList(
-                        (ReplicatedLogEntry) new MockRaftActorContext.MockReplicatedLogEntry(2, 101,
-                                new MockRaftActorContext.MockPayload("foo"))
-                );
+        List<ReplicatedLogEntry> entries = Arrays.<ReplicatedLogEntry>asList(
+                newReplicatedLogEntry(2, 101, "foo"));
 
-            // The new commitIndex is 101
-            AppendEntries appendEntries =
-                new AppendEntries(2, "leader-1", 100, 1, entries, 101, 100);
+        // The new commitIndex is 101
+        AppendEntries appendEntries = new AppendEntries(2, "leader-1", 100, 1, entries, 101, 100);
 
-            RaftActorBehavior raftBehavior =
-                createBehavior(context).handleMessage(getRef(), appendEntries);
+        follower = createBehavior(context);
+        follower.handleMessage(leaderActor, appendEntries);
 
-            assertEquals(101L, context.getLastApplied());
-
-        }};
+        assertEquals("getLastApplied", 101L, context.getLastApplied());
     }
 
     /**
@@ -199,58 +157,30 @@ public class FollowerTest extends AbstractRaftActorBehaviorTest {
      * @throws Exception
      */
     @Test
-    public void testHandleAppendEntriesSenderPrevLogTermNotSameAsReceiverPrevLogTerm()
-        throws Exception {
-        new JavaTestKit(getSystem()) {{
-
-            MockRaftActorContext context = (MockRaftActorContext)
-                createActorContext();
-
-            // First set the receivers term to lower number
-            context.getTermInformation().update(95, "test");
-
-            // Set the last log entry term for the receiver to be greater than
-            // what we will be sending as the prevLogTerm in AppendEntries
-            MockRaftActorContext.SimpleReplicatedLog mockReplicatedLog =
-                setLastLogEntry(context, 20, 0, new MockRaftActorContext.MockPayload(""));
-
-            // AppendEntries is now sent with a bigger term
-            // this will set the receivers term to be the same as the sender's term
-            AppendEntries appendEntries =
-                new AppendEntries(100, "leader-1", 0, 0, null, 101, -1);
+    public void testHandleAppendEntriesSenderPrevLogTermNotSameAsReceiverPrevLogTerm() {
+        logStart("testHandleAppendEntriesSenderPrevLogTermNotSameAsReceiverPrevLogTerm");
 
-            RaftActorBehavior behavior = createBehavior(context);
+        MockRaftActorContext context = createActorContext();
 
-            // Send an unknown message so that the state of the RaftActor remains unchanged
-            RaftActorBehavior expected = behavior.handleMessage(getRef(), "unknown");
+        // First set the receivers term to lower number
+        context.getTermInformation().update(95, "test");
 
-            RaftActorBehavior raftBehavior =
-                behavior.handleMessage(getRef(), appendEntries);
+        // AppendEntries is now sent with a bigger term
+        // this will set the receivers term to be the same as the sender's term
+        AppendEntries appendEntries = new AppendEntries(100, "leader", 0, 0, null, 101, -1);
 
-            assertEquals(expected, raftBehavior);
+        follower = createBehavior(context);
 
-            // Also expect an AppendEntriesReply to be sent where success is false
-            final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"),
-                "AppendEntriesReply") {
-                // do not put code outside this method, will run afterwards
-                protected Boolean match(Object in) {
-                    if (in instanceof AppendEntriesReply) {
-                        AppendEntriesReply reply = (AppendEntriesReply) in;
-                        return reply.isSuccess();
-                    } else {
-                        throw noMatch();
-                    }
-                }
-            }.get();
+        RaftActorBehavior newBehavior = follower.handleMessage(leaderActor, appendEntries);
 
-            assertEquals(false, out);
+        Assert.assertSame(follower, newBehavior);
 
+        AppendEntriesReply reply = MessageCollectorActor.expectFirstMatching(leaderActor,
+                AppendEntriesReply.class);
 
-        }};
+        assertEquals("isSuccess", false, reply.isSuccess());
     }
 
-
-
     /**
      * This test verifies that when a new AppendEntries message is received with
      * new entries and the logs of the sender and receiver match that the new
@@ -260,278 +190,201 @@ public class FollowerTest extends AbstractRaftActorBehaviorTest {
      * @throws Exception
      */
     @Test
-    public void testHandleAppendEntriesAddNewEntries() throws Exception {
-        new JavaTestKit(getSystem()) {{
-
-            MockRaftActorContext context = (MockRaftActorContext)
-                createActorContext();
-
-            // First set the receivers term to lower number
-            context.getTermInformation().update(1, "test");
-
-            // Prepare the receivers log
-            MockRaftActorContext.SimpleReplicatedLog log =
-                new MockRaftActorContext.SimpleReplicatedLog();
-            log.append(
-                new MockRaftActorContext.MockReplicatedLogEntry(1, 0, new MockRaftActorContext.MockPayload("zero")));
-            log.append(
-                new MockRaftActorContext.MockReplicatedLogEntry(1, 1, new MockRaftActorContext.MockPayload(&qu