Merge "Neutron LBaaS v2.0 API support"
authorMadhu Venugopal <mavenugo@gmail.com>
Fri, 8 Aug 2014 23:56:04 +0000 (23:56 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 8 Aug 2014 23:56:04 +0000 (23:56 +0000)
236 files changed:
features/config-netty/pom.xml
features/config-persister/pom.xml
features/netconf/pom.xml
features/protocol-framework/pom.xml
opendaylight/commons/opendaylight/pom.xml
opendaylight/config/config-manager/pom.xml
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/ConfigManagerActivator.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/runtimembean/RuntimeBeanRegistratorImplTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.java
opendaylight/config/config-netty-config/src/main/resources/initial/00-netty.xml
opendaylight/config/config-util/pom.xml
opendaylight/config/pom.xml
opendaylight/config/yang-jmx-generator-it/pom.xml
opendaylight/config/yang-jmx-generator/pom.xml
opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/RuntimeBeanEntryTest.java
opendaylight/distribution/opendaylight-karaf/pom.xml
opendaylight/distribution/opendaylight/pom.xml
opendaylight/md-sal/compatibility/flow-management-compatibility/pom.xml [deleted file]
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/ConfigurationReader.java [deleted file]
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.java [deleted file]
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowCommitTransaction.java [deleted file]
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.java [deleted file]
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowManagementReader.java [deleted file]
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/SampleConsumer.java [deleted file]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/pom.xml [deleted file]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/inventory/InventoryReader.java [deleted file]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/CompatibleSwitchManager.java [deleted file]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/ConfigurableSwitchManager.java [deleted file]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyMapping.java [deleted file]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyReader.java [deleted file]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/AdSalTopologyMapping.java [deleted file]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/CompatibleTopologyManager.java [deleted file]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/ConfigurableLinkManager.java [deleted file]
opendaylight/md-sal/compatibility/pom.xml
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java
opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/NodeMappingTest.java
opendaylight/md-sal/forwardingrules-manager/pom.xml
opendaylight/md-sal/md-sal-config/src/main/resources/initial/01-md-sal.xml
opendaylight/md-sal/pom.xml
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/DefaultConfigParamsImpl.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLog.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Leader.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImplTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/MockRaftActorContext.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/CandidateTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/FollowerTest.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedDataBroker.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBackwardsCompatibleDataBroker.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRouterCodegenInstance.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataTransactionImpl.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/MountPointManagerImpl.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcProviderRegistryImpl.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1418AugmentationTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/MockSchemaService.java
opendaylight/md-sal/sal-binding-dom-it/pom.xml
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java [deleted file]
opendaylight/md-sal/sal-binding-it/pom.xml
opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java
opendaylight/md-sal/sal-clustering-commons/README-FIRST [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/README-FIRST with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/pom.xml [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/pom.xml with 98% similarity]
opendaylight/md-sal/sal-clustering-commons/run.sh [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/run.sh with 93% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/NodeToNormalizedNodeBuilder.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/NodeToNormalizedNodeBuilder.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/NodeValueCodec.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/NodeValueCodec.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/NormalizedNodeToNodeCodec.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/NormalizedNodeToNodeCodec.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/NormalizedNodeToProtocolBufferNode.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/NormalizedNodeToProtocolBufferNode.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/AugmentationIdentifierGenerator.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/AugmentationIdentifierGenerator.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierFactory.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierFactory.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierGenerator.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierGenerator.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierWithPredicatesGenerator.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierWithPredicatesGenerator.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierWithValueGenerator.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierWithValueGenerator.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodeGetter.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodeGetter.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodeNavigator.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodeNavigator.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodePrinter.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodePrinter.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodeVisitor.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodeVisitor.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/PathUtils.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/PathUtils.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/QNameFactory.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/QNameFactory.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/util/EncoderDecoderUtil.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/util/EncoderDecoderUtil.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/util/InstanceIdentifierUtils.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/util/InstanceIdentifierUtils.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/mdsal/CompositeModificationPayload.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/mdsal/CompositeModificationPayload.java with 90% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/cohort3pc/ThreePhaseCommitCohortMessages.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/cohort3pc/ThreePhaseCommitCohortMessages.java with 99% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/common/NormalizedNodeMessages.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/common/NormalizedNodeMessages.java with 99% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/common/SimpleNormalizedNodeMessage.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/common/SimpleNormalizedNodeMessage.java with 98% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/datachange/notification/DataChangeListenerMessages.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/datachange/notification/DataChangeListenerMessages.java with 99% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/persistent/PersistentMessages.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/persistent/PersistentMessages.java with 99% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/registration/ListenerRegistrationMessages.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/registration/ListenerRegistrationMessages.java with 99% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/shard/ShardManagerMessages.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/shard/ShardManagerMessages.java with 99% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionChainMessages.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionChainMessages.java with 99% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessages.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessages.java with 98% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/Cohort.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/Cohort.proto with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/Common.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/Common.proto with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/CompositeModificationPayload.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/CompositeModificationPayload.proto with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/DataChangeListener.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/DataChangeListener.proto with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/ListenerRegistration.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ListenerRegistration.proto with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/Persistent.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/Persistent.proto with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/ShardManager.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ShardManager.proto with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/ShardTransaction.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ShardTransaction.proto with 96% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/ShardTransactionChain.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ShardTransactionChain.proto with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/SimpleNormalizedNode.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/SimpleNormalizedNode.proto with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/NormalizedNodeToNodeCodecTest.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/node/NormalizedNodeToNodeCodecTest.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierFactoryTest.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierFactoryTest.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/InstanceIdentifierUtilsTest.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/util/InstanceIdentifierUtilsTest.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/NormalizedNodeXmlConverterTest.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/util/NormalizedNodeXmlConverterTest.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/TestModel.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/util/TestModel.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/AbstractMessagesTest.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/protobuff/messages/AbstractMessagesTest.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/cohort3pc/ThreePhaseCommitCohortMessagesTest.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/protobuff/messages/cohort3pc/ThreePhaseCommitCohortMessagesTest.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/common/NormalizedNodeMessagesTest.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/protobuff/messages/common/NormalizedNodeMessagesTest.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/datachange/notification/DataChangeListenerMessagesTest.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/protobuff/messages/datachange/notification/DataChangeListenerMessagesTest.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/persistent/PersistentMessagesTest.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/protobuff/messages/persistent/PersistentMessagesTest.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/registration/ListenerRegistrationMessagesTest.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/protobuff/messages/registration/ListenerRegistrationMessagesTest.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/shard/ShardManagerMessagesTest.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/protobuff/messages/shard/ShardManagerMessagesTest.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionChainMessagesTest.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionChainMessagesTest.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessagesTest.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessagesTest.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/application.conf [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/application.conf with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/augment_choice.xml [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/augment_choice.xml with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/augment_choice.yang [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/augment_choice.yang with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/odl-datastore-augmentation.yang [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/odl-datastore-augmentation.yang with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/odl-datastore-test-notification.yang [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/odl-datastore-test-notification.yang with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/odl-datastore-test.yang [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/odl-datastore-test.yang with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/simple_xml_with_attributes.xml [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/simple_xml_with_attributes.xml with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/test.yang [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/test.yang with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/DataChangeListenerMessagesData [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/version-compatibility-serialized-data/DataChangeListenerMessagesData with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ListenerRegistrationMessagesData [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/version-compatibility-serialized-data/ListenerRegistrationMessagesData with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/NormalizedNodeMessagesTestData [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/version-compatibility-serialized-data/NormalizedNodeMessagesTestData with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/PersistentMessagesTestData [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/version-compatibility-serialized-data/PersistentMessagesTestData with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ShardManagerMessagesTestData [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/version-compatibility-serialized-data/ShardManagerMessagesTestData with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ShardTransactionChainMessagesTestData [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/version-compatibility-serialized-data/ShardTransactionChainMessagesTestData with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ShardTransactionMessagesTestData [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/version-compatibility-serialized-data/ShardTransactionMessagesTestData with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ThreePhaseCommitCohortMessagesTestData [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/version-compatibility-serialized-data/ThreePhaseCommitCohortMessagesTestData with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/readme.txt [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/version-compatibility-serialized-data/readme.txt with 100% similarity]
opendaylight/md-sal/sal-clustering-config/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/05-clustering.xml.conf [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/akka.conf [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/module-shards.conf [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/modules.conf [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionCommitDeadlockException.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.java
opendaylight/md-sal/sal-distributed-datastore/pom.xml
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ActorSystemFactory.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataChangeListener.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerProxy.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/ShardReadTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadWriteTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChain.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardWriteTransaction.java [new file with mode: 0644]
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/TransactionProxy.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStats.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStatsMBean.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransaction.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ModuleShardStrategy.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategy.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedConfigDataStoreProviderModule.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedOperationalDataStoreProviderModule.java
opendaylight/md-sal/sal-distributed-datastore/src/main/resources/application.conf
opendaylight/md-sal/sal-distributed-datastore/src/main/resources/modules.conf
opendaylight/md-sal/sal-distributed-datastore/src/main/yang/distributed-datastore-provider.yang
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/BasicIntegrationTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerProxyTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerRegistrationTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreIntegrationTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardManagerTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChainTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ModuleShardStrategyTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/resources/application.conf
opendaylight/md-sal/sal-distributed-datastore/src/test/resources/modules.conf
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcImplementationUnavailableException.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomInmemoryDataBrokerModule.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/mount/DOMMountPointServiceImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPointManager.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataTransactionImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointManagerImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RoutedRpcSelector.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareRpcBroker.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/store/impl/TestModel.java
opendaylight/md-sal/sal-dom-broker/src/test/resources/odl-datastore-test.yang
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ResolveDataChangeEventsTask.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/NetconfStateSchemas.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfDeviceCommunicator.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceReadOnlyTx.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/schema/mapping/NetconfMessageTransformer.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTest.java
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfStateSchemasTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfToNotificationTest.java
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfToRpcRequestTest.java
opendaylight/md-sal/sal-netconf-connector/src/test/resources/netconf-state.schemas.payload.xml [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/test/resources/schemas/config-test-rpc.yang [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/pom.xml
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModule.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModuleFactory.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/ActorSystemFactory.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcProviderFactory.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RpcManager.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RoutingTable.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RoutingTableOld.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistry.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistryOld.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/Bucket.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/BucketImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/BucketStore.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/Copier.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/Gossiper.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/Messages.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/XmlDocumentUtils.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/resources/application.conf
opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/RpcBrokerTest.java
opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/RoutingTableOldTest.java [moved from opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/RoutingTableTest.java with 97% similarity]
opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistryOldTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistryTest.java
opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/gossip/BucketStoreTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/gossip/GossiperTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/src/test/resources/application.conf [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestGetOperationTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java
opendaylight/md-sal/sal-rest-docgen/src/test/resources/yang/toaster_short.yang
opendaylight/md-sal/sal-test-model/src/main/java/org/opendaylight/controller/md/sal/test/model/util/ListsBindingUtils.java
opendaylight/md-sal/topology-lldp-discovery/pom.xml
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java
opendaylight/netconf/netconf-cli/pom.xml
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/NormalizedNodeWriter.java
opendaylight/netconf/netconf-it/pom.xml

index 98b97d1d95feabcfba4b8b4ca5b9bc15aafe8a5d..16fd975130592a1975332b6b390dbce2f9f1d614 100644 (file)
@@ -19,7 +19,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-persister-features</artifactId>
-      <version>${config.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
       <scope>runtime</scope>
index 969d0c8841b61caa947aa63166ff4ddba01c4a57..ec1520ed9818eb573942cde1ac6561110d2cb44f 100644 (file)
@@ -27,7 +27,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>netconf-features</artifactId>
-      <version>${netconf.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
       <scope>runtime</scope>
@@ -35,7 +34,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-features</artifactId>
-      <version>${config.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
       <scope>runtime</scope>
index 90c088eaba2aab2911bdc65fbbba281af094ecb4..856557c1e8245ef24ada6cdb63e9ad4c775b696e 100644 (file)
@@ -19,7 +19,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-features</artifactId>
-      <version>${config.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
       <scope>runtime</scope>
@@ -27,7 +26,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>features-odl-protocol-framework</artifactId>
-      <version>${protocol-framework.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
       <scope>runtime</scope>
index 045ac2dffec10871437ab784f53d7c97cbfe98cd..ba5dd18fc21615f3e52ddcbbe6f91c2323cc33d5 100644 (file)
@@ -19,7 +19,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-features</artifactId>
-      <version>${config.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
       <scope>runtime</scope>
index a7bbbe772d8514c150ec2a92de4acd3cdbca00d9..8797c7e85c7c0abbb06fc82df8f06783fc74b2d2 100644 (file)
     <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>
-    <junit.version>4.8.1</junit.version>
     <karaf.branding.version>1.0.0-SNAPSHOT</karaf.branding.version>
     <karaf.shell.version>3.0.0</karaf.shell.version>
     <karaf.version>3.0.1</karaf.version>
     <sonar.branch>${user.name}-private-view</sonar.branch>
     <sonar.host.url>https://sonar.opendaylight.org/</sonar.host.url>
     <!-- Sonar properties using jacoco to retrieve integration test results -->
+    <sonar-jacoco-listeners.version>2.4</sonar-jacoco-listeners.version>
     <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
     <sonar.language>java</sonar.language>
+    <sonar.jacoco.reportPath>target/code-coverage/jacoco.exec</sonar.jacoco.reportPath>
+    <sonar.jacoco.itReportPath>target/code-coverage/jacoco-it.exec</sonar.jacoco.itReportPath>
     <sonar.skippedModules>org.openflow.openflowj,net.sf.jung2,org.opendaylight.controller.protobuff.messages</sonar.skippedModules>
     <spifly.version>1.0.0</spifly.version>
     <spring-osgi.version>1.2.1</spring-osgi.version>
     <spring-security-karaf.version>3.1.4.RELEASE</spring-security-karaf.version>
     <spring-security.version>3.1.3.RELEASE</spring-security.version>
     <spring.version>3.1.3.RELEASE</spring.version>
-    <sonar.skippedModules>org.openflow.openflowj,net.sf.jung2</sonar.skippedModules>
     <statistics.northbound.version>0.4.2-SNAPSHOT</statistics.northbound.version>
     <statisticsmanager.implementation.version>0.4.2-SNAPSHOT</statisticsmanager.implementation.version>
     <statisticsmanager.version>0.5.1-SNAPSHOT</statisticsmanager.version>
         <artifactId>akka-testkit_${scala.version}</artifactId>
         <version>${akka.version}</version>
       </dependency>
+        <dependency>
+            <groupId>com.typesafe.akka</groupId>
+            <artifactId>akka-osgi_${scala.version}</artifactId>
+            <version>${akka.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.typesafe.akka</groupId>
+            <artifactId>akka-slf4j_${scala.version}</artifactId>
+            <version>${akka.version}</version>
+        </dependency>
       <dependency>
         <groupId>commons-codec</groupId>
         <artifactId>commons-codec</artifactId>
         <artifactId>filter-valve</artifactId>
         <version>${filtervalve.version}</version>
       </dependency>
-      <dependency>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>flow-management-compatibility</artifactId>
-        <version>${mdsal.version}</version>
-      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>flowprogrammer.northbound</artifactId>
         <artifactId>sal-distributed-datastore</artifactId>
         <version>${mdsal.version}</version>
       </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-clustering-commons</artifactId>
+            <version>${mdsal.version}</version>
+        </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-clustering-config</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
+
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-remoterpc-connector</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
+
 
       <!-- SAL Extension bundles -->
       <dependency>
         <artifactId>model-flow-base</artifactId>
         <version>${mdsal.version}</version>
       </dependency>
-      <dependency>
-        <groupId>org.opendaylight.controller.model</groupId>
-        <artifactId>model-flow-management</artifactId>
-        <version>${mdsal.version}</version>
-      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller.model</groupId>
         <artifactId>model-flow-service</artifactId>
         <artifactId>slf4j-simple</artifactId>
         <version>${slf4j.version}</version>
       </dependency>
-      <dependency>
-        <groupId>junit</groupId>
-        <artifactId>junit</artifactId>
-        <version>${junit.version}</version>
-        <scope>test</scope>
-      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>commons.logback_settings</artifactId>
         <version>${yangtools.version}</version>
         <scope>test</scope>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>config-features</artifactId>
+        <version>${config.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>features-odl-protocol-framework</artifactId>
+        <version>${protocol-framework.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>netconf-features</artifactId>
+        <version>${netconf.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>config-persister-features</artifactId>
+        <version>${config.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>config-netty-features</artifactId>
+        <version>${config.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>features-adsal</artifactId>
+        <version>${sal.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>mdsal-features</artifactId>
+        <version>${mdsal.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
     </dependencies>
   </dependencyManagement>
 
+  <dependencies>
+    <!-- Sonar -->
+    <dependency>
+      <groupId>org.codehaus.sonar-plugins.java</groupId>
+      <artifactId>sonar-jacoco-listeners</artifactId>
+      <version>${sonar-jacoco-listeners.version}</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
   <build>
     <pluginManagement>
       <plugins>
           <groupId>org.jacoco</groupId>
           <artifactId>jacoco-maven-plugin</artifactId>
           <version>${jacoco.version}</version>
+          <executions>
+            <execution>
+              <id>prepare-ut-agent</id>
+              <phase>process-test-classes</phase>
+              <goals>
+                <goal>prepare-agent</goal>
+              </goals>
+              <configuration>
+                <destFile>${sonar.jacoco.reportPath}</destFile>
+                <propertyName>jacoco.agent.ut.arg</propertyName>
+              </configuration>
+            </execution>
+            <execution>
+              <id>prepare-it-agent</id>
+              <phase>pre-integration-test</phase>
+              <goals>
+                <goal>prepare-agent</goal>
+              </goals>
+              <configuration>
+                <destFile>${sonar.jacoco.itReportPath}</destFile>
+                <propertyName>jacoco.agent.it.arg</propertyName>
+              </configuration>
+            </execution>
+          </executions>
         </plugin>
         <plugin>
           <groupId>org.opendaylight.yangtools</groupId>
         <artifactId>maven-failsafe-plugin</artifactId>
         <version>${failsafe.version}</version>
         <configuration>
-          <argLine>${testvm.argLine}</argLine>
+          <argLine>${testvm.argLine} ${jacoco.agent.it.arg}</argLine>
           <systemProperties>
             <property>
               <name>logback.configurationFile</name>
               <value>logback.xml</value>
             </property>
           </systemProperties>
+          <!-- Specific to generate mapping between tests and covered code -->
+          <properties>
+            <property>
+                <name>listener</name>
+                <value>org.sonar.java.jacoco.JUnitListener</value>
+            </property>
+          </properties>
         </configuration>
         <executions>
           <execution>
         <artifactId>maven-surefire-plugin</artifactId>
         <version>${surefire.version}</version>
         <configuration>
-          <argLine>${testvm.argLine}</argLine>
+          <argLine>${testvm.argLine} ${jacoco.agent.ut.arg}</argLine>
           <systemProperties>
             <property>
               <name>logback.configurationFile</name>
               <value>logback.xml</value>
             </property>
           </systemProperties>
+          <!-- Specific to generate mapping between tests and covered code -->
+          <properties>
+            <property>
+                <name>listener</name>
+                <value>org.sonar.java.jacoco.JUnitListener</value>
+            </property>
+          </properties>
         </configuration>
       </plugin>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>build-helper-maven-plugin</artifactId>
       </plugin>
+      <plugin>
+        <groupId>org.jacoco</groupId>
+        <artifactId>jacoco-maven-plugin</artifactId>
+      </plugin>
     </plugins>
   </build>
 
index fc2c0fd85b86f79a60c30fb34bc8199b1459c1c9..c98a47660ee3c92a8ebec0ea586d40af31dca99d 100644 (file)
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-jar-plugin</artifactId>
       </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <configuration>
-          <forkCount>1</forkCount>
-          <reuseForks>false</reuseForks>
-          <perCoreThreadCount>false</perCoreThreadCount>
-          <threadCount>1</threadCount>
-        </configuration>
-      </plugin>
     </plugins>
   </build>
 
index 6381836af856f06c6eba19eccfaa4529da6c1194..828fcb01e11bb00a9fde10f064b93cc2cac34863 100644 (file)
@@ -7,6 +7,14 @@
  */
 package org.opendaylight.controller.config.manager.impl.osgi;
 
+import static org.opendaylight.controller.config.manager.impl.util.OsgiRegistrationUtil.registerService;
+import static org.opendaylight.controller.config.manager.impl.util.OsgiRegistrationUtil.wrap;
+
+import java.lang.management.ManagementFactory;
+import java.util.Arrays;
+import java.util.List;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.MBeanServer;
 import org.opendaylight.controller.config.manager.impl.ConfigRegistryImpl;
 import org.opendaylight.controller.config.manager.impl.jmx.ConfigRegistryJMXRegistrator;
 import org.opendaylight.controller.config.manager.impl.osgi.mapping.CodecRegistryProvider;
@@ -14,27 +22,19 @@ import org.opendaylight.controller.config.manager.impl.osgi.mapping.ModuleInfoBu
 import org.opendaylight.controller.config.manager.impl.osgi.mapping.RefreshingSCPModuleInfoRegistry;
 import org.opendaylight.controller.config.manager.impl.util.OsgiRegistrationUtil;
 import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
 import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.util.tracker.ServiceTracker;
 
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.MBeanServer;
-import java.lang.management.ManagementFactory;
-import java.util.Arrays;
-import java.util.List;
-
-import static org.opendaylight.controller.config.manager.impl.util.OsgiRegistrationUtil.registerService;
-import static org.opendaylight.controller.config.manager.impl.util.OsgiRegistrationUtil.wrap;
-
 public class ConfigManagerActivator implements BundleActivator {
     private final MBeanServer configMBeanServer = ManagementFactory.getPlatformMBeanServer();
 
     private AutoCloseable autoCloseable;
 
     @Override
-    public void start(BundleContext context) {
+    public void start(final BundleContext context) {
 
         ModuleInfoBackedContext moduleInfoBackedContext = ModuleInfoBackedContext.create();// the inner strategy is backed by thread context cl?
 
@@ -63,6 +63,7 @@ public class ConfigManagerActivator implements BundleActivator {
         bundleTracker.open();
 
         // register config registry to OSGi
+        AutoCloseable clsReg = registerService(context, moduleInfoBackedContext, GeneratedClassLoadingStrategy.class);
         AutoCloseable configRegReg = registerService(context, configRegistry, ConfigRegistryImpl.class);
 
         // register config registry to jmx
@@ -79,12 +80,12 @@ public class ConfigManagerActivator implements BundleActivator {
         serviceTracker.open();
 
         List<AutoCloseable> list = Arrays.asList(
-                codecRegistryProvider, configRegistry, wrap(bundleTracker), configRegReg, configRegistryJMXRegistrator, wrap(serviceTracker));
+                codecRegistryProvider, clsReg,configRegistry, wrap(bundleTracker), configRegReg, configRegistryJMXRegistrator, wrap(serviceTracker));
         autoCloseable = OsgiRegistrationUtil.aggregate(list);
     }
 
     @Override
-    public void stop(BundleContext context) throws Exception {
+    public void stop(final BundleContext context) throws Exception {
         autoCloseable.close();
     }
 }
index ce3648d1607009aacd5ecc41e2a1f119660d8045..16de00508ab4e7ecf4d7fc6df22b6b476b37ae1d 100644 (file)
@@ -7,10 +7,12 @@
  */
 package org.opendaylight.controller.config.manager.impl.runtimembean;
 
+import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.fail;
-import static org.junit.internal.matchers.StringContains.containsString;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
 
 import java.lang.management.ManagementFactory;
 import java.util.Map;
@@ -29,9 +31,6 @@ import org.opendaylight.controller.config.manager.impl.jmx.BaseJMXRegistrator;
 import org.opendaylight.controller.config.manager.impl.jmx.HierarchicalRuntimeBeanRegistrationImpl;
 import org.opendaylight.controller.config.manager.impl.jmx.RootRuntimeBeanRegistratorImpl;
 
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-
 public class RuntimeBeanRegistratorImplTest extends
         AbstractLockedPlatformMBeanServerTest {
     static final String module1 = "module1";
@@ -60,11 +59,11 @@ public class RuntimeBeanRegistratorImplTest extends
         assertEquals(0, baseJMXRegistrator.getRegisteredObjectNames().size());
     }
 
-    protected void checkExists(ObjectName on) throws Exception {
+    protected void checkExists(final ObjectName on) throws Exception {
         platformMBeanServer.getMBeanInfo(on);
     }
 
-    protected void checkNotExists(ObjectName on) throws Exception {
+    protected void checkNotExists(final ObjectName on) throws Exception {
         try {
             platformMBeanServer.getMBeanInfo(on);
             fail();
@@ -98,7 +97,7 @@ public class RuntimeBeanRegistratorImplTest extends
     }
 
     private HierarchicalRuntimeBeanRegistration createAdditional(
-            HierarchicalRuntimeBeanRegistrationImpl rootRegistration)
+            final HierarchicalRuntimeBeanRegistrationImpl rootRegistration)
             throws Exception {
 
         HierarchicalRuntimeBeanRegistrationImpl registration = rootRegistration
index c9810d052149ead1b358d14b42bda64d33c707c9..165a6c7ed62e02bdbb05e5644962dc15b42712d9 100644 (file)
@@ -7,14 +7,16 @@
  */
 package org.opendaylight.controller.config.manager.testingservices.parallelapsp.test;
 
+import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.junit.internal.matchers.StringContains.containsString;
 
 import java.util.Map;
+
 import javax.management.ObjectName;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
index 686d3631108d250f5dc56b825200e387536dd9c5..2bf5b36d7a770c43bc5a51fa2e7eb7c057624041 100644 (file)
@@ -15,7 +15,7 @@
         <capability>urn:opendaylight:params:xml:ns:yang:controller:netty:timer?module=netty-timer&amp;revision=2013-11-19</capability>
     </required-capabilities>
     <configuration>
-    
+
         <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
             <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
                 <module>
@@ -35,7 +35,7 @@
                     <name>singleton</name>
                 </module>
             </modules>
-            
+
             <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
                 <service>
                     <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-threadgroup</type>
index 7429f4d57431c9922d9a33ef5e8053ef1cfd174f..fd9c1b91e3944146b0d1ad9fb63f78acc5b2daff 100644 (file)
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-jar-plugin</artifactId>
       </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <configuration>
-          <forkCount>1</forkCount>
-          <reuseForks>false</reuseForks>
-          <perCoreThreadCount>false</perCoreThreadCount>
-          <threadCount>1</threadCount>
-        </configuration>
-      </plugin>
       <plugin>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
index 26fac47e71cc63c6d1462335a7f520f9309ed259..343d13e9c19194ad67680801639fdf52df9563b3 100644 (file)
             </execution>
           </executions>
         </plugin>
-        <plugin>
-          <groupId>org.apache.maven.plugins</groupId>
-          <artifactId>maven-surefire-plugin</artifactId>
-          <configuration>
-            <redirectTestOutputToFile>true</redirectTestOutputToFile>
-            <parallel>classes</parallel>
-            <forkCount>1C</forkCount>
-            <reuseForks>false</reuseForks>
-            <perCoreThreadCount>true</perCoreThreadCount>
-            <threadCount>2</threadCount>
-          </configuration>
-        </plugin>
         <plugin>
           <groupId>org.codehaus.groovy.maven</groupId>
           <artifactId>gmaven-plugin</artifactId>
index c91881bd3e639e48424dd9e8d02ee4f7201b970e..f9e0c7036a858b60246a7956a8bdc6fc7ba18d44 100644 (file)
       <scope>test</scope>
     </dependency>
   </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <configuration>
-          <forkCount>1</forkCount>
-          <reuseForks>false</reuseForks>
-          <perCoreThreadCount>false</perCoreThreadCount>
-        </configuration>
-        <executions>
-          <execution>
-            <id>default-test</id>
-            <configuration>
-              <skip>true</skip>
-            </configuration>
-          </execution>
-          <execution>
-            <id>integration-tests</id>
-            <goals>
-              <goal>test</goal>
-            </goals>
-            <phase>integration-test</phase>
-            <configuration>
-              <includes>
-                <include>**/org/opendaylight/controller/config/yangjmxgenerator/it/*.java</include>
-              </includes>
-              <skip>false</skip>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
 </project>
index fbae840fc65df1df5c1bb1ea83f60a94989c3b5e..133b07ff8661f5ce4e8851e7e6de378f4c8740c2 100644 (file)
       <artifactId>yang-parser-impl</artifactId>
       <scope>test</scope>
     </dependency>
-    <dependency>
-       <groupId>org.hamcrest</groupId>
-       <artifactId>hamcrest-core</artifactId>
-       <version>1.1</version>
-       <scope>test</scope>
-     </dependency>
   </dependencies>
 
   <build>
index b570302563b9d9c4e00a4171614beb28df578cd8..e80ebc67a566197294ac64e2c431dd07c5131b3c 100644 (file)
@@ -7,7 +7,22 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator;
 
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import javax.management.openmbean.SimpleType;
+
 import org.junit.Test;
 import org.mockito.Mockito;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
@@ -18,20 +33,6 @@ import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 
-import javax.management.openmbean.SimpleType;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
-import static org.hamcrest.CoreMatchers.is;
-
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.doReturn;
-
 public class RuntimeBeanEntryTest extends AbstractYangTest {
 
     public static final String PACKAGE_NAME = "packages.sis";
@@ -54,10 +55,10 @@ public class RuntimeBeanEntryTest extends AbstractYangTest {
         Map<String, RuntimeBeanEntry> runtimeBeans = RuntimeBeanEntry
                 .extractClassNameToRuntimeBeanMap(PACKAGE_NAME, caseNode, "test-name", new TypeProviderWrapper(new
                         TypeProviderImpl(context)), "test", jmxImplModule);
-        assertThat(runtimeBeans.size(), is(1));
+        assertEquals(1, runtimeBeans.size());
         RuntimeBeanEntry runtimeMXBean = runtimeBeans.get("testRuntimeMXBean");
-        assertThat(runtimeMXBean.isRoot(), is(true));
-        assertThat(runtimeMXBean.getYangName(), is("test-name"));
+        assertTrue(runtimeMXBean.isRoot());
+        assertEquals("test-name", runtimeMXBean.getYangName());
     }
 
     @Test
@@ -72,7 +73,7 @@ public class RuntimeBeanEntryTest extends AbstractYangTest {
                 threadsJavaModule, modulesToSIEs, context,
                 new TypeProviderWrapper(new TypeProviderImpl(context)),
                 PACKAGE_NAME);
-        assertThat(namesToMBEs.isEmpty(), is(false));
+        assertFalse(namesToMBEs.isEmpty());
 
         // get threadfactory-naming bean
         ModuleMXBeanEntry threadfactoryNamingMXBean = namesToMBEs
@@ -82,13 +83,13 @@ public class RuntimeBeanEntryTest extends AbstractYangTest {
         // get runtime beans
         Collection<RuntimeBeanEntry> runtimeBeanEntries = threadfactoryNamingMXBean
                 .getRuntimeBeans();
-        assertThat(runtimeBeanEntries.isEmpty(), is(false));
+        assertFalse(runtimeBeanEntries.isEmpty());
 
         // get root runtime bean
         RuntimeBeanEntry threadfactoryRuntimeBeanEntry = getRuntimeBeanEntryByJavaName(
                 runtimeBeanEntries, "NamingThreadFactoryRuntimeMXBean");
         assertNotNull(threadfactoryRuntimeBeanEntry);
-        assertThat(threadfactoryRuntimeBeanEntry.isRoot(), is(true));
+        assertTrue(threadfactoryRuntimeBeanEntry.isRoot());
 
         // get thread runtime bean
         RuntimeBeanEntry runtimeBeanEntry = getRuntimeBeanEntryByJavaName(
@@ -96,43 +97,41 @@ public class RuntimeBeanEntryTest extends AbstractYangTest {
         assertNotNull(runtimeBeanEntry);
 
         // test thread runtime bean properties
-        assertThat(runtimeBeanEntry.getJavaNamePrefix(),
-                is(THREAD_RUNTIME_BEAN_JAVA_PREFIX));
-        assertThat(runtimeBeanEntry.getPackageName(), is(PACKAGE_NAME));
-        assertThat(runtimeBeanEntry.getFullyQualifiedName(runtimeBeanEntry
-                .getJavaNameOfRuntimeMXBean()), is(PACKAGE_NAME + "."
-                + THREAD_RUNTIME_BEAN_JAVA_NAME));
-        assertThat(runtimeBeanEntry.getYangName(),
-                is(THREAD_RUNTIME_BEAN_YANG_NAME));
+        assertEquals(THREAD_RUNTIME_BEAN_JAVA_PREFIX, runtimeBeanEntry.getJavaNamePrefix());
+        assertEquals(PACKAGE_NAME, runtimeBeanEntry.getPackageName());
+        assertEquals(PACKAGE_NAME + "." + THREAD_RUNTIME_BEAN_JAVA_NAME,
+            runtimeBeanEntry.getFullyQualifiedName(runtimeBeanEntry
+                .getJavaNameOfRuntimeMXBean()));
+        assertEquals(THREAD_RUNTIME_BEAN_YANG_NAME, runtimeBeanEntry.getYangName());
 
         // get thread runtime bean rpcs
         List<RuntimeBeanEntry.Rpc> rpcs = new ArrayList<RuntimeBeanEntry.Rpc>(
                 runtimeBeanEntry.getRpcs());
-        assertThat(rpcs.size(), is(2));
+        assertEquals(2, rpcs.size());
 
         // get sleep rpc and test it
         RuntimeBeanEntry.Rpc rpc = getRpcByName(rpcs, SLEEP_RPC_NAME);
         assertNotNull(rpc);
-        assertThat(rpc.getYangName(), is(SLEEP_RPC_NAME));
+        assertEquals(SLEEP_RPC_NAME, rpc.getYangName());
 
-        assertThat(((JavaAttribute)rpc.getReturnType()).getType().getFullyQualifiedName().endsWith(SLEEP_RPC_OUTPUT),  is(true));
+        assertTrue(((JavaAttribute)rpc.getReturnType()).getType().getFullyQualifiedName().endsWith(SLEEP_RPC_OUTPUT));
 
         // get sleep rpc input attribute and test it
         List<JavaAttribute> attributes = rpc.getParameters();
-        assertThat(attributes.size(), is(1));
+        assertEquals(1, attributes.size());
         JavaAttribute attribute = attributes.get(0);
-        assertThat(attribute.getAttributeYangName(), is(SLEEP_RPC_INPUT_NAME));
-        assertThat(attribute.getType().getName(), is(SLEEP_RPC_INPUT_TYPE));
-        assertThat(attribute.getLowerCaseCammelCase(), is(SLEEP_RPC_INPUT_NAME));
-        assertThat(attribute.getUpperCaseCammelCase(), is("Millis"));
+        assertEquals(SLEEP_RPC_INPUT_NAME, attribute.getAttributeYangName());
+        assertEquals(SLEEP_RPC_INPUT_TYPE, attribute.getType().getName());
+        assertEquals(SLEEP_RPC_INPUT_NAME, attribute.getLowerCaseCammelCase());
+        assertEquals("Millis", attribute.getUpperCaseCammelCase());
         assertNull(attribute.getNullableDefault());
         assertNull(attribute.getNullableDescription());
-        assertThat(attribute.getOpenType(), is(SimpleType.class));
+        assertTrue(attribute.getOpenType() instanceof SimpleType);
     }
 
     private RuntimeBeanEntry getRuntimeBeanEntryByJavaName(
             final Collection<RuntimeBeanEntry> runtimeBeanEntries,
-            String javaName) {
+            final String javaName) {
         if (runtimeBeanEntries != null && !runtimeBeanEntries.isEmpty()) {
             for (RuntimeBeanEntry runtimeBeanEntry : runtimeBeanEntries) {
                 if (runtimeBeanEntry.getJavaNameOfRuntimeMXBean().equals(
@@ -145,7 +144,7 @@ public class RuntimeBeanEntryTest extends AbstractYangTest {
     }
 
     private RuntimeBeanEntry.Rpc getRpcByName(
-            final List<RuntimeBeanEntry.Rpc> rpcs, String name) {
+            final List<RuntimeBeanEntry.Rpc> rpcs, final String name) {
         if (rpcs != null && !rpcs.isEmpty()) {
             for (RuntimeBeanEntry.Rpc rpc : rpcs) {
                 if (rpc.getName().equals(name)) {
index 977fab1334ae48791f9901aedbc1420eabb1e2e7..5effbb09fc81536ed2cf176427c37f25d16e9ddf 100644 (file)
@@ -64,7 +64,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-netty-features</artifactId>
-      <version>${config.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
       <scope>runtime</scope>
@@ -74,7 +73,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>features-adsal</artifactId>
-      <version>${sal.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
       <scope>runtime</scope>
@@ -92,7 +90,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>mdsal-features</artifactId>
-      <version>${mdsal.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
       <scope>runtime</scope>
index e4468b6f2735f4c7189ccf236fc48b5d8384e0e6..7ab56e6d03d63071216189c716f3022b6e834967 100644 (file)
             <phase>generate-resources</phase>
             <configuration>
                <outputDirectory>${project.build.directory}/configuration</outputDirectory>
-               <includeArtifactIds>sal-rest-connector-config,config-netty-config,md-sal-config,netconf-config,toaster-config,netconf-connector-config</includeArtifactIds>
-               <includes>**\/*.xml</includes>
+               <includeArtifactIds>sal-rest-connector-config,config-netty-config,md-sal-config,netconf-config,toaster-config,netconf-connector-config,sal-clustering-config</includeArtifactIds>
+               <includes>**\/*.xml,**/*.conf</includes>
                <excludeTransitive>true</excludeTransitive>
                <ignorePermissions>false</ignorePermissions>
             </configuration>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-restconf-broker</artifactId>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-remoterpc-connector</artifactId>
+        </dependency>
+
 
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>jeromq</artifactId>
           <version>0.3.1</version>
         </dependency>
-          <dependency>
-              <groupId>org.opendaylight.controller</groupId>
-              <artifactId>sal-distributed-datastore</artifactId>
-          </dependency>
-
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-distributed-datastore</artifactId>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-clustering-config</artifactId>
+        </dependency>
       </dependencies>
     </profile>
     <profile>
diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/pom.xml b/opendaylight/md-sal/compatibility/flow-management-compatibility/pom.xml
deleted file mode 100644 (file)
index 7770c15..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>org.opendaylight.controller</groupId>
-    <artifactId>compatibility-parent</artifactId>
-    <version>1.1-SNAPSHOT</version>
-  </parent>
-  <artifactId>flow-management-compatibility</artifactId>
-  <packaging>bundle</packaging>
-
-  <dependencies>
-    <dependency>
-      <groupId>com.google.guava</groupId>
-      <artifactId>guava</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>forwardingrulesmanager</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-binding-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-common-util</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-compatibility</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.model</groupId>
-      <artifactId>model-flow-management</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-api</artifactId>
-    </dependency>
-    <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>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Bundle-Name>Forwarding Rules Manager Adapter for MD-SAL</Bundle-Name>
-          </instructions>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-  <scm>
-    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
-    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
-    <tag>HEAD</tag>
-    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
-  </scm>
-</project>
diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/ConfigurationReader.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/ConfigurationReader.java
deleted file mode 100644 (file)
index 411af28..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.frm.compatibility;
-
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
-import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
-import org.opendaylight.controller.sal.compatibility.NodeMapping;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.FlowsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ConfigurationReader implements FlowManagementReader {
-
-    private final static Logger LOG = LoggerFactory.getLogger(ConfigurationReader.class);
-
-    private IForwardingRulesManager manager;
-
-    @Override
-    public Flows readAllFlows() {
-        List<FlowConfig> staticFlows = this.manager.getStaticFlows();
-        List<Flow> flowMap = new ArrayList<Flow>(staticFlows.size());
-
-        for (FlowConfig conf : staticFlows) {
-            flowMap.add(FlowConfigMapping.toConfigurationFlow(conf));
-        }
-        final FlowsBuilder flowsBuilder = new FlowsBuilder();
-        return (flowsBuilder.setFlow(flowMap)).build();
-    }
-
-    @Override
-    public Flow readFlow(final FlowKey key) {
-        try {
-            final FlowConfig flowConf =
-                    this.manager.getStaticFlow(String.valueOf(key.getId()), NodeMapping.toADNode(key.getNode()));
-            return FlowConfigMapping.toConfigurationFlow(flowConf);
-        } catch (Exception e) {
-            String errMsg = MessageFormat.format("readFlow by key {} fail", key);
-            LOG.error(errMsg, e);
-            throw new RuntimeException(errMsg, e);
-        }
-    }
-
-    public IForwardingRulesManager getManager() {
-        return this.manager;
-    }
-
-    public void setManager(final IForwardingRulesManager manager) {
-        this.manager = manager;
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.java
deleted file mode 100644 (file)
index 0653eeb..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.frm.compatibility;
-
-import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
-import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
-import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
-import org.opendaylight.controller.sal.common.util.Arguments;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.Identifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-
-public class FRMRuntimeDataProvider implements RuntimeDataProvider, DataCommitHandler<InstanceIdentifier<? extends DataObject>,DataObject> {
-
-    private final static InstanceIdentifier<Flows> FLOWS_PATH = InstanceIdentifier.<Flows> builder(Flows.class).toInstance();
-
-    private final FlowManagementReader configuration = new ConfigurationReader();
-    private DataChangeListener<InstanceIdentifier<? extends DataObject>, DataObject> changeListener;
-    private DataProviderService dataService;
-    private IForwardingRulesManager manager;
-
-    public Registration init() {
-        return this.dataService.registerCommitHandler(FRMRuntimeDataProvider.FLOWS_PATH, this);
-    }
-
-    @Override
-    public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
-        return this.readFrom(this.configuration, path);
-    }
-
-    @Override
-    public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
-        return this.readFrom(this.configuration, path);
-    }
-
-    public DataObject readFrom(final FlowManagementReader store, final InstanceIdentifier<? extends DataObject> path) {
-        if (Objects.equal(FRMRuntimeDataProvider.FLOWS_PATH, path)) {
-            return store.readAllFlows();
-        }
-        if (FRMRuntimeDataProvider.FLOWS_PATH.contains(path)) {
-            return store.readFlow(this.toFlowKey(path));
-        }
-        return null;
-    }
-
-    @Override
-    public FlowCommitTransaction requestCommit(final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
-        return new FlowCommitTransaction(this, modification);
-    }
-
-    public FlowKey toFlowKey(final InstanceIdentifier<? extends DataObject> identifier) {
-        Preconditions.<InstanceIdentifier<? extends DataObject>> checkNotNull(identifier);
-
-        Iterable<PathArgument> path = identifier.getPathArguments();
-        PathArgument get = path.iterator().next();
-        final Identifier itemKey = Arguments.<IdentifiableItem> checkInstanceOf(get, IdentifiableItem.class).getKey();
-        return Arguments.<FlowKey> checkInstanceOf(itemKey, FlowKey.class);
-    }
-
-    public RpcResult<Void> finish(final FlowCommitTransaction transaction) {
-        Iterable<FlowConfig> toRemove = transaction.getToRemove();
-        for (final FlowConfig flow : toRemove) {
-            this.manager.removeStaticFlow(flow.getName(), flow.getNode());
-        }
-        Iterable<FlowConfig> toUpdate = transaction.getToUpdate();
-        for (final FlowConfig flow : toUpdate) {
-            this.manager.removeStaticFlow(flow.getName(), flow.getNode());
-            this.manager.addStaticFlow(flow);
-        }
-        return RpcResultBuilder.<Void> success().build();
-    }
-
-    public RpcResult<Void> rollback(final FlowCommitTransaction transaction) {
-        return null;
-    }
-
-    public DataProviderService getDataService() {
-        return this.dataService;
-    }
-
-    public void setDataService(final DataProviderService dataService) {
-        this.dataService = dataService;
-    }
-
-    public DataChangeListener<InstanceIdentifier<? extends DataObject>, DataObject> getChangeListener() {
-        return this.changeListener;
-    }
-
-    public void setChangeListener(final DataChangeListener<InstanceIdentifier<? extends DataObject>, DataObject> changeListener) {
-        this.changeListener = changeListener;
-    }
-
-    public IForwardingRulesManager getManager() {
-        return this.manager;
-    }
-
-    public void setManager(final IForwardingRulesManager manager) {
-        this.manager = manager;
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowCommitTransaction.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowCommitTransaction.java
deleted file mode 100644 (file)
index bf0050d..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.frm.compatibility;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-
-public class FlowCommitTransaction implements DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
-
-    private final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
-    private final HashSet<FlowConfig> toAdd = new HashSet<FlowConfig>();
-    private final FRMRuntimeDataProvider flowManager;
-    private Iterable<FlowConfig> toUpdate;
-    private Iterable<FlowConfig> toRemove;
-
-    public FlowCommitTransaction(
-            final FRMRuntimeDataProvider flowManager,
-            final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
-        this.flowManager = flowManager;
-        this.modification = modification;
-        this.processModification();
-    }
-
-    @Override
-    public RpcResult<Void> finish() throws IllegalStateException {
-        return this.flowManager.finish(this);
-    }
-
-    @Override
-    public RpcResult<Void> rollback() throws IllegalStateException {
-        return this.flowManager.rollback(this);
-    }
-
-    public void processModification() {
-        final Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updated =
-                this.modification.getUpdatedConfigurationData().entrySet();
-        final List<FlowConfig> forUpdate = new ArrayList<FlowConfig>(updated.size());
-
-        if (updated != null && !(updated.isEmpty())) {
-            for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : updated) {
-                if (FlowConfigMapping.isFlowPath(entry.getKey())) {
-                    forUpdate.add(FlowConfigMapping.toFlowConfig((Flow) entry.getValue()));
-                }
-            }
-        }
-        this.toUpdate = Collections.unmodifiableCollection(forUpdate);
-
-        final Set<InstanceIdentifier<? extends DataObject>> removedConfigurationData =
-                this.modification.getRemovedConfigurationData();
-        final List<FlowConfig> forRemove = new ArrayList<FlowConfig>(removedConfigurationData.size());
-
-        if (removedConfigurationData != null && !(removedConfigurationData.isEmpty())) {
-            for (InstanceIdentifier<? extends DataObject> data : removedConfigurationData) {
-                if (FlowConfigMapping.isFlowPath(data)) {
-                    forRemove.add(FlowConfigMapping.toFlowConfig(data));
-                }
-            }
-        }
-        this.toRemove = Collections.unmodifiableCollection(forRemove);
-    }
-
-    @Override
-    public DataModification<InstanceIdentifier<? extends DataObject>, DataObject> getModification() {
-        return this.modification;
-    }
-
-    public FRMRuntimeDataProvider getFlowManager() {
-        return this.flowManager;
-    }
-
-    public HashSet<FlowConfig> getToAdd() {
-        return this.toAdd;
-    }
-
-    public Iterable<FlowConfig> getToUpdate() {
-        return this.toUpdate;
-    }
-
-    public Iterable<FlowConfig> getToRemove() {
-        return this.toRemove;
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.java
deleted file mode 100644 (file)
index 58c60ec..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.frm.compatibility;
-
-import java.text.MessageFormat;
-import java.util.Iterator;
-
-import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
-import org.opendaylight.controller.sal.compatibility.MDFlowMapping;
-import org.opendaylight.controller.sal.compatibility.NodeMapping;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
-import org.opendaylight.yangtools.yang.binding.Identifiable;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class FlowConfigMapping {
-
-    private final static Logger LOG = LoggerFactory.getLogger(FlowConfigMapping.class);
-
-    /* nodes/node/flow  -> 0 / 1 / 2  */
-    private static final int FLOW_KEY_IDENTIFIER_DEEP = 2;
-
-    public static Flow toConfigurationFlow(final FlowConfig sourceCfg) {
-        final FlowAdded source = MDFlowMapping.flowAdded(sourceCfg.getFlow());
-        final FlowBuilder flowBuilder = new FlowBuilder();
-        flowBuilder.setInstructions(source.getInstructions());
-        flowBuilder.setCookie(source.getCookie());
-        flowBuilder.setHardTimeout(source.getHardTimeout());
-        flowBuilder.setIdleTimeout(source.getIdleTimeout());
-        flowBuilder.setMatch(source.getMatch());
-        flowBuilder.setNode(source.getNode());
-
-        FlowKey flowKey =
-                new FlowKey(Long.valueOf(sourceCfg.getName()), flowBuilder.getNode());
-        flowBuilder.setKey(flowKey);
-        return flowBuilder.build();
-    }
-
-    public static FlowConfig toFlowConfig(final Flow sourceCfg) {
-        try {
-            final FlowConfig flowConfig = new FlowConfig();
-            flowConfig.setName(String.valueOf(sourceCfg.getId()));
-            flowConfig.setNode(NodeMapping.toADNode(sourceCfg.getNode()));
-            return flowConfig;
-        } catch (Exception e) {
-            String errMsg = MessageFormat.format("Convert from Flow {} to FlowConfig fail", sourceCfg);
-            LOG.error(errMsg, e);
-            throw new RuntimeException(errMsg, e);
-        }
-    }
-
-    public static FlowConfig toFlowConfig(final InstanceIdentifier<? extends Object> identifier) {
-        try {
-            PathArgument pathArg = FlowConfigMapping.getSecondPathArgumentFromPath(identifier);
-            if (pathArg != null) {
-                final FlowConfig flowConfig = new FlowConfig();
-                FlowKey key = ((IdentifiableItem<Flow, FlowKey>) pathArg).getKey();
-                flowConfig.setName(String.valueOf(key.getId()));
-                flowConfig.setNode(NodeMapping.toADNode(key.getNode()));
-                return flowConfig;
-            }
-            return null;
-        } catch (Exception e) {
-            String errMsg = MessageFormat.format("Convert from InstanceIdentifier {} to FlowConfig fail", identifier);
-            LOG.error(errMsg, e);
-            throw new RuntimeException(errMsg, e);
-        }
-    }
-
-    public static boolean isFlowPath(final InstanceIdentifier<? extends Object> path) {
-        PathArgument pathArg = FlowConfigMapping.getSecondPathArgumentFromPath(path);
-        if (pathArg == null) {
-            return false;
-        }
-        if (pathArg instanceof IdentifiableItem<?,?>) {
-            final Identifiable<?> key = ((IdentifiableItem<?, ? extends Identifiable<?>>) pathArg).getKey();
-            if ((key instanceof FlowKey)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private static PathArgument getSecondPathArgumentFromPath(final InstanceIdentifier<? extends Object> path) {
-        if (path != null && path.getPathArguments() != null) {
-            Iterator<PathArgument> iterator = path.getPathArguments().iterator();
-            int deep = 0;
-            while (iterator.hasNext()) {
-                PathArgument pathArg = iterator.next();
-                if (deep == FlowConfigMapping.FLOW_KEY_IDENTIFIER_DEEP) {
-                    return pathArg;
-                }
-                deep++;
-            }
-        }
-        return null;
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowManagementReader.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowManagementReader.java
deleted file mode 100644 (file)
index cb61c8a..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.frm.compatibility;
-
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-
-public interface FlowManagementReader {
-
-    Flows readAllFlows();
-
-    Flow readFlow(FlowKey key);
-
-}
diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/SampleConsumer.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/SampleConsumer.java
deleted file mode 100644 (file)
index a91cef6..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.frm.compatibility;
-
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-public class SampleConsumer {
-
-    ConsumerContext context;
-
-    void addFlowExample() {
-
-        DataBrokerService dataService = context.getSALService(DataBrokerService.class);
-
-        DataModificationTransaction transaction = dataService.beginTransaction();
-        Flow flow = createSampleFlow("foo", null);
-        InstanceIdentifier<Flow> path = InstanceIdentifier.builder(Flows.class).child(Flow.class, flow.getKey())
-                .toInstance();
-        transaction.putConfigurationData(path, flow);
-
-        transaction.commit();
-
-        dataService.readConfigurationData(path);
-    }
-
-    Flow createSampleFlow(String name, NodeRef node) {
-        FlowBuilder ret = new FlowBuilder();
-        FlowKey key = new FlowKey(Long.parseLong(name), node);
-        ret.setKey(key);
-        return ret.build();
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/pom.xml b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/pom.xml
deleted file mode 100644 (file)
index 62dc2ff..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>org.opendaylight.controller</groupId>
-    <artifactId>compatibility-parent</artifactId>
-    <version>1.1-SNAPSHOT</version>
-  </parent>
-  <artifactId>inventory-topology-compatibility</artifactId>
-  <packaging>bundle</packaging>
-
-  <dependencies>
-    <dependency>
-      <groupId>com.google.guava</groupId>
-      <artifactId>guava</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>forwardingrulesmanager</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-binding-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-binding-util</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-common-util</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-compatibility</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>switchmanager</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>topologymanager</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.model</groupId>
-      <artifactId>model-flow-management</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.model</groupId>
-      <artifactId>model-topology</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-api</artifactId>
-    </dependency>
-    <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>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Bundle-Name>Forwarding Rules Manager Adapter
-                            for MD-SAL</Bundle-Name>
-          </instructions>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-  <scm>
-    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
-    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
-    <tag>HEAD</tag>
-    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
-  </scm>
-</project>
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/inventory/InventoryReader.java b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/inventory/InventoryReader.java
deleted file mode 100644 (file)
index b37b501..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.compatibility.inventory;
-
-import java.util.ArrayList;
-import java.util.Set;
-
-import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
-import org.opendaylight.controller.sal.compatibility.InventoryMapping;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class InventoryReader implements RuntimeDataProvider {
-    private static final Logger LOG = LoggerFactory.getLogger(InventoryReader.class);
-    private ISwitchManager switchManager;
-
-    public ISwitchManager getSwitchManager() {
-        return switchManager;
-    }
-
-    public void setSwitchManager(final ISwitchManager switchManager) {
-        this.switchManager = switchManager;
-    }
-
-    @Override
-    public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
-        // Topology and Inventory are operational only
-        return null;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
-        final Class<? extends DataObject> type = path.getTargetType();
-        if (Nodes.class.equals(type)) {
-            return readNodes(((InstanceIdentifier<Nodes>) path));
-        }
-        if (Node.class.equals(type)) {
-            return readNode(((InstanceIdentifier<Node>) path));
-        }
-        if (NodeConnector.class.equals(type)) {
-            return readNodeConnector(((InstanceIdentifier<NodeConnector>) path));
-        }
-
-        LOG.debug("Unsupported type {}", type);
-        return null;
-    }
-
-    private NodeConnector readNodeConnector(final InstanceIdentifier<NodeConnector> identifier) {
-        return constructNodeConnector(InventoryMapping.toAdNodeConnector(identifier));
-    }
-
-    private Node readNode(final InstanceIdentifier<Node> identifier) {
-        return constructNode(InventoryMapping.toAdNode(identifier));
-    }
-
-    private Node constructNode(final org.opendaylight.controller.sal.core.Node node) {
-        final Set<org.opendaylight.controller.sal.core.NodeConnector> connectors = getSwitchManager().getNodeConnectors(node);
-        final ArrayList<NodeConnector> tpList = new ArrayList<NodeConnector>(connectors.size());
-        for (final org.opendaylight.controller.sal.core.NodeConnector connector : connectors) {
-            tpList.add(constructNodeConnector(connector));
-        }
-
-        return new NodeBuilder()
-        .setKey(InventoryMapping.toNodeKey(node))
-        .setNodeConnector(tpList)
-        .build();
-    }
-
-    private Nodes readNodes(final InstanceIdentifier<Nodes> identifier) {
-        final Set<org.opendaylight.controller.sal.core.Node> nodes = getSwitchManager().getNodes();
-        final ArrayList<Node> nodeList = new ArrayList<Node>(nodes.size());
-        for (final org.opendaylight.controller.sal.core.Node node : nodes) {
-            nodeList.add(constructNode(node));
-        }
-
-        return new NodesBuilder().setNode(nodeList).build();
-    }
-
-    private static NodeConnector constructNodeConnector(final org.opendaylight.controller.sal.core.NodeConnector connector) {
-        return new NodeConnectorBuilder().setKey(InventoryMapping.toNodeConnectorKey(connector)).build();
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/CompatibleSwitchManager.java b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/CompatibleSwitchManager.java
deleted file mode 100644 (file)
index 82c5b7b..0000000
+++ /dev/null
@@ -1,347 +0,0 @@
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.compatibility.switchmanager;
-
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.compatibility.NodeMapping;
-import org.opendaylight.controller.sal.core.Bandwidth;
-import org.opendaylight.controller.sal.core.ConstructionException;
-import org.opendaylight.controller.sal.core.Description;
-import org.opendaylight.controller.sal.core.ForwardingMode;
-import org.opendaylight.controller.sal.core.MacAddress;
-import org.opendaylight.controller.sal.core.NodeConnector;
-import org.opendaylight.controller.sal.core.Property;
-import org.opendaylight.controller.sal.core.Tier;
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
-import org.opendaylight.controller.switchmanager.Subnet;
-import org.opendaylight.controller.switchmanager.Switch;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class CompatibleSwitchManager extends ConfigurableSwitchManager implements ISwitchManager {
-    private static final  Logger LOG = LoggerFactory.getLogger(CompatibleSwitchManager.class);
-
-    private DataBrokerService _dataService;
-
-    public DataBrokerService getDataService() {
-        return this._dataService;
-    }
-
-    public void setDataService(final DataBrokerService dataService) {
-        this._dataService = dataService;
-    }
-
-    @Override
-    public Status addNodeConnectorProp(final NodeConnector nodeConnector, final Property prop) {
-        final DataModificationTransaction it = getDataService().beginTransaction();
-        final NodeConnectorRef path = NodeMapping.toNodeConnectorRef(nodeConnector);
-        return null;
-    }
-
-    @Override
-    public Property createProperty(final String propName, final String propValue) {
-        try {
-            if (propName.equalsIgnoreCase(Description.propertyName)) {
-                return new Description(propValue);
-            } else if (propName.equalsIgnoreCase(Tier.TierPropName)) {
-                return new Tier(Integer.parseInt(propValue));
-            } else if (propName.equalsIgnoreCase(Bandwidth.BandwidthPropName)) {
-                return new Bandwidth(Long.parseLong(propValue));
-            } else if (propName.equalsIgnoreCase(ForwardingMode.name)) {
-                return new ForwardingMode(Integer.parseInt(propValue));
-            } else if (propName.equalsIgnoreCase(MacAddress.name)) {
-                return new MacAddress(propValue);
-            } else {
-                LOG.debug("Not able to create {} property", propName);
-            }
-        } catch (Exception e) {
-            LOG.debug("createProperty caught exception {}", e.getMessage());
-        }
-
-        return null;
-    }
-
-    @Override
-    public boolean doesNodeConnectorExist(final NodeConnector nc) {
-        return (getDataService().readOperationalData(NodeMapping.toNodeConnectorRef(nc).getValue()) != null);
-    }
-
-    @Override
-    public byte[] getControllerMAC() {
-        final Enumeration<NetworkInterface> nis;
-        try {
-            nis = NetworkInterface.getNetworkInterfaces();
-        } catch (SocketException e) {
-            LOG.error("Failed to acquire list of interfaces, cannot determine controller MAC", e);
-            return null;
-        }
-
-        while (nis.hasMoreElements()) {
-            final NetworkInterface ni = nis.nextElement();
-            try {
-                return ni.getHardwareAddress();
-            } catch (SocketException e) {
-                LOG.error("Failed to acquire controller MAC from interface {}", ni, e);
-            }
-        }
-
-        // This happens when running controller on windows VM, for example
-        // Try parsing the OS command output
-        LOG.warn("Failed to acquire controller MAC: No physical interface found");
-        return null;
-    }
-
-    @Override
-    public Map<String,Property> getControllerProperties() {
-        return Collections.<String, Property>emptyMap();
-    }
-
-    @Override
-    public Property getControllerProperty(final String propertyName) {
-        return null;
-    }
-
-    @Override
-    public List<Switch> getNetworkDevices() {
-        final InstanceIdentifier<Nodes> path = InstanceIdentifier.builder(Nodes.class).toInstance();
-        final Nodes data = ((Nodes) getDataService().readOperationalData(path));
-        final ArrayList<Switch> ret = new ArrayList<>();
-        for (final Node node : data.getNode()) {
-            try {
-                ret.add(toSwitch(node));
-            } catch (ConstructionException e) {
-                throw new IllegalStateException(String.format("Failed to create switch {}", node), e);
-            }
-        }
-        return ret;
-    }
-
-    @Override
-    public NodeConnector getNodeConnector(final org.opendaylight.controller.sal.core.Node node, final String nodeConnectorName) {
-        final NodeConnectorKey key = new NodeConnectorKey(new NodeConnectorId(nodeConnectorName));
-        try {
-            return new NodeConnector(NodeMapping.MD_SAL_TYPE, key, node);
-        } catch (ConstructionException e) {
-            throw new IllegalStateException(String.format("Failed to create node connector for {} {}", node, nodeConnectorName), e);
-        }
-    }
-
-    @Override
-    public Property getNodeConnectorProp(final NodeConnector nodeConnector, final String propName) {
-        return getNodeConnectorProps(nodeConnector).get(propName);
-    }
-
-    @Override
-    public Map<String,Property> getNodeConnectorProps(final NodeConnector nodeConnector) {
-        final NodeConnectorRef ref = NodeMapping.toNodeConnectorRef(nodeConnector);
-        return toAdProperties(readNodeConnector(ref.getValue()));
-    }
-
-    @Override
-    public Set<NodeConnector> getNodeConnectors(final org.opendaylight.controller.sal.core.Node node) {
-        final Node data = this.readNode(NodeMapping.toNodeRef(node).getValue());
-        final HashSet<NodeConnector> ret = new HashSet<>();
-        for (final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector nc : data.getNodeConnector()) {
-            try {
-                ret.add(new NodeConnector(NodeMapping.MD_SAL_TYPE, nc.getKey(), node));
-            } catch (ConstructionException e) {
-                throw new IllegalStateException(String.format("Failed to create node {} connector", node, nc.getKey()), e);
-            }
-        }
-        return ret;
-    }
-
-    @Override
-    public String getNodeDescription(final org.opendaylight.controller.sal.core.Node node) {
-        return ((Description) getNodeProps(node).get(Description.propertyName)).getValue();
-    }
-
-    @Override
-    public byte[] getNodeMAC(final org.opendaylight.controller.sal.core.Node node) {
-        return ((MacAddress) getNodeProps(node).get(MacAddress.name)).getMacAddress();
-    }
-
-    @Override
-    public Property getNodeProp(final org.opendaylight.controller.sal.core.Node node, final String propName) {
-        return getNodeProps(node).get(propName);
-    }
-
-    @Override
-    public Map<String,Property> getNodeProps(final org.opendaylight.controller.sal.core.Node node) {
-        final NodeRef ref = NodeMapping.toNodeRef(node);
-        return toAdProperties(((Node) getDataService().readOperationalData(ref.getValue())));
-    }
-
-    @Override
-    public Set<org.opendaylight.controller.sal.core.Node> getNodes() {
-        final InstanceIdentifier<Nodes> path = InstanceIdentifier.builder(Nodes.class).toInstance();
-        final Nodes data = ((Nodes) getDataService().readOperationalData(path));
-        final HashSet<org.opendaylight.controller.sal.core.Node> ret = new HashSet<>();
-        for (final Node node : data.getNode()) {
-            try {
-                ret.add(new org.opendaylight.controller.sal.core.Node(NodeMapping.MD_SAL_TYPE, node.getKey()));
-            } catch (ConstructionException e) {
-                throw new IllegalStateException(String.format("Failed to create node for {}", node), e);
-            }
-        }
-        return ret;
-    }
-
-    private static Switch toSwitch(final Node node) throws ConstructionException {
-        return new Switch(new org.opendaylight.controller.sal.core.Node(NodeMapping.MD_SAL_TYPE, node.getKey()));
-    }
-
-    @Override
-    public Set<NodeConnector> getPhysicalNodeConnectors(final org.opendaylight.controller.sal.core.Node node) {
-        final NodeRef ref = NodeMapping.toNodeRef(node);
-        final Node data = readNode(ref.getValue());
-        final HashSet<NodeConnector> ret = new HashSet<>();
-        for (final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector nc : data.getNodeConnector()) {
-            final FlowCapableNodeConnector flowConnector = nc.getAugmentation(FlowCapableNodeConnector.class);
-            try {
-                ret.add(new NodeConnector(NodeMapping.MD_SAL_TYPE, nc.getKey(), node));
-            } catch (ConstructionException e) {
-                throw new IllegalStateException(String.format("Failed to create connector for {} on node {}", nc.getKey(), node), e);
-            }
-        }
-        return ret;
-    }
-
-    private static Map<String,Property> toAdProperties(final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector connector) {
-        return Collections.emptyMap();
-    }
-
-    private static Map<String,Property> toAdProperties(final Node connector) {
-        return Collections.emptyMap();
-    }
-
-    private Node readNode(final InstanceIdentifier<? extends Object> ref) {
-        return (Node) getDataService().readOperationalData((ref));
-    }
-
-    private org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector readNodeConnector(final InstanceIdentifier<? extends Object> ref) {
-        return ((org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector) getDataService().readOperationalData(ref));
-    }
-
-    @Override
-    public List<NodeConnector> getSpanPorts(final org.opendaylight.controller.sal.core.Node node) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public Subnet getSubnetByNetworkAddress(final InetAddress networkAddress) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public Set<NodeConnector> getUpNodeConnectors(final org.opendaylight.controller.sal.core.Node node) {
-        final Node data = readNode(NodeMapping.toNodeRef(node).getValue());
-        final HashSet<NodeConnector> ret = new HashSet<>();
-        for (final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector nc : data.getNodeConnector()) {
-            final FlowCapableNodeConnector flowConn = nc.<FlowCapableNodeConnector>getAugmentation(FlowCapableNodeConnector.class);
-            if (flowConn != null && flowConn.getState() != null && !flowConn.getState().isLinkDown()) {
-                try {
-                    ret.add(new NodeConnector(NodeMapping.MD_SAL_TYPE, nc.getKey(), node));
-                } catch (ConstructionException e) {
-                    throw new IllegalStateException(String.format("Failed to create node connector for node {} connector {}", node, nc), e);
-                }
-            }
-        }
-        return ret;
-    }
-
-    @Override
-    public Boolean isNodeConnectorEnabled(final NodeConnector nodeConnector) {
-        final NodeConnectorRef ref = NodeMapping.toNodeConnectorRef(nodeConnector);
-        final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector data = readNodeConnector(ref.getValue());
-        return true;
-    }
-
-    @Override
-    public boolean isSpecial(final NodeConnector p) {
-        final NodeConnectorRef ref = NodeMapping.toNodeConnectorRef(p);
-        final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector data = readNodeConnector(ref.getValue());
-        return true;
-    }
-
-    @Override
-    public Status removeControllerProperty(final String propertyName) {
-        return null;
-    }
-
-    @Override
-    public Status removeNodeAllProps(final org.opendaylight.controller.sal.core.Node node) {
-        return null;
-    }
-
-    @Override
-    public Status removeNodeConnectorAllProps(final NodeConnector nodeConnector) {
-        return null;
-    }
-
-    @Override
-    public Status removeNodeConnectorProp(final NodeConnector nc, final String propName) {
-        return null;
-    }
-
-    @Override
-    public Status removeNodeProp(final org.opendaylight.controller.sal.core.Node node, final String propName) {
-        return null;
-    }
-
-    @Override
-    public Status removePortsFromSubnet(final String name, final List<String> nodeConnectors) {
-        return null;
-    }
-
-    @Override
-    public Status removeSubnet(final String name) {
-        return null;
-    }
-
-    @Override
-    public Status setControllerProperty(final Property property) {
-        return null;
-    }
-
-    @Override
-    public void setNodeProp(final org.opendaylight.controller.sal.core.Node node, final Property prop) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public Status addPortsToSubnet(final String name, final List<String> nodeConnectors) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public Set<Switch> getConfiguredNotConnectedSwitches() {
-        return null;
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/ConfigurableSwitchManager.java b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/ConfigurableSwitchManager.java
deleted file mode 100644 (file)
index 63f682a..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.compatibility.switchmanager;
-
-import java.util.List;
-
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
-import org.opendaylight.controller.switchmanager.SpanConfig;
-import org.opendaylight.controller.switchmanager.SubnetConfig;
-import org.opendaylight.controller.switchmanager.SwitchConfig;
-
-/**
- * These methods should be backed by config subsystem.
- */
-public abstract class ConfigurableSwitchManager implements ISwitchManager {
-    @Override
-    public Status saveSwitchConfig() {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public Status removeSpanConfig(final SpanConfig cfgObject) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public Status addSubnet(final SubnetConfig configObject) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final Status addSpanConfig(final SpanConfig configObject) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final List<SpanConfig> getSpanConfigList() {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final void updateSwitchConfig(final SwitchConfig cfgObject) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final Status updateNodeConfig(final SwitchConfig switchConfig) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final SubnetConfig getSubnetConfig(final String subnet) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final Status removeNodeConfig(final String nodeId) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final Status removeSubnet(final SubnetConfig configObject) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final List<SubnetConfig> getSubnetsConfigList() {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final SwitchConfig getSwitchConfig(final String nodeId) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public Status modifySubnet(final SubnetConfig configObject) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyMapping.java b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyMapping.java
deleted file mode 100644 (file)
index 8e50bd8..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.compatibility.topology;
-
-import java.util.Iterator;
-
-import org.opendaylight.controller.sal.compatibility.InventoryMapping;
-import org.opendaylight.controller.sal.core.ConstructionException;
-import org.opendaylight.controller.sal.core.Edge;
-import org.opendaylight.controller.sal.core.NodeConnector;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.LinkId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-
-import com.google.common.base.Splitter;
-
-public class TopologyMapping {
-    private static final String HEAD_TAIL_STRING = "::::";
-    private static final Splitter HEAD_TAIL_SPLITTER = Splitter.on(HEAD_TAIL_STRING);
-
-    public TopologyMapping(final TopologyKey path, final InstanceIdentifier<Topology> key) {
-        // No-op for now. Multi-instance will require fixing InventoryMapping first.
-    }
-
-    public Edge toAdTopologyEdge(final InstanceIdentifier<Link> identifier) throws ConstructionException {
-        @SuppressWarnings("unchecked")
-        final LinkKey linkKey = ((KeyedInstanceIdentifier<Link, LinkKey>)identifier).getKey();
-
-        final Iterator<String> it = HEAD_TAIL_SPLITTER.split(linkKey.getLinkId().getValue()).iterator();
-        final NodeConnector tail = InventoryMapping.nodeConnectorFromId(it.next());
-        final NodeConnector head = InventoryMapping.nodeConnectorFromId(it.next());
-        return new Edge(tail, head);
-    }
-
-    public NodeConnector toAdTopologyNodeConnector(final InstanceIdentifier<TerminationPoint> identifier) {
-        @SuppressWarnings("unchecked")
-        final TerminationPointKey tpKey = ((KeyedInstanceIdentifier<TerminationPoint, TerminationPointKey>)identifier).getKey();
-
-        return InventoryMapping.nodeConnectorFromId(tpKey.getTpId().getValue());
-    }
-
-    public org.opendaylight.controller.sal.core.Node toAdTopologyNode(final InstanceIdentifier<Node> identifier) {
-        @SuppressWarnings("unchecked")
-        final NodeKey nodeKey = ((KeyedInstanceIdentifier<Node, NodeKey>)identifier).getKey();
-
-        return InventoryMapping.nodeFromNodeId(nodeKey.getNodeId().getValue());
-    }
-
-    public NodeKey toTopologyNodeKey(final org.opendaylight.controller.sal.core.Node node) {
-        return new NodeKey(new NodeId(InventoryMapping.toNodeId(node)));
-    }
-
-    public TerminationPointKey toTopologyTerminationPointKey(final NodeConnector nc) {
-        return new TerminationPointKey(new TpId(InventoryMapping.toNodeConnectorId(nc)));
-    }
-
-    public LinkKey toTopologyLinkKey(final Edge edge) {
-        final TerminationPointKey sourceTp = toTopologyTerminationPointKey(edge.getTailNodeConnector());
-        final TerminationPointKey destTp = toTopologyTerminationPointKey(edge.getHeadNodeConnector());
-
-        final StringBuilder sb = new StringBuilder();
-        sb.append(sourceTp.getTpId().toString());
-        sb.append(HEAD_TAIL_STRING);
-        sb.append(destTp.getTpId().toString());
-        return new LinkKey(new LinkId(sb.toString()));
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyReader.java b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyReader.java
deleted file mode 100644 (file)
index a4ac6f9..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.compatibility.topology;
-
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.Set;
-
-import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
-import org.opendaylight.controller.sal.core.ConstructionException;
-import org.opendaylight.controller.sal.core.Edge;
-import org.opendaylight.controller.sal.core.NodeConnector;
-import org.opendaylight.controller.sal.core.Property;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
-import org.opendaylight.controller.topologymanager.ITopologyManager;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.DestinationBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.SourceBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class TopologyReader implements RuntimeDataProvider {
-    private static final Logger LOG = LoggerFactory.getLogger(TopologyReader.class);
-    private final InstanceIdentifier<Topology> topologyPath;
-    private final TopologyKey topologyKey;
-    private final TopologyMapping mapping;
-    private ITopologyManager topologyManager;
-    private ISwitchManager switchManager;
-
-    public ISwitchManager getSwitchManager() {
-        return this.switchManager;
-    }
-
-    public void setSwitchManager(final ISwitchManager switchManager) {
-        this.switchManager = switchManager;
-    }
-
-    public ITopologyManager getTopologyManager() {
-        return this.topologyManager;
-    }
-
-    public void setTopologyManager(final ITopologyManager topologyManager) {
-        this.topologyManager = topologyManager;
-    }
-
-    public TopologyKey getTopologyKey() {
-        return this.topologyKey;
-    }
-
-    public TopologyMapping getMapping() {
-        return this.mapping;
-    }
-
-    public TopologyReader() {
-        this.topologyKey = new TopologyKey(new TopologyId("compatibility:ad-sal"));
-        this.topologyPath = InstanceIdentifier.builder(NetworkTopology.class)
-                .child(Topology.class, topologyKey)
-                .toInstance();
-        this.mapping = new TopologyMapping(topologyKey, topologyPath);
-    }
-
-    @Override
-    public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
-        // Topology and Inventory are operational only
-        return null;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
-        if (!topologyPath.contains(path)) {
-            return null;
-        }
-
-        final Class<? extends DataObject> type = path.getTargetType();
-        if (Link.class.equals(type)) {
-            return readLink((InstanceIdentifier<Link>) path);
-        }
-        if (Node.class.equals(type)) {
-            return readNode((InstanceIdentifier<Node>) path);
-        }
-        if (TerminationPoint.class.equals(type)) {
-            return readTerminationPoint((InstanceIdentifier<TerminationPoint>) path);
-
-        }
-        if (Topology.class.equals(type)) {
-            return readTopology((InstanceIdentifier<Topology>) path);
-        }
-
-        LOG.debug("Unsupported type {}", type);
-        return null;
-    }
-
-    private Link readLink(final InstanceIdentifier<Link> identifier) {
-        final Edge edge;
-        try {
-            edge = this.mapping.toAdTopologyEdge(identifier);
-        } catch (ConstructionException e) {
-            throw new IllegalStateException(String.format("Failed to construct edge for link %s", identifier), e);
-        }
-
-        final Map<Edge,Set<Property>> edges;
-        if (topologyManager != null) {
-            edges = topologyManager.getEdges();
-        } else {
-            edges = null;
-        }
-
-        final Set<Property> properties;
-        if (edges != null) {
-            properties = edges.get(edge);
-        } else {
-            properties = null;
-        }
-
-        return constructLink(edge);
-    }
-
-    private TerminationPoint readTerminationPoint(final InstanceIdentifier<TerminationPoint> identifier) {
-        return constructTerminationPoint(mapping.toAdTopologyNodeConnector(identifier));
-    }
-
-    private Node readNode(final InstanceIdentifier<Node> identifier) {
-        return constructNode(mapping.toAdTopologyNode(identifier));
-    }
-
-    private Topology readTopology(final InstanceIdentifier<Topology> identifier) {
-        final Set<org.opendaylight.controller.sal.core.Node> nodes = getSwitchManager().getNodes();
-        final ArrayList<Node> nodeList = new ArrayList<Node>(nodes.size());
-        for (final org.opendaylight.controller.sal.core.Node node : nodes) {
-            nodeList.add(constructNode(node));
-        }
-
-        final Map<Edge,Set<Property>> edges = getTopologyManager().getEdges();
-        final ArrayList<Link> linkList = new ArrayList<Link>(edges.size());
-        for (final Edge edge : edges.keySet()) {
-            linkList.add(constructLink(edge));
-        }
-
-        return new TopologyBuilder()
-        .setKey(topologyKey)
-        .setNode(nodeList)
-        .setLink(linkList)
-        .build();
-    }
-
-    private Link constructLink(final Edge edge) {
-        final NodeConnector sourceNc = edge.getTailNodeConnector();
-        final NodeConnector destNc = edge.getHeadNodeConnector();
-
-        final LinkBuilder it = new LinkBuilder().setKey(mapping.toTopologyLinkKey(edge));
-
-        it.setSource(new SourceBuilder()
-        .setSourceNode(mapping.toTopologyNodeKey(sourceNc.getNode()).getNodeId())
-        .setSourceTp(mapping.toTopologyTerminationPointKey(sourceNc).getTpId())
-        .build());
-
-        it.setDestination(new DestinationBuilder()
-        .setDestNode(mapping.toTopologyNodeKey(destNc.getNode()).getNodeId())
-        .setDestTp(mapping.toTopologyTerminationPointKey(destNc).getTpId())
-        .build());
-
-        return it.build();
-    }
-
-    private Node constructNode(final org.opendaylight.controller.sal.core.Node node) {
-        final Set<NodeConnector> connectors = getSwitchManager().getNodeConnectors(node);
-        final ArrayList<TerminationPoint> tpList = new ArrayList<TerminationPoint>(connectors.size());
-        for (final NodeConnector connector : connectors) {
-            tpList.add(constructTerminationPoint(connector));
-        }
-
-        return new NodeBuilder()
-        .setKey(mapping.toTopologyNodeKey(node))
-        .setTerminationPoint(tpList)
-        .build();
-    }
-
-    private TerminationPoint constructTerminationPoint(final NodeConnector connector) {
-        return new TerminationPointBuilder().setKey(mapping.toTopologyTerminationPointKey(connector)).build();
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/AdSalTopologyMapping.java b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/AdSalTopologyMapping.java
deleted file mode 100644 (file)
index a7a7a9a..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.compatibility.topologymanager;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.opendaylight.controller.sal.compatibility.NodeMapping;
-import org.opendaylight.controller.sal.core.ConstructionException;
-import org.opendaylight.controller.sal.core.Edge;
-import org.opendaylight.controller.sal.core.NodeConnector;
-import org.opendaylight.controller.sal.core.Property;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.Destination;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.Source;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-public class AdSalTopologyMapping {
-    private final InstanceIdentifier<Topology> topologyPath;
-
-    public AdSalTopologyMapping(final TopologyKey topology) {
-        this.topologyPath = InstanceIdentifier.builder(NetworkTopology.class)
-                .child(Topology.class, topology).toInstance();
-    }
-
-    public InstanceIdentifier<Topology> getTopologyPath() {
-        return topologyPath;
-    }
-
-    public InstanceIdentifier<TerminationPoint> toTerminationPoint(final NodeConnector connector) {
-        return getTopologyPath().builder()
-                .child(Node.class)
-                .child(TerminationPoint.class, toTerminationPointKey(connector))
-                .toInstance();
-    }
-
-    public Map<Edge,Set<Property>> toEdgePropertiesMap(final Iterable<Link> links) {
-        final HashMap<Edge,Set<Property>> ret = new HashMap<>();
-        for (final Link link : links) {
-            try {
-                ret.put(toEdge(link), toProperties(link));
-            } catch (ConstructionException e) {
-                throw new IllegalStateException(String.format("Failed to create edge properties for {}", link), e);
-            }
-        }
-        return ret;
-    }
-
-    public static Set<Edge> toEdges(final Iterable<Link> links) throws ConstructionException {
-        final HashSet<Edge> ret = new HashSet<Edge>();
-        for (final Link link : links) {
-            ret.add(toEdge(link));
-        }
-        return ret;
-    }
-
-    public static Edge toEdge(final Link link) throws ConstructionException {
-        final NodeConnector tail = toNodeConnector(link.getSource());
-        final NodeConnector head = toNodeConnector(link.getDestination());
-        return new Edge(tail, head);
-    }
-
-    public static org.opendaylight.controller.sal.core.Node toAdNode(final Node node) throws ConstructionException {
-        return toAdNode(node.getNodeId());
-    }
-
-    public static org.opendaylight.controller.sal.core.Node toAdNode(final NodeId node) throws ConstructionException {
-        final NodeKey key = new NodeKey(
-                new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId(node));
-        return new org.opendaylight.controller.sal.core.Node(NodeMapping.MD_SAL_TYPE, key);
-    }
-
-    public static NodeConnector toNodeConnector(final Source ref) throws ConstructionException {
-        final org.opendaylight.controller.sal.core.Node adNode = toAdNode(ref.getSourceNode());
-        final NodeConnectorKey key = new NodeConnectorKey(new NodeConnectorId(ref.getSourceTp()));
-        return new NodeConnector(NodeMapping.MD_SAL_TYPE, key, adNode);
-    }
-
-    public static NodeConnector toNodeConnector(final Destination ref) throws ConstructionException {
-        final org.opendaylight.controller.sal.core.Node adNode = toAdNode(ref.getDestNode());
-        final NodeConnectorKey key = new NodeConnectorKey(new NodeConnectorId(ref.getDestTp()));
-        return new NodeConnector(NodeMapping.MD_SAL_TYPE, key, adNode);
-    }
-
-    public TerminationPointKey toTerminationPointKey(final NodeConnector connector) {
-        return null;
-    }
-
-    public Set<Property> toProperties(final Link link) {
-        return null;
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/CompatibleTopologyManager.java b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/CompatibleTopologyManager.java
deleted file mode 100644 (file)
index 11320a1..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.compatibility.topologymanager;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader;
-import org.opendaylight.controller.sal.core.ConstructionException;
-import org.opendaylight.controller.sal.core.Edge;
-import org.opendaylight.controller.sal.core.Host;
-import org.opendaylight.controller.sal.core.NodeConnector;
-import org.opendaylight.controller.sal.core.Property;
-import org.opendaylight.controller.sal.core.UpdateType;
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.topologymanager.ITopologyManager;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.FluentIterable;
-
-@SuppressWarnings("all")
-public class CompatibleTopologyManager extends ConfigurableLinkManager implements ITopologyManager {
-    private AdSalTopologyMapping topologyMapping;
-    private TypeSafeDataReader dataReader;
-
-    public TypeSafeDataReader getDataReader() {
-        return dataReader;
-    }
-
-    public void setDataReader(final TypeSafeDataReader dataReader) {
-        this.dataReader = dataReader;
-    }
-
-    public AdSalTopologyMapping getTopologyMapping() {
-        return topologyMapping;
-    }
-
-    public void setTopologyMapping(final AdSalTopologyMapping topologyMapping) {
-        this.topologyMapping = topologyMapping;
-    }
-
-    @Override
-    public Map<Edge,Set<Property>> getEdges() {
-        final Topology topology = getDataReader().readOperationalData(topologyMapping.getTopologyPath());
-        return this.topologyMapping.toEdgePropertiesMap(topology.getLink());
-    }
-
-    @Override
-    public Map<org.opendaylight.controller.sal.core.Node, Set<Edge>> getNodeEdges() {
-        final Topology topology = getDataReader().readOperationalData(topologyMapping.getTopologyPath());
-        final HashMap<org.opendaylight.controller.sal.core.Node, Set<Edge>> ret = new HashMap<>();
-        for (final Node node : topology.getNode()) {
-            try {
-                ret.put(topologyMapping.toAdNode(node), topologyMapping.toEdges(
-                        FluentIterable.from(topology.getLink()).filter(new Predicate<Link>() {
-                            @Override
-                            public boolean apply(final Link input) {
-                                final NodeId nodeId = node.getNodeId();
-                                if (nodeId.equals(input.getSource().getSourceNode())) {
-                                    return true;
-                                }
-                                if (nodeId.equals(input.getDestination().getDestNode())) {
-                                    return true;
-                                }
-
-                                return false;
-                            }
-                        })));
-            } catch (ConstructionException e) {
-                throw new IllegalStateException(String.format("Failed to construct node for {}", node), e);
-            }
-        }
-        return ret;
-    }
-
-    /**
-     * Returns true if point is connected to link
-     */
-    private boolean isInternal(final TerminationPoint point) {
-        final Topology topology = getDataReader().readConfigurationData(topologyMapping.getTopologyPath());
-        final TpId tpId = point.getKey().getTpId();
-        return FluentIterable.from(topology.getLink()).anyMatch(new Predicate<Link>() {
-            @Override
-            public boolean apply(final Link input) {
-                if (tpId.equals(input.getSource().getSourceTp())) {
-                    return true;
-                }
-                if (tpId.equals(input.getDestination().getDestTp())) {
-                    return true;
-                }
-                return false;
-            }
-        });
-    }
-
-    @Override
-    public Set<NodeConnector> getNodeConnectorWithHost() {
-        return null;
-    }
-
-    @Override
-    public Host getHostAttachedToNodeConnector(final NodeConnector p) {
-        final InstanceIdentifier<TerminationPoint> tpPath = topologyMapping.toTerminationPoint(p);
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public List<Host> getHostsAttachedToNodeConnector(final NodeConnector p) {
-        final Topology topology = getDataReader().readOperationalData(topologyMapping.getTopologyPath());
-        throw new UnsupportedOperationException("Hosts not mapped yet");
-    }
-
-    @Override
-    public Map<org.opendaylight.controller.sal.core.Node, Set<NodeConnector>> getNodesWithNodeConnectorHost() {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public boolean isInternal(final NodeConnector p) {
-        final TerminationPoint connector = getDataReader()
-                .readConfigurationData(topologyMapping.toTerminationPoint(p));
-        return this.isInternal(connector);
-    }
-
-    @Override
-    public void updateHostLink(final NodeConnector p, final Host h, final UpdateType t, final Set<Property> props) {
-        // Update app defined topology
-    }
-
-    @Override
-    public Status saveConfig() {
-        // FIXME: commit configuration
-        return null;
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/ConfigurableLinkManager.java b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/ConfigurableLinkManager.java
deleted file mode 100644 (file)
index 2d85f76..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.compatibility.topologymanager;
-
-import java.util.concurrent.ConcurrentMap;
-
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.topologymanager.ITopologyManager;
-import org.opendaylight.controller.topologymanager.TopologyUserLinkConfig;
-
-public abstract class ConfigurableLinkManager implements ITopologyManager {
-    @Override
-    public final Status addUserLink(final TopologyUserLinkConfig link) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final Status deleteUserLink(final String linkName) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final ConcurrentMap<String,TopologyUserLinkConfig> getUserLinks() {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-}
index 688e6ac09b25b29d8160ad05b10ef078430e1d37..b9e9d19b48dce4eed7f5e42cc335588306ad1692 100644 (file)
@@ -12,8 +12,6 @@
 
   <modules>
     <module>sal-compatibility</module>
-    <module>inventory-topology-compatibility</module>
-    <module>flow-management-compatibility</module>
   </modules>
 
   <dependencies>
index 02964c6d5531553d23abaa0cce39dfae1db30881..be087abdb41099b9a5d8505ed20f7ac59624f531 100644 (file)
@@ -7,11 +7,13 @@
  */
 package org.opendaylight.controller.sal.compatibility;
 
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
 import java.math.BigInteger;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
-
 import org.opendaylight.controller.sal.common.util.Arguments;
 import org.opendaylight.controller.sal.core.AdvertisedBandwidth;
 import org.opendaylight.controller.sal.core.Bandwidth;
@@ -62,16 +64,14 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-
 public final class NodeMapping {
 
     private static final Logger LOG = LoggerFactory
             .getLogger(NodeMapping.class);
 
-    /** openflow id prefix */
+    /**
+     * openflow id prefix
+     */
     public static final String OPENFLOW_ID_PREFIX = "openflow:";
 
     public final static String MD_SAL_TYPE = "MD_SAL_DEPRECATED";
@@ -90,8 +90,14 @@ public final class NodeMapping {
     }
 
     public static org.opendaylight.controller.sal.core.Node toADNode(final NodeId id) throws ConstructionException {
-        Long aDNodeId = openflowFullNodeIdToLong(NodeMapping.toADNodeId(id));
-        return new org.opendaylight.controller.sal.core.Node(NodeIDType.OPENFLOW, aDNodeId);
+        String nodeId = NodeMapping.toADNodeId(id);
+        String nodeIdasNumber = nodeId.replaceFirst("^.*:", "");
+        if (isInteger(nodeIdasNumber)) {
+            Long aDNodeId = openflowFullNodeIdToLong(nodeIdasNumber);
+            return new org.opendaylight.controller.sal.core.Node(NodeIDType.OPENFLOW, aDNodeId);
+        } else {
+            return new org.opendaylight.controller.sal.core.Node(NodeIDType.PRODUCTION, nodeId);
+        }
     }
 
     /**
@@ -103,7 +109,7 @@ public final class NodeMapping {
         if (adNodeId == null) {
             return null;
         }
-        return new BigInteger(adNodeId.replaceFirst("^.*:", "")).longValue();
+        return new BigInteger(adNodeId).longValue();
     }
 
     public static NodeId toNodeId(final InstanceIdentifier<?> id) {
@@ -137,8 +143,8 @@ public final class NodeMapping {
     }
 
     /**
-     * @param ncid nodeConnector identifier, e.g.: OF:21 or CTRL
-     * @param node
+     * @param ncid   nodeConnector identifier, e.g.: OF:21 or CTRL
+     * @param aDNode
      * @return nodeConnector attached to given node
      * @throws ConstructionException
      */
@@ -155,7 +161,7 @@ public final class NodeMapping {
      * @return
      */
     private static NodeId toNodeId(org.opendaylight.controller.sal.core.Node aDNode) {
-        return new NodeId(aDNode.getType() + ":" +String.valueOf(aDNode.getID()));
+        return new NodeId(aDNode.getType() + ":" + String.valueOf(aDNode.getID()));
     }
 
     public static String toNodeConnectorType(final NodeConnectorId ncId, final NodeId nodeId) {
@@ -212,7 +218,7 @@ public final class NodeMapping {
     public static NodeRef toNodeRef(final org.opendaylight.controller.sal.core.Node node) {
         Preconditions.checkArgument(NodeIDType.OPENFLOW.equals(node.getType()));
         final Long nodeId = Arguments.<Long>checkInstanceOf(node.getID(), Long.class);
-        final NodeKey nodeKey = new NodeKey(new NodeId(OPENFLOW_ID_PREFIX+nodeId));
+        final NodeKey nodeKey = new NodeKey(new NodeId(OPENFLOW_ID_PREFIX + nodeId));
         final InstanceIdentifier<Node> nodePath = InstanceIdentifier.builder(Nodes.class).child(NODE_CLASS, nodeKey).toInstance();
         return new NodeRef(nodePath);
     }
@@ -257,7 +263,7 @@ public final class NodeMapping {
     }
 
     /**
-     * @param id
+     * @param nodeRef
      * @return node description in AD form, e.g.: OF|00:00:00:...:01
      */
     private static Description toADDescription(NodeRef nodeRef) {
@@ -463,4 +469,17 @@ public final class NodeMapping {
     public static Buffers toADBuffers(final Long buffers) {
         return new Buffers(buffers.intValue());
     }
+
+
+    private static final boolean isInteger(String value) {
+        if (value.isEmpty()) return false;
+        for (int i = 0; i < value.length(); i++) {
+            if (i == 0 && value.charAt(i) == '-') {
+                if (value.length() == 1) return false;
+                else continue;
+            }
+            if (Character.digit(value.charAt(i), 10) < 0) return false;
+        }
+        return true;
+    }
 }
index cef7ae7a427672b8276411b2e1ace77f66dc04fd..a776ef231292c1fa562cf19b7a1fe7571d7e8a06 100644 (file)
@@ -101,6 +101,16 @@ public class NodeMappingTest {
         } catch (ConstructionException e) {
             Assert.fail("should succeed to construct Node: "+e.getMessage());
         }
+
+        final String nodeUriPrefix = "opendaylight-inventory:nodes/node/";
+        nodeId = new NodeId(nodeUriPrefix + "iosv-2");
+        try {
+            observed = NodeMapping.toADNode(nodeId);
+            Assert.assertEquals("PR|opendaylight-inventory:nodes/node/iosv-2", observed.toString());
+        } catch (ConstructionException e) {
+            Assert.fail("should succeed to construct Node: "+e.getMessage());
+        }
+
     }
 
     /**
index ed5e19219353e3265a5b7f55ef58dccd5f6b7ad7..5a9b19021945b947e7601fbdaa82dd74676fbdc8 100644 (file)
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-binding-api</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.model</groupId>
-      <artifactId>model-flow-management</artifactId>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-flow-service</artifactId>
index f25b7d91bdb38b2f357ec5faa91283d2929e3128..35a77662b542cb18333723f174d762328057ff48 100644 (file)
                 <module>
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:distributed-datastore-provider">prefix:distributed-operational-datastore-provider</type>
                     <name>distributed-operational-store-module</name>
-                    <schema-service>
+                    <operational-schema-service>
                         <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
                         <name>yang-schema-service</name>
-                    </schema-service>
+                    </operational-schema-service>
                 </module>
 
                 <module>
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:distributed-datastore-provider">prefix:distributed-config-datastore-provider</type>
                     <name>distributed-config-store-module</name>
-                    <schema-service>
+                    <configschema-service>
                         <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
                         <name>yang-schema-service</name>
-                    </schema-service>
+                    </config-schema-service>
                 </module>
                 -->
 
index 02fbde8f1826648b12278311fb3defe1e72c1347..6c6760d789a086157bdb35a0a66d620db8057d3c 100644 (file)
     <!--InMemory DOM DataStore-->
     <module>sal-inmemory-datastore</module>
 
-    <!--sal-protocolbuffer-encoding-->
-    <module>sal-protocolbuffer-encoding</module>
+    <!--sal-protocolbuffer-encoding is now part of sal-clutering-commons-->
+    <module>sal-clustering-commons</module>
+
+    <!-- sal clustering configuration -->
+    <module>sal-clustering-config</module>
 
     <!-- sal-distributed-datastore -->
     <module>sal-distributed-datastore</module>
index 24bfa3de21f0d6d8af306fda1e73a8f4638af160..b5b034afb9cf8edc7635cfca5509c93cbeb457b5 100644 (file)
@@ -100,16 +100,26 @@ public abstract class AbstractReplicatedLogImpl implements ReplicatedLog {
 
     @Override
     public List<ReplicatedLogEntry> getFrom(long logEntryIndex) {
+        return getFrom(logEntryIndex, journal.size());
+    }
+
+    @Override
+    public List<ReplicatedLogEntry> getFrom(long logEntryIndex, int max) {
         int adjustedIndex = adjustedIndex(logEntryIndex);
         int size = journal.size();
         List<ReplicatedLogEntry> entries = new ArrayList<>(100);
         if (adjustedIndex >= 0 && adjustedIndex < size) {
             // physical index should be less than list size and >= 0
-            entries.addAll(journal.subList(adjustedIndex, size));
+            int maxIndex = adjustedIndex + max;
+            if(maxIndex > size){
+                maxIndex = size;
+            }
+            entries.addAll(journal.subList(adjustedIndex, maxIndex));
         }
         return entries;
     }
 
+
     @Override
     public long size() {
        return journal.size();
index c633337226769d14c281fc71537a71e1dd2e1586..6432fa4811beb64ef13f6869e6e252289c2163be 100644 (file)
@@ -33,7 +33,7 @@ public class DefaultConfigParamsImpl implements ConfigParams {
      * Since this is set to 100 milliseconds the Election timeout should be
      * at least 200 milliseconds
      */
-    protected static final FiniteDuration HEART_BEAT_INTERVAL =
+    public static final FiniteDuration HEART_BEAT_INTERVAL =
         new FiniteDuration(100, TimeUnit.MILLISECONDS);
 
 
@@ -51,7 +51,7 @@ public class DefaultConfigParamsImpl implements ConfigParams {
     @Override
     public FiniteDuration getElectionTimeOutInterval() {
         // returns 2 times the heart beat interval
-        return HEART_BEAT_INTERVAL.$times(2);
+        return getHeartBeatInterval().$times(2);
     }
 
     @Override
index caa0e507c1b0ec408745150863920f720c94a1cb..0a979d24eef2a26d60cb6168c18d84815037cf18 100644 (file)
@@ -148,6 +148,7 @@ public abstract class RaftActor extends UntypedPersistentActor {
                 replicatedLog.lastIndex(), replicatedLog.snapshotIndex,
                 replicatedLog.snapshotTerm, replicatedLog.size());
             currentBehavior = switchBehavior(RaftState.Follower);
+            onStateChanged();
         }
     }
 
@@ -206,7 +207,11 @@ public abstract class RaftActor extends UntypedPersistentActor {
 
             RaftState state =
                 currentBehavior.handleMessage(getSender(), message);
+            RaftActorBehavior oldBehavior = currentBehavior;
             currentBehavior = switchBehavior(state);
+            if(oldBehavior != currentBehavior){
+                onStateChanged();
+            }
         }
     }
 
@@ -271,9 +276,21 @@ public abstract class RaftActor extends UntypedPersistentActor {
         String peerAddress = context.getPeerAddress(leaderId);
         LOG.debug("getLeader leaderId = " + leaderId + " peerAddress = "
             + peerAddress);
+
+        if(peerAddress == null){
+            return null;
+        }
         return context.actorSelection(peerAddress);
     }
 
+    /**
+     *
+     * @return the current leader's id
+     */
+    protected String getLeaderId(){
+        return currentBehavior.getLeaderId();
+    }
+
     protected RaftState getRaftState() {
         return currentBehavior.state();
     }
@@ -375,7 +392,7 @@ public abstract class RaftActor extends UntypedPersistentActor {
             behavior = new Leader(context);
         }
 
-        onStateChanged();
+
 
         return behavior;
     }
index b7c8955aad982873ee02fff78f629b7f7bc1f1b5..e6e160bc02bf1fd72305325aefc91a1ac2a9fac0 100644 (file)
@@ -84,6 +84,11 @@ public interface ReplicatedLog {
      */
     List<ReplicatedLogEntry> getFrom(long index);
 
+    /**
+     *
+     * @param index the index of the log entry
+     */
+    List<ReplicatedLogEntry> getFrom(long index, int max);
 
     /**
      *
index 2a44e8b7a5c3adeecd1c534de0664d8deb290934..a50666233c31f30b2e94cbf4c49d53a95cca93f4 100644 (file)
@@ -310,7 +310,7 @@ public class Leader extends AbstractRaftActorBehavior {
                     // that has fallen too far behind with the log but yet is not
                     // eligible to receive a snapshot
                     entries =
-                        context.getReplicatedLog().getFrom(nextIndex);
+                        context.getReplicatedLog().getFrom(nextIndex, 1);
                 }
 
                 followerActor.tell(
index ae8e525233cbe96f74418ce0fa45d70a2266df34..913665861d6f694dbb01c51d96978c05d6e9c5ea 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.cluster.raft;
 
+import junit.framework.Assert;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -31,6 +32,12 @@ public class AbstractReplicatedLogImplTest {
     @Before
     public void setUp() {
         replicatedLogImpl = new MockAbstractReplicatedLogImpl();
+        // create a set of initial entries in the in-memory log
+        replicatedLogImpl.append(new MockReplicatedLogEntry(1, 0, new MockPayload("A")));
+        replicatedLogImpl.append(new MockReplicatedLogEntry(1, 1, new MockPayload("B")));
+        replicatedLogImpl.append(new MockReplicatedLogEntry(1, 2, new MockPayload("C")));
+        replicatedLogImpl.append(new MockReplicatedLogEntry(2, 3, new MockPayload("D")));
+
     }
 
     @After
@@ -43,11 +50,6 @@ public class AbstractReplicatedLogImplTest {
 
     @Test
     public void testIndexOperations() {
-        // create a set of initial entries in the in-memory log
-        replicatedLogImpl.append(new MockReplicatedLogEntry(1, 0, new MockPayload("A")));
-        replicatedLogImpl.append(new MockReplicatedLogEntry(1, 1, new MockPayload("B")));
-        replicatedLogImpl.append(new MockReplicatedLogEntry(1, 2, new MockPayload("C")));
-        replicatedLogImpl.append(new MockReplicatedLogEntry(2, 3, new MockPayload("D")));
 
         // check if the values returned are correct, with snapshotIndex = -1
         assertEquals("B", replicatedLogImpl.get(1).getData().toString());
@@ -112,6 +114,22 @@ public class AbstractReplicatedLogImplTest {
 
     }
 
+    @Test
+    public void testGetFromWithMax(){
+        List<ReplicatedLogEntry> from = replicatedLogImpl.getFrom(0, 1);
+        Assert.assertEquals(1, from.size());
+        Assert.assertEquals(1, from.get(0).getTerm());
+
+        from = replicatedLogImpl.getFrom(0, 20);
+        Assert.assertEquals(4, from.size());
+        Assert.assertEquals(2, from.get(3).getTerm());
+
+        from = replicatedLogImpl.getFrom(1, 2);
+        Assert.assertEquals(2, from.size());
+        Assert.assertEquals(1, from.get(1).getTerm());
+
+    }
+
     // create a snapshot for test
     public Map takeSnapshot(int numEntries) {
         Map map = new HashMap(numEntries);
index aa50fa7442b1f54ed026c5e2b95ff4c52270ea86..70671a6a21ab112b339a07b6ab37b4c56c176b47 100644 (file)
@@ -248,6 +248,23 @@ public class MockRaftActorContext implements RaftActorContext {
             return entries;
         }
 
+        @Override public List<ReplicatedLogEntry> getFrom(long index, int max) {
+            if(index >= log.size() || index < 0){
+                return Collections.EMPTY_LIST;
+            }
+            List<ReplicatedLogEntry> entries = new ArrayList<>();
+            int maxIndex = (int) index + max;
+            if(maxIndex > log.size()){
+                maxIndex = log.size();
+            }
+
+            for(int i=(int) index ; i < maxIndex ; i++) {
+                entries.add(get(i));
+            }
+            return entries;
+
+        }
+
         @Override public long size() {
             return log.size();
         }
index c76368370506af15ab4b7b567672514514e41690..d478b175550ba223a778fcf4121f36b9b41fbc1f 100644 (file)
@@ -6,6 +6,7 @@ import akka.testkit.JavaTestKit;
 import junit.framework.Assert;
 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;
@@ -80,12 +81,12 @@ public class CandidateTest extends AbstractRaftActorBehaviorTest {
     public void testThatAnElectionTimeoutIsTriggered(){
         new JavaTestKit(getSystem()) {{
 
-            new Within(duration("1 seconds")) {
+            new Within(DefaultConfigParamsImpl.HEART_BEAT_INTERVAL.$times(6)) {
                 protected void run() {
 
                     Candidate candidate = new Candidate(createActorContext(getTestActor()));
 
-                    final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"), "ElectionTimeout") {
+                    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) {
index c015d950c42055799bdd5826f0cca1aaf398f357..c5a81aa1c9225ea03fa548bf1950d5e73a7e3329 100644 (file)
@@ -5,6 +5,7 @@ import akka.actor.Props;
 import akka.testkit.JavaTestKit;
 import junit.framework.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.RaftState;
@@ -41,12 +42,12 @@ public class FollowerTest extends AbstractRaftActorBehaviorTest {
     public void testThatAnElectionTimeoutIsTriggered(){
         new JavaTestKit(getSystem()) {{
 
-            new Within(duration("1 seconds")) {
+            new Within(DefaultConfigParamsImpl.HEART_BEAT_INTERVAL.$times(6)) {
                 protected void run() {
 
                     Follower follower = new Follower(createActorContext(getTestActor()));
 
-                    final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"), "ElectionTimeout") {
+                    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) {
index 2d81b6022d35af1c70fba4adb269ffc2d8c93dce..e632e6336aaf959808a28f9ecc209432c504b4eb 100644 (file)
@@ -97,6 +97,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
     }
 
     protected Map<InstanceIdentifier<?>, DataObject> toBinding(
+            InstanceIdentifier<?> path,
             final Map<YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized) {
         Map<InstanceIdentifier<?>, DataObject> newMap = new HashMap<>();
 
@@ -107,6 +108,11 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
                 if (potential.isPresent()) {
                     Entry<InstanceIdentifier<? extends DataObject>, DataObject> binding = potential.get();
                     newMap.put(binding.getKey(), binding.getValue());
+                } else if (entry.getKey().getLastPathArgument() instanceof YangInstanceIdentifier.AugmentationIdentifier) {
+                    DataObject bindingDataObject = getCodec().toBinding(path, entry.getValue());
+                    if (bindingDataObject != null) {
+                        newMap.put(path, bindingDataObject);
+                    }
                 }
             } catch (DeserializationException e) {
                 LOG.warn("Failed to transform {}, omitting it", entry, e);
@@ -148,7 +154,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         }
     }
 
-    protected Set<InstanceIdentifier<?>> toBinding(
+    protected Set<InstanceIdentifier<?>> toBinding(InstanceIdentifier<?> path,
             final Set<YangInstanceIdentifier> normalized) {
         Set<InstanceIdentifier<?>> hashSet = new HashSet<>();
         for (YangInstanceIdentifier normalizedPath : normalized) {
@@ -157,6 +163,8 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
                 if (potential.isPresent()) {
                     InstanceIdentifier<? extends DataObject> binding = potential.get();
                     hashSet.add(binding);
+                } else if (normalizedPath.getLastPathArgument() instanceof YangInstanceIdentifier.AugmentationIdentifier) {
+                    hashSet.add(path);
                 }
             } catch (DeserializationException e) {
                 LOG.warn("Failed to transform {}, omitting it", normalizedPath, e);
@@ -219,7 +227,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         @Override
         public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
             if (createdCache == null) {
-                createdCache = Collections.unmodifiableMap(toBinding(domEvent.getCreatedData()));
+                createdCache = Collections.unmodifiableMap(toBinding(path, domEvent.getCreatedData()));
             }
             return createdCache;
         }
@@ -227,7 +235,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         @Override
         public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
             if (updatedCache == null) {
-                updatedCache = Collections.unmodifiableMap(toBinding(domEvent.getUpdatedData()));
+                updatedCache = Collections.unmodifiableMap(toBinding(path, domEvent.getUpdatedData()));
             }
             return updatedCache;
 
@@ -236,7 +244,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         @Override
         public Set<InstanceIdentifier<?>> getRemovedPaths() {
             if (removedCache == null) {
-                removedCache = Collections.unmodifiableSet(toBinding(domEvent.getRemovedPaths()));
+                removedCache = Collections.unmodifiableSet(toBinding(path, domEvent.getRemovedPaths()));
             }
             return removedCache;
         }
@@ -244,7 +252,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         @Override
         public Map<InstanceIdentifier<?>, DataObject> getOriginalData() {
             if (originalCache == null) {
-                originalCache = Collections.unmodifiableMap(toBinding(domEvent.getOriginalData()));
+                originalCache = Collections.unmodifiableMap(toBinding(path, domEvent.getOriginalData()));
             }
             return originalCache;
 
index c924b74a12bb0e7c6f080e98dffc09352faa16a7..237d9678f95f3a743dfbe19a033ca02845b81375 100644 (file)
@@ -39,7 +39,7 @@ import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
 import org.opendaylight.yangtools.concepts.Delegator;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
index 709b62fee25247c09ec980c188acd504693d4e3e..783e5c0cd4f459e94a2009c5a6783c6e8a54cb42 100644 (file)
@@ -22,7 +22,7 @@ import org.opendaylight.controller.sal.binding.api.rpc.RpcRoutingTable;
 import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper;
 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.RpcService;
index 1ea2eba87f932a565a7d537b8c41725c6ecfa8b8..15314d3bdcd077ec96f772123648512a024763f8 100644 (file)
@@ -11,7 +11,7 @@ import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataTransaction;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
index 05651bfabe5c521d66c25a219fb096b5d9ef0ecb..c390fe70491a9cfea76996e866008258b1979e26 100644 (file)
@@ -15,7 +15,7 @@ import org.opendaylight.controller.md.sal.binding.util.AbstractBindingSalProvide
 import org.opendaylight.controller.sal.binding.api.mount.MountProviderInstance;
 import org.opendaylight.controller.sal.binding.api.mount.MountProviderService;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
index 258ba517775a2145f3c3046ebbf08194123a0439..58e46ceca3d14d63bb2dbd6a45feec2417280f21 100644 (file)
@@ -19,7 +19,7 @@ import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
 import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory.NotificationInvoker;
 import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.binding.Notification;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
index f2e467038f003cbc3acaa9dad3f4d108b0df691c..13a9f1cc107642a483390d90460ed39a1795b488 100644 (file)
@@ -33,7 +33,7 @@ import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper;
 import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.RpcService;
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1418AugmentationTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1418AugmentationTest.java
new file mode 100644 (file)
index 0000000..6b5c825
--- /dev/null
@@ -0,0 +1,135 @@
+package org.opendaylight.controller.md.sal.binding.impl.test;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataChangeListenerTest;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertContains;
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertEmpty;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.top;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_FOO_KEY;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.topLevelList;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.leafOnlyUsesAugment;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.complexUsesAugment;
+
+public class Bug1418AugmentationTest extends AbstractDataChangeListenerTest{
+    private static final InstanceIdentifier<Top> TOP = InstanceIdentifier.create(Top.class);
+    private static final InstanceIdentifier<TopLevelList> TOP_FOO = TOP.child(TopLevelList.class, TOP_FOO_KEY);
+    private static final InstanceIdentifier<TreeLeafOnlyUsesAugment> SIMPLE_AUGMENT =
+            TOP.child(TopLevelList.class, TOP_FOO_KEY).augmentation(TreeLeafOnlyUsesAugment.class);
+    private static final InstanceIdentifier<TreeComplexUsesAugment> COMPLEX_AUGMENT =
+            TOP.child(TopLevelList.class, TOP_FOO_KEY).augmentation(TreeComplexUsesAugment.class);
+    private static final ListViaUsesKey LIST_VIA_USES_KEY =
+            new ListViaUsesKey("list key");
+    private static final ListViaUsesKey LIST_VIA_USES_KEY_MOD =
+            new ListViaUsesKey("list key modified");
+
+    @Test
+    public void leafOnlyAugmentationCreatedTest() {
+        TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
+                AsyncDataBroker.DataChangeScope.SUBTREE);
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf"));
+        assertCommit(writeTx.submit());
+        assertTrue(listener.hasEvent());
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+        assertContains(event.getCreatedData(), SIMPLE_AUGMENT);
+        assertEmpty(event.getUpdatedData());
+        assertEmpty(event.getOriginalData());
+        assertEmpty(event.getRemovedPaths());
+    }
+
+    @Test
+    public void leafOnlyAugmentationUpdatedTest() {
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf"));
+        assertCommit(writeTx.submit());
+        TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
+                AsyncDataBroker.DataChangeScope.SUBTREE);
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf changed"));
+        assertCommit(writeTx.submit());
+        assertTrue(listener.hasEvent());
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+        assertContains(event.getUpdatedData(), SIMPLE_AUGMENT);
+        assertContains(event.getOriginalData(), SIMPLE_AUGMENT);
+        assertEmpty(event.getCreatedData());
+        assertEmpty(event.getRemovedPaths());
+    }
+
+    @Test
+    public void leafOnlyAugmentationDeletedTest() {
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf"));
+        assertCommit(writeTx.submit());
+        TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
+                AsyncDataBroker.DataChangeScope.SUBTREE);
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.delete(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT);
+        assertCommit(writeTx.submit());
+        assertTrue(listener.hasEvent());
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+        assertContains(event.getRemovedPaths(), SIMPLE_AUGMENT);
+        assertContains(event.getOriginalData(), SIMPLE_AUGMENT);
+        assertEmpty(event.getCreatedData());
+        assertEmpty(event.getUpdatedData());
+    }
+
+    @Test
+    public void complexAugmentationCreatedTest() {
+        TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT,
+                AsyncDataBroker.DataChangeScope.SUBTREE);
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment(LIST_VIA_USES_KEY));
+        assertCommit(writeTx.submit());
+        assertTrue(listener.hasEvent());
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+        assertContains(event.getCreatedData(), COMPLEX_AUGMENT);
+        assertContains(event.getCreatedData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
+        assertEmpty(event.getUpdatedData());
+        assertEmpty(event.getOriginalData());
+        assertEmpty(event.getRemovedPaths());
+    }
+
+    @Test
+    public void complexAugmentationUpdatedTest() {
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment(LIST_VIA_USES_KEY));
+        assertCommit(writeTx.submit());
+        TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT,
+                AsyncDataBroker.DataChangeScope.SUBTREE);
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment(LIST_VIA_USES_KEY_MOD));
+        assertCommit(writeTx.submit());
+        assertTrue(listener.hasEvent());
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+        assertContains(event.getUpdatedData(), COMPLEX_AUGMENT);
+        assertContains(event.getCreatedData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY_MOD));
+        assertContains(event.getRemovedPaths(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
+        assertContains(event.getOriginalData(), COMPLEX_AUGMENT);
+        assertContains(event.getOriginalData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
+    }
+}
index 63a4ffb23a3930d4830ea3e300c168578172c39c..356a4b810ecb6a74bb484974e6e1477aa7da4bba 100644 (file)
@@ -10,7 +10,7 @@ package org.opendaylight.controller.sal.binding.test.util;
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
 import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProvider;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
index 42d5cfff65e755e29ef2f9198fb6478eabf783d6..7a66c411962285efe2de6514b862f10670b9e296 100644 (file)
       <type>test-jar</type>
       <scope>test</scope>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.model</groupId>
-      <artifactId>model-flow-management</artifactId>
-      <scope>test</scope>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-flow-service</artifactId>
diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java
deleted file mode 100644 (file)
index 34a71ac..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.binding.test.bugfix;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import org.junit.Ignore;
-import org.junit.Test;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-
-@SuppressWarnings("deprecation")
-public class DOMCodecBug01Test extends AbstractDataServiceTest {
-
-    private static final long FLOW_ID = 1234;
-    private static final String NODE_ID = "node:1";
-
-    private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
-
-    private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) //
-            .child(Node.class, NODE_KEY).toInstance();
-
-    private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
-
-    private static final FlowKey FLOW_KEY = new FlowKey(FLOW_ID, NODE_REF);
-
-    private static final InstanceIdentifier<? extends DataObject> FLOW_INSTANCE_ID_BA = //
-    InstanceIdentifier.builder(Flows.class) //
-            .child(Flow.class, FLOW_KEY) //
-            .toInstance();
-
-
-
-    /**
-     *
-     * Testcase for https://bugs.opendaylight.org/show_bug.cgi?id=
-     *
-     * Cannot compile CoDec for
-     * org.opendaylight.yang.gen.v1.urn.opendaylight.flow
-     * .config.rev130819.flows.Flow
-     *
-     * When invoking following code in the consumer, user got an
-     * IllegalStateException during creation of mapping between Java DTOs and
-     * data-dom.
-     *
-     * Exception was compilation error which was caused by incorect generation
-     * of code.
-     *
-     * Reported by Depthi V V
-     *
-     * @deprecated This test tests indirect generation, which should be tested
-     *    different way. the test creates conflicting transactions
-     *    and assumes correct commit - to test codec generation
-     *
-     */
-    @Test
-    @Ignore
-    @Deprecated
-    public void testIndirectGeneration() throws Exception {
-
-        ExecutorService basePool = Executors.newFixedThreadPool(2);
-        ListeningExecutorService listenablePool = MoreExecutors.listeningDecorator(basePool);
-
-        createFlow();
-
-        Object lock = new Object();
-        CreateFlowTask task1 = new CreateFlowTask(lock);
-        CreateFlowTask task2 = new CreateFlowTask(lock);
-        CreateFlowTask task3 = new CreateFlowTask(lock);
-
-        ListenableFuture<Void> task1Future = listenablePool.submit(task1);
-        ListenableFuture<Void> task2Future = listenablePool.submit(task2);
-        ListenableFuture<Void> task3Future = listenablePool.submit(task3);
-
-
-        @SuppressWarnings("unchecked")
-        ListenableFuture<List<Void>> compositeFuture = Futures.allAsList(task1Future,task2Future,task3Future);
-
-        Thread.sleep(500);
-        //lock.notifyAll();
-        compositeFuture.get();
-
-        verifyDataAreStoredProperly();
-
-        DataModificationTransaction modification2 = baDataService.beginTransaction();
-        modification2.removeConfigurationData(FLOW_INSTANCE_ID_BA);
-
-        DataObject originalData = modification2.getOriginalConfigurationData().get(FLOW_INSTANCE_ID_BA);
-        assertNotNull(originalData);
-        RpcResult<TransactionStatus> ret2 = modification2.commit().get();
-
-        assertNotNull(ret2);
-        assertEquals(TransactionStatus.COMMITED, ret2.getResult());
-
-        // Data are not in the store.
-        assertNull(baDataService.readConfigurationData(FLOW_INSTANCE_ID_BA));
-
-    }
-
-    private void createFlow() throws Exception {
-
-        DataModificationTransaction modification = baDataService.beginTransaction();
-
-        FlowBuilder flow = new FlowBuilder();
-        MatchBuilder match = new MatchBuilder();
-        VlanMatchBuilder vlanBuilder = new VlanMatchBuilder();
-        VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
-        VlanId vlanId = new VlanId(10);
-        vlanBuilder.setVlanId(vlanIdBuilder.setVlanId(vlanId).build());
-        match.setVlanMatch(vlanBuilder.build());
-
-        flow.setKey(FLOW_KEY);
-        flow.setMatch(match.build());
-        flow.setNode(NODE_REF);
-        InstructionsBuilder instructions = new InstructionsBuilder();
-        InstructionBuilder instruction = new InstructionBuilder();
-
-        instruction.setOrder(10);
-        ApplyActionsBuilder applyActions = new ApplyActionsBuilder();
-        List<Action> actionList = new ArrayList<>();
-        PopMplsActionBuilder popMplsAction = new PopMplsActionBuilder();
-        popMplsAction.setEthernetType(34);
-        actionList.add(new ActionBuilder().setAction(new PopMplsActionCaseBuilder().setPopMplsAction(popMplsAction.build()).build()).setOrder(10).build());
-
-        applyActions.setAction(actionList );
-
-        instruction.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(applyActions.build()).build());
-
-
-        List<Instruction> instructionList = Collections.<Instruction>singletonList(instruction.build());
-        instructions.setInstruction(instructionList );
-
-        flow.setInstructions(instructions.build());
-        modification.putConfigurationData(FLOW_INSTANCE_ID_BA, flow.build());
-        RpcResult<TransactionStatus> ret = modification.commit().get();
-        assertNotNull(ret);
-        assertEquals(TransactionStatus.COMMITED, ret.getResult());
-    }
-
-    private void createFlow2() throws Exception {
-        DataModificationTransaction modification = baDataService.beginTransaction();
-        long id = 123;
-        FlowKey key = new FlowKey(id, new NodeRef(NODE_INSTANCE_ID_BA));
-        InstanceIdentifier<?> path1;
-        FlowBuilder flow = new FlowBuilder();
-        flow.setKey(key);
-        MatchBuilder match = new MatchBuilder();
-        match.setLayer4Match(new TcpMatchBuilder().build());
-        flow.setMatch(match.build());
-
-        path1 = InstanceIdentifier.builder(Flows.class).child(Flow.class, key).toInstance();
-       // DataObject cls = (DataObject) modification.readConfigurationData(path1);
-        modification.putConfigurationData(path1, flow.build());
-        modification.commit();
-
-    }
-
-    private class CreateFlowTask implements Callable<Void> {
-
-        public CreateFlowTask(final Object startSync) {
-        }
-
-        @Override
-        public Void call() {
-            try {
-                //startSyncObj          ect.wait();
-                //Thread.sleep(500);
-                createFlow();
-                createFlow2();
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-            return null;
-        }
-    }
-
-    private void verifyDataAreStoredProperly() {
-        CompositeNode biFlows = biDataService.readConfigurationData(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.of(Flows.QNAME));
-        assertNotNull(biFlows);
-        CompositeNode biFlow = biFlows.getFirstCompositeByName(Flow.QNAME);
-        assertNotNull(biFlow);
-    }
-
-
-}
index b8bb891e790f7e905edc071c04e61608d4f277c1..1912462cf0aa5d081ec56166d16b6256e69f7be8 100644 (file)
@@ -8,12 +8,6 @@
   </parent>
   <artifactId>sal-binding-it</artifactId>
 
-  <properties>
-    <sonar.jacoco.itReportPath>../sal-binding-broker/target/jacoco-it.exec</sonar.jacoco.itReportPath>
-    <!-- Sonar jacoco plugin to get integration test coverage info -->
-    <sonar.jacoco.reportPath>../sal-binding-broker/target/jacoco.exec</sonar.jacoco.reportPath>
-  </properties>
-
   <dependencies>
     <dependency>
       <groupId>ch.qos.logback</groupId>
       <groupId>org.mockito</groupId>
       <artifactId>mockito-all</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>object-cache-guava</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-manager</artifactId>
       <groupId>org.slf4j</groupId>
       <artifactId>log4j-over-slf4j</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.model</groupId>
-      <artifactId>model-flow-management</artifactId>
-      <scope>provided</scope>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-flow-service</artifactId>
             </lifecycleMappingMetadata>
           </configuration>
         </plugin>
-        <plugin>
-          <groupId>org.jacoco</groupId>
-          <artifactId>jacoco-maven-plugin</artifactId>
-          <version>${jacoco.version}</version>
-          <configuration>
-            <destFile>../sal-binding-broker/target/jacoco-it.exec</destFile>
-            <includes>
-              <include>org.opendaylight.controller.*</include>
-            </includes>
-          </configuration>
-          <executions>
-            <execution>
-              <id>pre-test</id>
-              <goals>
-                <goal>prepare-agent</goal>
-              </goals>
-            </execution>
-            <execution>
-              <id>post-test</id>
-              <configuration>
-                <skip>true</skip>
-              </configuration>
-            </execution>
-          </executions>
-        </plugin>
       </plugins>
     </pluginManagement>
     <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <configuration>
-          <reuseForks>false</reuseForks>
-        </configuration>
-      </plugin>
-      <plugin>
-        <groupId>org.jacoco</groupId>
-        <artifactId>jacoco-maven-plugin</artifactId>
-        <configuration>
-          <includes>
-            <include>org.opendaylight.controller.*</include>
-          </includes>
-        </configuration>
-        <executions>
-          <execution>
-            <id>pre-test</id>
-            <goals>
-              <goal>prepare-agent</goal>
-            </goals>
-          </execution>
-          <execution>
-            <id>post-test</id>
-            <goals>
-              <goal>report</goal>
-            </goals>
-            <phase>test</phase>
-          </execution>
-        </executions>
-      </plugin>
       <plugin>
         <groupId>org.ops4j.pax.exam</groupId>
         <artifactId>maven-paxexam-plugin</artifactId>
index c389618f2eb829f2dedb12ec58b0b365f7654ff0..83a69969b7b8c8bd0be90111227bda05cd61fd58 100644 (file)
@@ -30,6 +30,8 @@ public class TestHelper {
                 mavenBundle(YANGTOOLS, "util").versionAsInProject(), // //
                 mavenBundle(YANGTOOLS, "yang-binding").versionAsInProject(), // //
                 mavenBundle(YANGTOOLS, "yang-common").versionAsInProject(), // //
+                mavenBundle(YANGTOOLS, "object-cache-api").versionAsInProject(), // //
+                mavenBundle(YANGTOOLS, "object-cache-guava").versionAsInProject(), // //
                 mavenBundle(CONTROLLER, "sal-common").versionAsInProject(), // //
                 mavenBundle(CONTROLLER, "sal-common-api").versionAsInProject(), // //
                 mavenBundle(CONTROLLER, "sal-common-impl").versionAsInProject(), // //
similarity index 98%
rename from opendaylight/md-sal/sal-protocolbuffer-encoding/pom.xml
rename to opendaylight/md-sal/sal-clustering-commons/pom.xml
index 28e629a92c92fa7b165a390e12e2fd89a15e2ba5..6db4d3a094f43cb80c461418cfd56d54639dd5a2 100644 (file)
@@ -8,7 +8,7 @@
     <version>1.1-SNAPSHOT</version>
   </parent>
 
-  <artifactId>sal-protocolbuffer-encoding</artifactId>
+  <artifactId>sal-clustering-commons</artifactId>
 
   <packaging>bundle</packaging>
 
similarity index 93%
rename from opendaylight/md-sal/sal-protocolbuffer-encoding/run.sh
rename to opendaylight/md-sal/sal-clustering-commons/run.sh
index f0907db6648e974298bb399f0956e719cd6e1552..d3d0324fa029e193dd4b36fcec6d34818db07e17 100755 (executable)
@@ -30,7 +30,7 @@
 #   org.opendaylight.controller.protobuff.messages to properly exclude from sonar.
 ########################################################################################################
 
-protoc --proto_path=src/main/resources --java_out=src/main/java src/main/resources/*.proto
+protoc --proto_path=src/main/resources --proto_path=../sal-akka-raft/src/main/resources --java_out=src/main/java src/main/resources/*.proto
 
 echo "Done generating Java source files."
 
@@ -1,13 +1,3 @@
-/*
- *
- *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- *  This program and the accompanying materials are made available under the
- *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
- *  and is available at http://www.eclipse.org/legal/epl-v10.html
- *
- */
-
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: CompositeModificationPayload.proto
 
@@ -1,13 +1,3 @@
-/*
- *
- *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- *  This program and the accompanying materials are made available under the
- *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
- *  and is available at http://www.eclipse.org/legal/epl-v10.html
- *
- */
-
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: Cohort.proto
 
@@ -1,13 +1,3 @@
-/*
- *
- *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- *  This program and the accompanying materials are made available under the
- *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
- *  and is available at http://www.eclipse.org/legal/epl-v10.html
- *
- */
-
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: Common.proto
 
@@ -1,13 +1,3 @@
-/*
- *
- *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- *  This program and the accompanying materials are made available under the
- *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
- *  and is available at http://www.eclipse.org/legal/epl-v10.html
- *
- */
-
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: SimpleNormalizedNode.proto
 
@@ -1,13 +1,3 @@
-/*
- *
- *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- *  This program and the accompanying materials are made available under the
- *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
- *  and is available at http://www.eclipse.org/legal/epl-v10.html
- *
- */
-
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: DataChangeListener.proto
 
@@ -1,13 +1,3 @@
-/*
- *
- *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- *  This program and the accompanying materials are made available under the
- *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
- *  and is available at http://www.eclipse.org/legal/epl-v10.html
- *
- */
-
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: Persistent.proto
 
@@ -1,13 +1,3 @@
-/*
- *
- *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- *  This program and the accompanying materials are made available under the
- *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
- *  and is available at http://www.eclipse.org/legal/epl-v10.html
- *
- */
-
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: ListenerRegistration.proto
 
@@ -1,13 +1,3 @@
-/*
- *
- *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- *  This program and the accompanying materials are made available under the
- *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
- *  and is available at http://www.eclipse.org/legal/epl-v10.html
- *
- */
-
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: ShardManager.proto
 
@@ -1,13 +1,3 @@
-/*
- *
- *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- *  This program and the accompanying materials are made available under the
- *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
- *  and is available at http://www.eclipse.org/legal/epl-v10.html
- *
- */
-
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: ShardTransactionChain.proto
 
@@ -1,13 +1,3 @@
-/*
- *
- *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- *  This program and the accompanying materials are made available under the
- *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
- *  and is available at http://www.eclipse.org/legal/epl-v10.html
- *
- */
-
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: ShardTransaction.proto
 
@@ -653,6 +643,16 @@ public final class ShardTransactionMessages {
      */
     com.google.protobuf.ByteString
         getTransactionIdBytes();
+
+    // required int32 transactionType = 2;
+    /**
+     * <code>required int32 transactionType = 2;</code>
+     */
+    boolean hasTransactionType();
+    /**
+     * <code>required int32 transactionType = 2;</code>
+     */
+    int getTransactionType();
   }
   /**
    * Protobuf type {@code org.opendaylight.controller.mdsal.CreateTransaction}
@@ -710,6 +710,11 @@ public final class ShardTransactionMessages {
               transactionId_ = input.readBytes();
               break;
             }
+            case 16: {
+              bitField0_ |= 0x00000002;
+              transactionType_ = input.readInt32();
+              break;
+            }
           }
         }
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -793,8 +798,25 @@ public final class ShardTransactionMessages {
       }
     }
 
+    // required int32 transactionType = 2;
+    public static final int TRANSACTIONTYPE_FIELD_NUMBER = 2;
+    private int transactionType_;
+    /**
+     * <code>required int32 transactionType = 2;</code>
+     */
+    public boolean hasTransactionType() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>required int32 transactionType = 2;</code>
+     */
+    public int getTransactionType() {
+      return transactionType_;
+    }
+
     private void initFields() {
       transactionId_ = "";
+      transactionType_ = 0;
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
@@ -805,6 +827,10 @@ public final class ShardTransactionMessages {
         memoizedIsInitialized = 0;
         return false;
       }
+      if (!hasTransactionType()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
       memoizedIsInitialized = 1;
       return true;
     }
@@ -815,6 +841,9 @@ public final class ShardTransactionMessages {
       if (((bitField0_ & 0x00000001) == 0x00000001)) {
         output.writeBytes(1, getTransactionIdBytes());
       }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeInt32(2, transactionType_);
+      }
       getUnknownFields().writeTo(output);
     }
 
@@ -828,6 +857,10 @@ public final class ShardTransactionMessages {
         size += com.google.protobuf.CodedOutputStream
           .computeBytesSize(1, getTransactionIdBytes());
       }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(2, transactionType_);
+      }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
       return size;
@@ -946,6 +979,8 @@ public final class ShardTransactionMessages {
         super.clear();
         transactionId_ = "";
         bitField0_ = (bitField0_ & ~0x00000001);
+        transactionType_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000002);
         return this;
       }
 
@@ -978,6 +1013,10 @@ public final class ShardTransactionMessages {
           to_bitField0_ |= 0x00000001;
         }
         result.transactionId_ = transactionId_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.transactionType_ = transactionType_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
@@ -999,6 +1038,9 @@ public final class ShardTransactionMessages {
           transactionId_ = other.transactionId_;
           onChanged();
         }
+        if (other.hasTransactionType()) {
+          setTransactionType(other.getTransactionType());
+        }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
@@ -1008,6 +1050,10 @@ public final class ShardTransactionMessages {
 
           return false;
         }
+        if (!hasTransactionType()) {
+
+          return false;
+        }
         return true;
       }
 
@@ -1104,6 +1150,39 @@ public final class ShardTransactionMessages {
         return this;
       }
 
+      // required int32 transactionType = 2;
+      private int transactionType_ ;
+      /**
+       * <code>required int32 transactionType = 2;</code>
+       */
+      public boolean hasTransactionType() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>required int32 transactionType = 2;</code>
+       */
+      public int getTransactionType() {
+        return transactionType_;
+      }
+      /**
+       * <code>required int32 transactionType = 2;</code>
+       */
+      public Builder setTransactionType(int value) {
+        bitField0_ |= 0x00000002;
+        transactionType_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required int32 transactionType = 2;</code>
+       */
+      public Builder clearTransactionType() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        transactionType_ = 0;
+        onChanged();
+        return this;
+      }
+
       // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.CreateTransaction)
     }
 
@@ -6581,32 +6660,33 @@ public final class ShardTransactionMessages {
     java.lang.String[] descriptorData = {
       "\n\026ShardTransaction.proto\022!org.opendaylig" +
       "ht.controller.mdsal\032\014Common.proto\"\022\n\020Clo" +
-      "seTransaction\"\027\n\025CloseTransactionReply\"*" +
+      "seTransaction\"\027\n\025CloseTransactionReply\"C" +
       "\n\021CreateTransaction\022\025\n\rtransactionId\030\001 \002" +
-      "(\t\"M\n\026CreateTransactionReply\022\034\n\024transact" +
-      "ionActorPath\030\001 \002(\t\022\025\n\rtransactionId\030\002 \002(" +
-      "\t\"\022\n\020ReadyTransaction\"*\n\025ReadyTransactio" +
-      "nReply\022\021\n\tactorPath\030\001 \002(\t\"l\n\nDeleteData\022" +
-      "^\n\037instanceIdentifierPathArguments\030\001 \002(\013" +
-      "25.org.opendaylight.controller.mdsal.Ins",
-      "tanceIdentifier\"\021\n\017DeleteDataReply\"j\n\010Re" +
-      "adData\022^\n\037instanceIdentifierPathArgument" +
-      "s\030\001 \002(\01325.org.opendaylight.controller.md" +
-      "sal.InstanceIdentifier\"P\n\rReadDataReply\022" +
-      "?\n\016normalizedNode\030\001 \001(\0132\'.org.opendaylig" +
-      "ht.controller.mdsal.Node\"\254\001\n\tWriteData\022^" +
-      "\n\037instanceIdentifierPathArguments\030\001 \002(\0132" +
-      "5.org.opendaylight.controller.mdsal.Inst" +
-      "anceIdentifier\022?\n\016normalizedNode\030\002 \002(\0132\'" +
-      ".org.opendaylight.controller.mdsal.Node\"",
-      "\020\n\016WriteDataReply\"\254\001\n\tMergeData\022^\n\037insta" +
+      "(\t\022\027\n\017transactionType\030\002 \002(\005\"M\n\026CreateTra" +
+      "nsactionReply\022\034\n\024transactionActorPath\030\001 " +
+      "\002(\t\022\025\n\rtransactionId\030\002 \002(\t\"\022\n\020ReadyTrans" +
+      "action\"*\n\025ReadyTransactionReply\022\021\n\tactor" +
+      "Path\030\001 \002(\t\"l\n\nDeleteData\022^\n\037instanceIden" +
+      "tifierPathArguments\030\001 \002(\01325.org.opendayl",
+      "ight.controller.mdsal.InstanceIdentifier" +
+      "\"\021\n\017DeleteDataReply\"j\n\010ReadData\022^\n\037insta" +
       "nceIdentifierPathArguments\030\001 \002(\01325.org.o" +
       "pendaylight.controller.mdsal.InstanceIde" +
-      "ntifier\022?\n\016normalizedNode\030\002 \002(\0132\'.org.op" +
-      "endaylight.controller.mdsal.Node\"\020\n\016Merg" +
-      "eDataReplyBV\n:org.opendaylight.controlle" +
-      "r.protobuff.messages.transactionB\030ShardT" +
-      "ransactionMessages"
+      "ntifier\"P\n\rReadDataReply\022?\n\016normalizedNo" +
+      "de\030\001 \001(\0132\'.org.opendaylight.controller.m" +
+      "dsal.Node\"\254\001\n\tWriteData\022^\n\037instanceIdent" +
+      "ifierPathArguments\030\001 \002(\01325.org.opendayli" +
+      "ght.controller.mdsal.InstanceIdentifier\022" +
+      "?\n\016normalizedNode\030\002 \002(\0132\'.org.opendaylig",
+      "ht.controller.mdsal.Node\"\020\n\016WriteDataRep" +
+      "ly\"\254\001\n\tMergeData\022^\n\037instanceIdentifierPa" +
+      "thArguments\030\001 \002(\01325.org.opendaylight.con" +
+      "troller.mdsal.InstanceIdentifier\022?\n\016norm" +
+      "alizedNode\030\002 \002(\0132\'.org.opendaylight.cont" +
+      "roller.mdsal.Node\"\020\n\016MergeDataReplyBV\n:o" +
+      "rg.opendaylight.controller.protobuff.mes" +
+      "sages.transactionB\030ShardTransactionMessa" +
+      "ges"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
       new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -6630,7 +6710,7 @@ public final class ShardTransactionMessages {
           internal_static_org_opendaylight_controller_mdsal_CreateTransaction_fieldAccessorTable = new
             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
               internal_static_org_opendaylight_controller_mdsal_CreateTransaction_descriptor,
-              new java.lang.String[] { "TransactionId", });
+              new java.lang.String[] { "TransactionId", "TransactionType", });
           internal_static_org_opendaylight_controller_mdsal_CreateTransactionReply_descriptor =
             getDescriptor().getMessageTypes().get(3);
           internal_static_org_opendaylight_controller_mdsal_CreateTransactionReply_fieldAccessorTable = new
similarity index 96%
rename from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ShardTransaction.proto
rename to opendaylight/md-sal/sal-clustering-commons/src/main/resources/ShardTransaction.proto
index 9684b7d72f57679ad069f31320bf00f0e989380c..4177bd7a052c244385e75df38dcf0fa31523b67c 100644 (file)
@@ -14,6 +14,7 @@ message CloseTransactionReply{
 
 message CreateTransaction{
   required string transactionId = 1;
+  required int32  transactionType =2;
 }
 
 message CreateTransactionReply{
diff --git a/opendaylight/md-sal/sal-clustering-config/pom.xml b/opendaylight/md-sal/sal-clustering-config/pom.xml
new file mode 100644 (file)
index 0000000..d726823
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>sal-parent</artifactId>
+    <version>1.1-SNAPSHOT</version>
+  </parent>
+  <artifactId>sal-clustering-config</artifactId>
+  <description>Configuration files for md-sal clustering</description>
+  <packaging>jar</packaging>
+  <build>
+    <plugins>
+        <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-artifacts</id>
+            <goals>
+              <goal>attach-artifact</goal>
+            </goals>
+            <phase>package</phase>
+            <configuration>
+              <artifacts>
+                <artifact>
+                  <file>${project.build.directory}/classes/initial/*.conf</file>
+                  <type>xml</type>
+                  <classifier>config</classifier>
+                </artifact>
+              </artifacts>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/05-clustering.xml.conf b/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/05-clustering.xml.conf
new file mode 100644 (file)
index 0000000..7891ee2
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<snapshot>
+    <configuration>
+        <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+            <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+                <module>
+                    <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-inmemory-data-broker</type>
+                    <name>inmemory-data-broker</name>
+
+                    <schema-service>
+                        <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+                        <name>yang-schema-service</name>
+                    </schema-service>
+
+                    <config-data-store>
+                        <type xmlns:config-dom-store-spi="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:config-dom-store">config-dom-store-spi:config-dom-datastore</type>
+                        <name>distributed-config-store-service</name>
+                    </config-data-store>
+
+                    <operational-data-store>
+                        <type xmlns:operational-dom-store-spi="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:operational-dom-store">operational-dom-store-spi:operational-dom-datastore</type>
+                        <name>distributed-operational-store-service</name>
+                    </operational-data-store>
+                </module>
+
+                <module>
+                    <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:distributed-datastore-provider">prefix:distributed-operational-datastore-provider</type>
+                    <name>distributed-operational-store-module</name>
+                    <schema-service>
+                        <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+                        <name>yang-schema-service</name>
+                    </schema-service>
+                </module>
+
+                <module>
+                    <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:distributed-datastore-provider">prefix:distributed-config-datastore-provider</type>
+                    <name>distributed-config-store-module</name>
+                    <schema-service>
+                        <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+                        <name>yang-schema-service</name>
+                    </schema-service>
+                </module>
+
+                <module>
+                    <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:remote-rpc-connector">prefix:remote-rpc-connector</type>
+                    <name>remote-rpc-connector</name>
+                    <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:remote-rpc-connector">
+                        <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+                        <name>dom-broker</name>
+                    </dom-broker>
+                </module>
+
+            </modules>
+            <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+
+                <service>
+                    <type xmlns:config-dom-store-spi="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:config-dom-store">config-dom-store-spi:config-dom-datastore</type>
+                    <instance>
+                        <name>distributed-config-store-service</name>
+                        <provider>/modules/module[type='distributed-config-datastore-provider'][name='distributed-config-store-module']</provider>
+                    </instance>
+                </service>
+                <service>
+                    <type xmlns:operational-dom-store-spi="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:operational-dom-store">operational-dom-store-spi:operational-dom-datastore</type>
+                    <instance>
+                        <name>distributed-operational-store-service</name>
+                        <provider>/modules/module[type='distributed-operational-datastore-provider'][name='distributed-operational-store-module']</provider>
+                    </instance>
+                </service>
+
+            </services>
+        </data>
+    </configuration>
+    <required-capabilities>
+        <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&amp;revision=2013-10-28</capability>
+    </required-capabilities>
+</snapshot>
diff --git a/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/akka.conf b/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/akka.conf
new file mode 100644 (file)
index 0000000..9749ae2
--- /dev/null
@@ -0,0 +1,55 @@
+
+odl-cluster-data {
+  akka {
+    actor {
+      provider = "akka.cluster.ClusterActorRefProvider"
+      serializers {
+                java = "akka.serialization.JavaSerializer"
+                proto = "akka.remote.serialization.ProtobufSerializer"
+              }
+
+              serialization-bindings {
+                  "com.google.protobuf.Message" = proto
+
+              }
+    }
+    remote {
+      log-remote-lifecycle-events = off
+      netty.tcp {
+        hostname = "<CHANGE_ME>"
+        port = 2550
+           maximum-frame-size = 2097152
+           send-buffer-size = 52428800
+           receive-buffer-size = 52428800
+      }
+    }
+
+    cluster {
+      seed-nodes = ["akka.tcp://opendaylight-cluster-data@<CHANGE_ME>:2550"]
+
+      auto-down-unreachable-after = 10s
+    }
+  }
+}
+
+odl-cluster-rpc {
+  akka {
+    actor {
+      provider = "akka.cluster.ClusterActorRefProvider"
+
+    }
+    remote {
+      log-remote-lifecycle-events = off
+      netty.tcp {
+        hostname = "<CHANGE_ME>"
+        port = 2551
+      }
+    }
+
+    cluster {
+      seed-nodes = ["akka.tcp://opendaylight-cluster-rpc@<CHANGE_ME>:2551"]
+
+      auto-down-unreachable-after = 10s
+    }
+  }
+}
diff --git a/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/module-shards.conf b/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/module-shards.conf
new file mode 100644 (file)
index 0000000..8449abb
--- /dev/null
@@ -0,0 +1,70 @@
+# This file describes which shards live on which members
+# The format for a module-shards is as follows,
+# {
+#    name = "<friendly_name_of_the_module>"
+#    shards = [
+#        {
+#            name="<any_name_that_is_unique_for_the_module>"
+#            replicas = [
+#                "<name_of_member_on_which_to_run>"
+#            ]
+#     ]
+# }
+#
+# For Helium we support only one shard per module. Beyond Helium
+# we will support more than 1
+# The replicas section is a collection of member names. This information
+# will be used to decide on which members replicas of a particular shard will be
+# located. Once replication is integrated with the distributed data store then
+# this section can have multiple entries.
+#
+#
+
+
+module-shards = [
+    {
+        name = "default"
+        shards = [
+            {
+                name="default"
+                replicas = [
+                    "member-1"
+                ]
+            }
+        ]
+    },
+    {
+        name = "topology"
+        shards = [
+            {
+                name="topology"
+                replicas = [
+                    "member-1"
+                ]
+            }
+        ]
+    },
+    {
+        name = "inventory"
+        shards = [
+            {
+                name="inventory"
+                replicas = [
+                    "member-1"
+                ]
+            }
+        ]
+    },
+         {
+             name = "toaster"
+             shards = [
+                 {
+                     name="toaster"
+                     replicas = [
+                         "member-1"
+                     ]
+                 }
+             ]
+         }
+
+]
diff --git a/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/modules.conf b/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/modules.conf
new file mode 100644 (file)
index 0000000..68347ee
--- /dev/null
@@ -0,0 +1,32 @@
+# This file should describe all the modules that need to be placed in a separate shard
+# The format of the configuration is as follows
+# {
+#    name = "<friendly_name_of_module>"
+#    namespace = "<the yang namespace of the module>"
+#    shard-strategy = "module"
+# }
+#
+# Note that at this time the only shard-strategy we support is module which basically
+# will put all the data of a single module in two shards (one for config and one for
+# operational data)
+
+modules = [
+    {
+        name = "inventory"
+        namespace = "urn:opendaylight:inventory"
+        shard-strategy = "module"
+    },
+
+    {
+        name = "topology"
+        namespace = "urn:TBD:params:xml:ns:yang:network-topology"
+        shard-strategy = "module"
+    },
+
+    {
+        name = "toaster"
+        namespace = "http://netconfcentral.org/ns/toaster"
+        shard-strategy = "module"
+    }
+
+]
diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionCommitDeadlockException.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionCommitDeadlockException.java
new file mode 100644 (file)
index 0000000..60313bf
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.md.sal.common.api.data;
+
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+
+import com.google.common.base.Function;
+
+/**
+ * A type of TransactionCommitFailedException that indicates a situation that would result in a
+ * threading deadlock. This can occur if a caller that submits a write transaction tries to perform
+ * a blocking call via one of the <code>get</code> methods on the returned ListenableFuture. Callers
+ * should process the commit result asynchronously (via Futures#addCallback) to ensure deadlock
+ * won't occur.
+ *
+ * @author Thomas Pantelis
+ */
+public class TransactionCommitDeadlockException extends TransactionCommitFailedException {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String DEADLOCK_MESSAGE =
+            "An attempt to block on a ListenableFuture via a get method from a write " +
+            "transaction submit was detected that would result in deadlock. The commit " +
+            "result must be obtained asynchronously, e.g. via Futures#addCallback, to avoid deadlock.";
+
+    public static Function<Void, Exception> DEADLOCK_EXECUTOR_FUNCTION = new Function<Void, Exception>() {
+        @Override
+        public Exception apply(Void notUsed) {
+            return new TransactionCommitDeadlockException( DEADLOCK_MESSAGE,
+                    RpcResultBuilder.newError(ErrorType.APPLICATION, "lock-denied", DEADLOCK_MESSAGE));
+        }
+    };
+
+    public TransactionCommitDeadlockException(String message, final RpcError... errors) {
+        super(message, errors);
+    }
+}
index a732f2f1b96b72ee72a6987e2f2b94651656bf09..ca6e6e9718c5fd516860df86080838e30bfc5ce8 100644 (file)
@@ -36,7 +36,7 @@ import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.Path;
 import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
index 94c895dab385a92e3f547099ac83010cb7e517ec..848d425bf9d8a712d42a873b564a1657b9d95953 100644 (file)
 
     <dependency>
         <groupId>org.opendaylight.controller</groupId>
-        <artifactId>sal-protocolbuffer-encoding</artifactId>
+        <artifactId>sal-clustering-commons</artifactId>
         <version>1.1-SNAPSHOT</version>
     </dependency>
 
             <Private-Package></Private-Package>
             <Import-Package>!*snappy;!org.jboss.*;*</Import-Package>
             <Embed-Dependency>
-                sal-protocolbuffer-encoding;
+                sal-clustering-commons;
                 sal-akka-raft;
                 !sal*;
                 !*config-api*;
index baf04fe43b771fddc1c009d11aed056dea6bbe24..15c0548761ecd96afee865025fc573d5a2d38c6e 100644 (file)
@@ -20,8 +20,8 @@ public class ActorSystemFactory {
 
         @Nullable @Override public ActorSystem apply(@Nullable Void aVoid) {
                 ActorSystem system =
-                    ActorSystem.create("opendaylight-cluster", ConfigFactory
-                        .load().getConfig("ODLCluster"));
+                    ActorSystem.create("opendaylight-cluster-data", ConfigFactory
+                        .load().getConfig("odl-cluster-data"));
                 system.actorOf(Props.create(TerminationMonitor.class), "termination-monitor");
                 return system;
         }
index b435eda7a381560320825d44458580e3c165a403..cdf04dd093e95676b6ce9d635125abc8aa2b602e 100644 (file)
@@ -33,7 +33,7 @@ public class DataChangeListener extends AbstractUntypedActor {
     }
 
     @Override public void handleReceive(Object message) throws Exception {
-        if(message.getClass().equals(DataChanged.SERIALIZABLE_CLASS)){
+        if(message instanceof DataChanged){
             dataChanged(message);
         } else if(message instanceof EnableNotification){
             enableNotification((EnableNotification) message);
@@ -51,13 +51,13 @@ public class DataChangeListener extends AbstractUntypedActor {
             return;
         }
 
-        DataChanged reply = DataChanged.fromSerialize(schemaContext,message, pathId);
+        DataChanged reply = (DataChanged) message;
         AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>>
             change = reply.getChange();
         this.listener.onDataChanged(change);
 
         if(getSender() != null){
-            getSender().tell(new DataChangedReply().toSerializable(), getSelf());
+            getSender().tell(new DataChangedReply(), getSelf());
         }
     }
 
index cd9c330268e1316f2f76296bc4736bc3e7c8487f..a4ca4562685d4f4b3dc717588d0e35ede957d466 100644 (file)
@@ -30,6 +30,6 @@ public class DataChangeListenerProxy implements AsyncDataChangeListener<YangInst
 
     @Override public void onDataChanged(
         AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
-        dataChangeListenerActor.tell(new DataChanged(schemaContext,change).toSerializable(), null);
+        dataChangeListenerActor.tell(new DataChanged(schemaContext,change), null);
     }
 }
index 780f28f358ec327f5ec6ab9cace63f769695e55a..479af79748033342041f32fe5221e68f78bf1c2f 100644 (file)
@@ -8,11 +8,10 @@
 
 package org.opendaylight.controller.cluster.datastore;
 
-import java.util.concurrent.Executors;
-
 import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
-
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
 import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListener;
 import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListenerReply;
 import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
@@ -33,8 +32,7 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
+import java.util.concurrent.Executors;
 
 /**
  *
@@ -88,13 +86,12 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener, Au
 
         Object result = actorContext.executeLocalShardOperation(shardName,
             new RegisterChangeListener(path, dataChangeListenerActor.path(),
-                scope).toSerializable(),
+                scope),
             ActorContext.ASK_DURATION
         );
 
         if (result != null) {
-            RegisterChangeListenerReply reply = RegisterChangeListenerReply
-                .fromSerializable(actorContext.getActorSystem(), result);
+            RegisterChangeListenerReply reply = (RegisterChangeListenerReply) result;
             return new DataChangeListenerRegistrationProxy(actorContext
                 .actorSelection(reply.getListenerRegistrationPath()), listener,
                 dataChangeListenerActor);
index 23e27c9f5ff909b2c9b887aa5f7687b92d7cda10..10dbbc84d873ee54b5421643c00b046043e58114 100644 (file)
@@ -15,11 +15,10 @@ import akka.event.Logging;
 import akka.event.LoggingAdapter;
 import akka.japi.Creator;
 import akka.serialization.Serialization;
-
+import com.google.common.base.Optional;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
-
 import org.opendaylight.controller.cluster.datastore.jmx.mbeans.shard.ShardMBeanFactory;
 import org.opendaylight.controller.cluster.datastore.jmx.mbeans.shard.ShardStats;
 import org.opendaylight.controller.cluster.datastore.messages.CommitTransactionReply;
@@ -35,6 +34,8 @@ import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeList
 import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
 import org.opendaylight.controller.cluster.datastore.modification.Modification;
 import org.opendaylight.controller.cluster.datastore.modification.MutableCompositeModification;
+import org.opendaylight.controller.cluster.raft.ConfigParams;
+import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
 import org.opendaylight.controller.cluster.raft.RaftActor;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
@@ -44,6 +45,7 @@ import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import scala.concurrent.duration.FiniteDuration;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -51,6 +53,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
 
 /**
  * A Shard represents a portion of the logical data tree <br/>
@@ -60,6 +63,8 @@ import java.util.concurrent.Executors;
  */
 public class Shard extends RaftActor {
 
+    private static final ConfigParams configParams = new ShardConfigParams();
+
     public static final String DEFAULT_NAME = "default";
 
     private final ListeningExecutorService storeExecutor =
@@ -86,7 +91,7 @@ public class Shard extends RaftActor {
     private final List<ActorSelection> dataChangeListeners = new ArrayList<>();
 
     private Shard(String name, Map<String, String> peerAddresses) {
-        super(name, peerAddresses);
+        super(name, peerAddresses, Optional.of(configParams));
 
         this.name = name;
 
@@ -123,8 +128,8 @@ public class Shard extends RaftActor {
             } else if(getLeader() != null){
                 getLeader().forward(message, getContext());
             }
-        } else if (message.getClass().equals(RegisterChangeListener.SERIALIZABLE_CLASS)) {
-            registerChangeListener(RegisterChangeListener.fromSerializable(getContext().system(), message));
+        } else if (message instanceof RegisterChangeListener) {
+            registerChangeListener((RegisterChangeListener) message);
         } else if (message instanceof UpdateSchemaContext) {
             updateSchemaContext((UpdateSchemaContext) message);
         } else if (message instanceof ForwardedCommitTransaction) {
@@ -143,13 +148,29 @@ public class Shard extends RaftActor {
         }
     }
 
+   private ActorRef createTypedTransactionActor(CreateTransaction createTransaction,String transactionId){
+      if(createTransaction.getTransactionType()== TransactionProxy.TransactionType.READ_ONLY.ordinal()){
+        return getContext().actorOf(
+            ShardTransaction.props( store.newReadOnlyTransaction(), getSelf(), schemaContext), transactionId);
+
+      }else if (createTransaction.getTransactionType()== TransactionProxy.TransactionType.READ_WRITE.ordinal()){
+        return getContext().actorOf(
+            ShardTransaction.props( store.newReadWriteTransaction(), getSelf(), schemaContext), transactionId);
+
+
+      }else if (createTransaction.getTransactionType()== TransactionProxy.TransactionType.WRITE_ONLY.ordinal()){
+        return getContext().actorOf(
+            ShardTransaction.props( store.newWriteOnlyTransaction(), getSelf(), schemaContext), transactionId);
+      }else{
+        throw new IllegalArgumentException ("CreateTransaction message has unidentified transaction type="+createTransaction.getTransactionType()) ;
+      }
+   }
+
     private void createTransaction(CreateTransaction createTransaction) {
-        DOMStoreReadWriteTransaction transaction =
-            store.newReadWriteTransaction();
+
         String transactionId = "shard-" + createTransaction.getTransactionId();
         LOG.info("Creating transaction : {} " , transactionId);
-        ActorRef transactionActor = getContext().actorOf(
-            ShardTransaction.props(transaction, getSelf(), schemaContext), transactionId);
+        ActorRef transactionActor = createTypedTransactionActor(createTransaction,transactionId);
 
         getSender()
             .tell(new CreateTransactionReply(Serialization.serializedActorPath(transactionActor), createTransaction.getTransactionId()).toSerializable(),
@@ -257,7 +278,7 @@ public class Shard extends RaftActor {
         LOG.debug("registerDataChangeListener sending reply, listenerRegistrationPath = " + listenerRegistration.path().toString());
 
         getSender()
-            .tell(new RegisterChangeListenerReply(listenerRegistration.path()).toSerializable(),
+            .tell(new RegisterChangeListenerReply(listenerRegistration.path()),
                 getSelf());
     }
 
@@ -304,9 +325,25 @@ public class Shard extends RaftActor {
         for(ActorSelection dataChangeListener : dataChangeListeners){
             dataChangeListener.tell(new EnableNotification(isLeader()), getSelf());
         }
+
+        if(getLeaderId() != null){
+            shardMBean.setLeader(getLeaderId());
+        }
+
+        shardMBean.setRaftState(getRaftState().name());
     }
 
     @Override public String persistenceId() {
         return this.name;
     }
+
+
+    private static class ShardConfigParams extends DefaultConfigParamsImpl {
+        public static final FiniteDuration HEART_BEAT_INTERVAL =
+            new FiniteDuration(500, TimeUnit.MILLISECONDS);
+
+        @Override public FiniteDuration getHeartBeatInterval() {
+            return HEART_BEAT_INTERVAL;
+        }
+    }
 }
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadTransaction.java
new file mode 100644 (file)
index 0000000..f78935b
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *
+ *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ *  This program and the accompanying materials are made available under the
+ *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ *  and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ */
+
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.PoisonPill;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.ReadData;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * @author: syedbahm
+ * Date: 8/6/14
+ */
+public class ShardReadTransaction extends ShardTransaction {
+  private final DOMStoreReadTransaction transaction;
+  private final LoggingAdapter log =
+      Logging.getLogger(getContext().system(), this);
+
+  public ShardReadTransaction(DOMStoreReadTransaction transaction, ActorRef shardActor, SchemaContext schemaContext) {
+    super(shardActor, schemaContext);
+    this.transaction = transaction;
+
+  }
+
+  public ShardReadTransaction(DOMStoreTransactionChain transactionChain, DOMStoreReadTransaction transaction, ActorRef shardActor, SchemaContext schemaContext) {
+    super(transactionChain, shardActor, schemaContext);
+    this.transaction = transaction;
+  }
+
+  @Override
+  public void handleReceive(Object message) throws Exception {
+    if (ReadData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      readData(transaction,ReadData.fromSerializable(message));
+    } else {
+      super.handleReceive(message);
+    }
+  }
+  protected void closeTransaction(CloseTransaction message) {
+    transaction.close();
+    getSender().tell(new CloseTransactionReply().toSerializable(), getSelf());
+    getSelf().tell(PoisonPill.getInstance(), getSelf());
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadWriteTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadWriteTransaction.java
new file mode 100644 (file)
index 0000000..6733bcf
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *
+ *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ *  This program and the accompanying materials are made available under the
+ *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ *  and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ */
+
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.PoisonPill;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
+import org.opendaylight.controller.cluster.datastore.messages.MergeData;
+import org.opendaylight.controller.cluster.datastore.messages.ReadData;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.WriteData;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * @author: syedbahm
+ * Date: 8/6/14
+ */
+public class ShardReadWriteTransaction extends ShardTransaction {
+  private final DOMStoreReadWriteTransaction transaction;
+  private final LoggingAdapter log =
+      Logging.getLogger(getContext().system(), this);
+  public ShardReadWriteTransaction(DOMStoreTransactionChain transactionChain, DOMStoreReadWriteTransaction transaction, ActorRef shardActor, SchemaContext schemaContext) {
+    super(transactionChain,  shardActor, schemaContext);
+    this.transaction = transaction;
+  }
+
+  public ShardReadWriteTransaction(DOMStoreReadWriteTransaction transaction, ActorRef shardActor, SchemaContext schemaContext) {
+    super( shardActor, schemaContext);
+    this.transaction = transaction;
+  }
+
+  @Override
+  public void handleReceive(Object message) throws Exception {
+    if (ReadData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      readData(transaction,ReadData.fromSerializable(message));
+    }else if (WriteData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      writeData(transaction, WriteData.fromSerializable(message, schemaContext));
+    } else if (MergeData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      mergeData(transaction, MergeData.fromSerializable(message, schemaContext));
+    } else if (DeleteData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      deleteData(transaction,DeleteData.fromSerizalizable(message));
+    } else if (ReadyTransaction.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      readyTransaction(transaction,new ReadyTransaction());
+    }else {
+      super.handleReceive(message);
+    }
+  }
+
+  protected void closeTransaction(CloseTransaction message) {
+    transaction.close();
+    getSender().tell(new CloseTransactionReply().toSerializable(), getSelf());
+    getSelf().tell(PoisonPill.getInstance(), getSelf());
+  }
+}
index 737f57bf5d7314536f5fc20b1cbc45167f1b6e97..3a916bda2c6e163d75c4d39a0c4d80b94b823fb2 100644 (file)
@@ -9,7 +9,6 @@
 package org.opendaylight.controller.cluster.datastore;
 
 import akka.actor.ActorRef;
-import akka.actor.PoisonPill;
 import akka.actor.Props;
 import akka.event.Logging;
 import akka.event.LoggingAdapter;
@@ -17,7 +16,6 @@ import akka.japi.Creator;
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
-import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
 import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
 import org.opendaylight.controller.cluster.datastore.messages.DeleteDataReply;
 import org.opendaylight.controller.cluster.datastore.messages.MergeData;
@@ -34,9 +32,11 @@ import org.opendaylight.controller.cluster.datastore.modification.ImmutableCompo
 import org.opendaylight.controller.cluster.datastore.modification.MergeModification;
 import org.opendaylight.controller.cluster.datastore.modification.MutableCompositeModification;
 import org.opendaylight.controller.cluster.datastore.modification.WriteModification;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -65,170 +65,200 @@ import java.util.concurrent.ExecutionException;
  * <li> {@link org.opendaylight.controller.cluster.datastore.messages.CloseTransaction}
  * </p>
  */
-public class ShardTransaction extends AbstractUntypedActor {
-
-    private final ActorRef shardActor;
-    private final SchemaContext schemaContext;
-
-    // FIXME : see below
-    // If transactionChain is not null then this transaction is part of a
-    // transactionChain. Not really clear as to what that buys us
-    private final DOMStoreTransactionChain transactionChain;
-
-    private final DOMStoreReadWriteTransaction transaction;
-
-    private final MutableCompositeModification modification =
-        new MutableCompositeModification();
-
-    private final LoggingAdapter log =
-        Logging.getLogger(getContext().system(), this);
-
-    public ShardTransaction(DOMStoreReadWriteTransaction transaction,
-        ActorRef shardActor, SchemaContext schemaContext) {
-        this(null, transaction, shardActor, schemaContext);
-    }
-
-    public ShardTransaction(DOMStoreTransactionChain transactionChain, DOMStoreReadWriteTransaction transaction,
-        ActorRef shardActor, SchemaContext schemaContext) {
-        this.transactionChain = transactionChain;
-        this.transaction = transaction;
-        this.shardActor = shardActor;
-        this.schemaContext = schemaContext;
-    }
-
-
-
-    public static Props props(final DOMStoreReadWriteTransaction transaction,
-        final ActorRef shardActor, final SchemaContext schemaContext) {
-        return Props.create(new Creator<ShardTransaction>() {
-
-            @Override
-            public ShardTransaction create() throws Exception {
-                return new ShardTransaction(transaction, shardActor, schemaContext);
-            }
-        });
-    }
-
-    public static Props props(final DOMStoreTransactionChain transactionChain, final DOMStoreReadWriteTransaction transaction,
-        final ActorRef shardActor, final SchemaContext schemaContext) {
-        return Props.create(new Creator<ShardTransaction>() {
-
-            @Override
-            public ShardTransaction create() throws Exception {
-                return new ShardTransaction(transactionChain, transaction, shardActor, schemaContext);
-            }
-        });
+public abstract class ShardTransaction extends AbstractUntypedActor {
+
+  private final ActorRef shardActor;
+  protected final SchemaContext schemaContext;
+
+  // FIXME : see below
+  // If transactionChain is not null then this transaction is part of a
+  // transactionChain. Not really clear as to what that buys us
+  private final DOMStoreTransactionChain transactionChain;
+
+
+  private final MutableCompositeModification modification =
+      new MutableCompositeModification();
+
+  private final LoggingAdapter log =
+      Logging.getLogger(getContext().system(), this);
+
+  protected ShardTransaction(
+                          ActorRef shardActor, SchemaContext schemaContext) {
+    this(null,  shardActor, schemaContext);
+  }
+
+  protected ShardTransaction(DOMStoreTransactionChain transactionChain,
+                          ActorRef shardActor, SchemaContext schemaContext) {
+    this.transactionChain = transactionChain;
+    //this.transaction = transaction;
+    this.shardActor = shardActor;
+    this.schemaContext = schemaContext;
+  }
+
+
+
+  public static Props props(final DOMStoreReadTransaction transaction,
+                            final ActorRef shardActor, final SchemaContext schemaContext) {
+    return Props.create(new Creator<ShardTransaction>() {
+
+      @Override
+      public ShardTransaction create() throws Exception {
+        return new ShardReadTransaction(transaction, shardActor, schemaContext);
+      }
+    });
+  }
+
+  public static Props props(final DOMStoreTransactionChain transactionChain, final DOMStoreReadTransaction transaction,
+                            final ActorRef shardActor, final SchemaContext schemaContext) {
+    return Props.create(new Creator<ShardTransaction>() {
+
+      @Override
+      public ShardTransaction create() throws Exception {
+        return new ShardReadTransaction(transactionChain, transaction, shardActor, schemaContext);
+      }
+    });
+  }
+
+  public static Props props(final DOMStoreReadWriteTransaction transaction,
+                            final ActorRef shardActor, final SchemaContext schemaContext) {
+    return Props.create(new Creator<ShardTransaction>() {
+
+      @Override
+      public ShardTransaction create() throws Exception {
+        return new ShardReadWriteTransaction(transaction, shardActor, schemaContext);
+      }
+    });
+  }
+
+  public static Props props(final DOMStoreTransactionChain transactionChain, final DOMStoreReadWriteTransaction transaction,
+                            final ActorRef shardActor, final SchemaContext schemaContext) {
+    return Props.create(new Creator<ShardTransaction>() {
+
+      @Override
+      public ShardTransaction create() throws Exception {
+        return new ShardReadWriteTransaction(transactionChain, transaction, shardActor, schemaContext);
+      }
+    });
+  }
+
+
+  public static Props props(final DOMStoreWriteTransaction transaction,
+                            final ActorRef shardActor, final SchemaContext schemaContext) {
+    return Props.create(new Creator<ShardTransaction>() {
+
+      @Override
+      public ShardTransaction create() throws Exception {
+        return new ShardWriteTransaction(transaction, shardActor, schemaContext);
+      }
+    });
+  }
+
+  public static Props props(final DOMStoreTransactionChain transactionChain, final DOMStoreWriteTransaction transaction,
+                            final ActorRef shardActor, final SchemaContext schemaContext) {
+    return Props.create(new Creator<ShardTransaction>() {
+
+      @Override
+      public ShardTransaction create() throws Exception {
+        return new ShardWriteTransaction(transactionChain, transaction, shardActor, schemaContext);
+      }
+    });
+  }
+
+
+  @Override
+  public void handleReceive(Object message) throws Exception {
+     if (message.getClass().equals(CloseTransaction.SERIALIZABLE_CLASS)) {
+      closeTransaction(new CloseTransaction());
+    } else if (message instanceof GetCompositedModification) {
+      // This is here for testing only
+      getSender().tell(new GetCompositeModificationReply(
+          new ImmutableCompositeModification(modification)), getSelf());
+    }else{
+      throw new Exception ("ShardTransaction:handleRecieve received an unknown message"+message);
     }
-
-
-    @Override
-    public void handleReceive(Object message) throws Exception {
-        if (ReadData.SERIALIZABLE_CLASS.equals(message.getClass())) {
-            readData(ReadData.fromSerializable(message));
-        } else if (WriteData.SERIALIZABLE_CLASS.equals(message.getClass())) {
-            writeData(WriteData.fromSerializable(message, schemaContext));
-        } else if (MergeData.SERIALIZABLE_CLASS.equals(message.getClass())) {
-            mergeData(MergeData.fromSerializable(message, schemaContext));
-        } else if (DeleteData.SERIALIZABLE_CLASS.equals(message.getClass())) {
-            deleteData(DeleteData.fromSerizalizable(message));
-        } else if (ReadyTransaction.SERIALIZABLE_CLASS.equals(message.getClass())) {
-            readyTransaction(new ReadyTransaction());
-        } else if (message.getClass().equals(CloseTransaction.SERIALIZABLE_CLASS)) {
-            closeTransaction(new CloseTransaction());
-        } else if (message instanceof GetCompositedModification) {
-            // This is here for testing only
-            getSender().tell(new GetCompositeModificationReply(
-                new ImmutableCompositeModification(modification)), getSelf());
-        }else{
-          throw new Exception ("Shard:handleRecieve received an unknown message"+message);
+  }
+
+  abstract protected  void closeTransaction(CloseTransaction message);
+
+  protected void readData(DOMStoreReadTransaction transaction,ReadData message) {
+    final ActorRef sender = getSender();
+    final ActorRef self = getSelf();
+    final YangInstanceIdentifier path = message.getPath();
+    final ListenableFuture<Optional<NormalizedNode<?, ?>>> future =
+        transaction.read(path);
+
+    future.addListener(new Runnable() {
+      @Override
+      public void run() {
+        try {
+          Optional<NormalizedNode<?, ?>> optional = future.get();
+          if (optional.isPresent()) {
+            sender.tell(new ReadDataReply(schemaContext,optional.get()).toSerializable(), self);
+          } else {
+            sender.tell(new ReadDataReply(schemaContext,null).toSerializable(), self);
+          }
+        } catch (InterruptedException | ExecutionException e) {
+          log.error(e,
+              "An exception happened when reading data from path : "
+                  + path.toString());
         }
-    }
 
-    private void readData(ReadData message) {
-        final ActorRef sender = getSender();
-        final ActorRef self = getSelf();
-        final YangInstanceIdentifier path = message.getPath();
-        final ListenableFuture<Optional<NormalizedNode<?, ?>>> future =
-            transaction.read(path);
-
-        future.addListener(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    Optional<NormalizedNode<?, ?>> optional = future.get();
-                    if (optional.isPresent()) {
-                        sender.tell(new ReadDataReply(schemaContext,optional.get()).toSerializable(), self);
-                    } else {
-                        sender.tell(new ReadDataReply(schemaContext,null).toSerializable(), self);
-                    }
-                } catch (InterruptedException | ExecutionException e) {
-                    log.error(e,
-                        "An exception happened when reading data from path : "
-                            + path.toString());
-                }
-
-            }
-        }, getContext().dispatcher());
-    }
+      }
+    }, getContext().dispatcher());
+  }
 
 
-    private void writeData(WriteData message) {
-        modification.addModification(
-            new WriteModification(message.getPath(), message.getData(),schemaContext));
-        LOG.debug("writeData at path : " + message.getPath().toString());
-        transaction.write(message.getPath(), message.getData());
-        getSender().tell(new WriteDataReply().toSerializable(), getSelf());
-    }
+  protected void writeData(DOMStoreWriteTransaction transaction, WriteData message) {
+    modification.addModification(
+        new WriteModification(message.getPath(), message.getData(),schemaContext));
+    LOG.debug("writeData at path : " + message.getPath().toString());
+    transaction.write(message.getPath(), message.getData());
+    getSender().tell(new WriteDataReply().toSerializable(), getSelf());
+  }
 
-    private void mergeData(MergeData message) {
-        modification.addModification(
-            new MergeModification(message.getPath(), message.getData(), schemaContext));
-        LOG.debug("mergeData at path : " + message.getPath().toString());
-        transaction.merge(message.getPath(), message.getData());
-        getSender().tell(new MergeDataReply().toSerializable(), getSelf());
-    }
+  protected void mergeData(DOMStoreWriteTransaction transaction, MergeData message) {
+    modification.addModification(
+        new MergeModification(message.getPath(), message.getData(), schemaContext));
+    LOG.debug("mergeData at path : " + message.getPath().toString());
+    transaction.merge(message.getPath(), message.getData());
+    getSender().tell(new MergeDataReply().toSerializable(), getSelf());
+  }
 
-    private void deleteData(DeleteData message) {
-        modification.addModification(new DeleteModification(message.getPath()));
-        transaction.delete(message.getPath());
-        getSender().tell(new DeleteDataReply().toSerializable(), getSelf());
-    }
+  protected void deleteData(DOMStoreWriteTransaction transaction, DeleteData message) {
+    modification.addModification(new DeleteModification(message.getPath()));
+    transaction.delete(message.getPath());
+    getSender().tell(new DeleteDataReply().toSerializable(), getSelf());
+  }
 
-    private void readyTransaction(ReadyTransaction message) {
-        DOMStoreThreePhaseCommitCohort cohort = transaction.ready();
-        ActorRef cohortActor = getContext().actorOf(
-            ThreePhaseCommitCohort.props(cohort, shardActor, modification), "cohort");
-        getSender()
-            .tell(new ReadyTransactionReply(cohortActor.path()).toSerializable(), getSelf());
+  protected void readyTransaction(DOMStoreWriteTransaction transaction, ReadyTransaction message) {
+    DOMStoreThreePhaseCommitCohort cohort =  transaction.ready();
+    ActorRef cohortActor = getContext().actorOf(
+        ThreePhaseCommitCohort.props(cohort, shardActor, modification), "cohort");
+    getSender()
+        .tell(new ReadyTransactionReply(cohortActor.path()).toSerializable(), getSelf());
 
-    }
-
-    private void closeTransaction(CloseTransaction message) {
-        transaction.close();
-        getSender().tell(new CloseTransactionReply().toSerializable(), getSelf());
-        getSelf().tell(PoisonPill.getInstance(), getSelf());
-    }
+  }
 
 
-    // These classes are in here for test purposes only
+  // These classes are in here for test purposes only
 
 
-    static class GetCompositedModification {
+  static class GetCompositedModification {
 
-    }
+  }
 
 
-    static class GetCompositeModificationReply {
-        private final CompositeModification modification;
+  static class GetCompositeModificationReply {
+    private final CompositeModification modification;
 
 
-        GetCompositeModificationReply(CompositeModification modification) {
-            this.modification = modification;
-        }
+    GetCompositeModificationReply(CompositeModification modification) {
+      this.modification = modification;
+    }
 
 
-        public CompositeModification getModification() {
-            return modification;
-        }
+    public CompositeModification getModification() {
+      return modification;
     }
+  }
 }
index 50042411b17eeb0b0428963535008e8a777ca915..ce63f1107daafe31855c67c4eec4d676e94f384a 100644 (file)
@@ -15,7 +15,6 @@ import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionCh
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionChainReply;
 import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply;
-import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
@@ -45,11 +44,27 @@ public class ShardTransactionChain extends AbstractUntypedActor {
         }
     }
 
+  private ActorRef createTypedTransactionActor(CreateTransaction createTransaction,String transactionId){
+    if(createTransaction.getTransactionType()== TransactionProxy.TransactionType.READ_ONLY.ordinal()){
+      return getContext().actorOf(
+          ShardTransaction.props( chain.newReadOnlyTransaction(), getSelf(), schemaContext), transactionId);
+
+    }else if (createTransaction.getTransactionType()== TransactionProxy.TransactionType.READ_WRITE.ordinal()){
+      return getContext().actorOf(
+          ShardTransaction.props( chain.newReadWriteTransaction(), getSelf(), schemaContext), transactionId);
+
+
+    }else if (createTransaction.getTransactionType()== TransactionProxy.TransactionType.WRITE_ONLY.ordinal()){
+      return getContext().actorOf(
+          ShardTransaction.props( chain.newWriteOnlyTransaction(), getSelf(), schemaContext), transactionId);
+    }else{
+      throw new IllegalArgumentException ("CreateTransaction message has unidentified transaction type="+createTransaction.getTransactionType()) ;
+    }
+  }
+
     private void createTransaction(CreateTransaction createTransaction) {
-        DOMStoreReadWriteTransaction transaction =
-            chain.newReadWriteTransaction();
-        ActorRef transactionActor = getContext().actorOf(ShardTransaction
-            .props(chain, transaction, getContext().parent(), schemaContext), "shard-" + createTransaction.getTransactionId());
+
+        ActorRef transactionActor = createTypedTransactionActor(createTransaction, "shard-" + createTransaction.getTransactionId());
         getSender()
             .tell(new CreateTransactionReply(transactionActor.path().toString(),createTransaction.getTransactionId()).toSerializable(),
                 getSelf());
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardWriteTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardWriteTransaction.java
new file mode 100644 (file)
index 0000000..2a5429b
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *
+ *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ *  This program and the accompanying materials are made available under the
+ *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ *  and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ */
+
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.PoisonPill;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
+import org.opendaylight.controller.cluster.datastore.messages.MergeData;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.WriteData;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * @author: syedbahm
+ * Date: 8/6/14
+ */
+public class ShardWriteTransaction extends ShardTransaction {
+  private final DOMStoreWriteTransaction transaction;
+  private final LoggingAdapter log =
+      Logging.getLogger(getContext().system(), this);
+  public ShardWriteTransaction(DOMStoreWriteTransaction transaction, ActorRef shardActor, SchemaContext schemaContext) {
+    super( shardActor, schemaContext);
+    this.transaction = transaction;
+
+  }
+
+  public ShardWriteTransaction(DOMStoreTransactionChain transactionChain, DOMStoreWriteTransaction transaction, ActorRef shardActor, SchemaContext schemaContext) {
+    super(transactionChain, shardActor, schemaContext);
+    this.transaction = transaction;
+  }
+
+  @Override
+  public void handleReceive(Object message) throws Exception {
+    if (WriteData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      writeData(transaction, WriteData.fromSerializable(message, schemaContext));
+    } else if (MergeData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      mergeData(transaction, MergeData.fromSerializable(message, schemaContext));
+    } else if (DeleteData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      deleteData(transaction,DeleteData.fromSerizalizable(message));
+    } else if (ReadyTransaction.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      readyTransaction(transaction,new ReadyTransaction());
+    }else {
+      super.handleReceive(message);
+    }
+  }
+
+  protected void closeTransaction(CloseTransaction message) {
+    transaction.close();
+    getSender().tell(new CloseTransactionReply().toSerializable(), getSelf());
+    getSelf().tell(PoisonPill.getInstance(), getSelf());
+  }
+}
index 56220656ad2f53f578e4cccfde405578ab187e5e..915b13dd8bc234a6cbf898658b8e6479333b36c2 100644 (file)
@@ -76,7 +76,6 @@ public class ThreePhaseCommitCohortProxy implements
                             CanCommitTransactionReply reply =
                                     CanCommitTransactionReply.fromSerializable(response);
                             if (!reply.getCanCommit()) {
-                                System.out.println("**TOM - failed: false");
                                 return false;
                             }
                         }
index 333a8f8617040ab3540ba6be39f6848085236df4..fa98905a66968b111372d4b893ef35bef6e32bd4 100644 (file)
@@ -180,7 +180,7 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
 
         try {
             Object response = actorContext.executeShardOperation(shardName,
-                new CreateTransaction(identifier).toSerializable(),
+                new CreateTransaction(identifier,this.transactionType.ordinal() ).toSerializable(),
                 ActorContext.ASK_DURATION);
             if (response.getClass()
                 .equals(CreateTransactionReply.SERIALIZABLE_CLASS)) {
index 2da6aae85f619b517b5f1edcadfd1035b7ce5b9a..4eb6a8cef96319d0ca885112c3a0812ee06e5431 100644 (file)
@@ -9,6 +9,8 @@ public class ShardStats extends AbstractBaseMBean implements ShardStatsMBean {
   private  Long committedTransactionsCount;
   private Long journalMessagesCount;
   final private String shardName;
+  private String leader;
+  private String raftState;
 
   ShardStats(String shardName){
     this.shardName = shardName;
@@ -33,6 +35,13 @@ public class ShardStats extends AbstractBaseMBean implements ShardStatsMBean {
     return journalMessagesCount;
   }
 
+  @Override public String getLeader() {
+    return leader;
+  }
+
+  @Override public String getRaftState() {
+    return raftState;
+  }
 
   public Long incrementCommittedTransactionCount() {
     return committedTransactionsCount++;
@@ -49,6 +58,13 @@ public class ShardStats extends AbstractBaseMBean implements ShardStatsMBean {
 
   }
 
+  public void setLeader(String leader){
+    this.leader = leader;
+  }
+
+  public void setRaftState(String raftState){
+    this.raftState = raftState;
+  }
 
 
   @Override
index 795131fdbf6400f0b53c98f91d167bf31f45d493..b27ad86be987097b9bb9c37713a50116bfa5116e 100644 (file)
@@ -15,23 +15,28 @@ import org.opendaylight.controller.protobuff.messages.transaction.ShardTransacti
 public class CreateTransaction implements SerializableMessage {
   public static Class SERIALIZABLE_CLASS = ShardTransactionMessages.CreateTransaction.class;
   private final String transactionId;
+  private final int transactionType;
 
-  public CreateTransaction(String transactionId){
+  public CreateTransaction(String transactionId, int transactionType){
 
     this.transactionId = transactionId;
+    this.transactionType = transactionType;
   }
 
   public String getTransactionId() {
     return transactionId;
   }
 
+  public int getTransactionType() { return transactionType;}
+
   @Override
   public Object toSerializable() {
-    return  ShardTransactionMessages.CreateTransaction.newBuilder().setTransactionId(transactionId).build();
+    return  ShardTransactionMessages.CreateTransaction.newBuilder().setTransactionId(transactionId).setTransactionType(transactionType).build();
   }
 
   public static CreateTransaction fromSerializable(Object message){
-    return new CreateTransaction(((ShardTransactionMessages.CreateTransaction)message).getTransactionId());
+    ShardTransactionMessages.CreateTransaction createTransaction = (ShardTransactionMessages.CreateTransaction)message;
+    return new CreateTransaction(createTransaction.getTransactionId(),createTransaction.getTransactionType() );
   }
 
 }
index 6f4b65a6f3c2db45baf5e1a9928d36928e252733..fc7ebd94dd481c909ba6e4d65d205e41cbfdebbf 100644 (file)
@@ -11,6 +11,8 @@ package org.opendaylight.controller.cluster.datastore.shardstrategy;
 import org.opendaylight.controller.cluster.datastore.Configuration;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 
+import java.util.List;
+
 public class ModuleShardStrategy implements ShardStrategy {
 
     public static final String NAME = "module";
@@ -25,6 +27,11 @@ public class ModuleShardStrategy implements ShardStrategy {
     }
 
     @Override public String findShard(YangInstanceIdentifier path) {
-        return configuration.getShardNamesFromModuleName(moduleName).get(0);
+        List<String> shardNames =
+            configuration.getShardNamesFromModuleName(moduleName);
+        if(shardNames.size() == 0){
+            return DefaultShardStrategy.DEFAULT_SHARD;
+        }
+        return shardNames.get(0);
     }
 }
index 2df945edd5e9b9c16ed454e55859611afe8a66e0..9a05c381ea556aeccf10013952aab453282c3dba 100644 (file)
@@ -16,6 +16,9 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 public interface ShardStrategy {
   /**
    * Find the name of the shard in which the data pointed to by the specified path belongs in
+   * <p>
+   * Should return the name of the default shard DefaultShardStrategy.DEFAULT_SHARD
+   * if no matching shard was found
    *
    * @param path The location of the data in the logical tree
    * @return
index 039446baf3d8be6d4a7c4796f0b4d690d61df0dd..87a621f9d370fa21b4b8e6ea9df4ca5fb42e4c79 100644 (file)
@@ -26,7 +26,7 @@ public class DistributedConfigDataStoreProviderModule extends
     @Override
     public java.lang.AutoCloseable createInstance() {
         return DistributedDataStoreFactory
-            .createInstance("config", getSchemaServiceDependency());
+            .createInstance("config", getConfigSchemaServiceDependency());
     }
 
 }
index 1a06629bb7cbeaa1e5214e8206de2ef209a06bc4..6af2748a8fa3e27ac0644d8fd184f258fa3e859e 100644 (file)
@@ -26,7 +26,7 @@ public class DistributedOperationalDataStoreProviderModule extends
     @Override
     public java.lang.AutoCloseable createInstance() {
         return DistributedDataStoreFactory
-            .createInstance("operational", getSchemaServiceDependency());
+            .createInstance("operational", getOperationalSchemaServiceDependency());
     }
 
 }
index 76914c2c84f020268377b2a5d191cf831bb96f6d..daac89c4c8adaef39047034138a8318e639f54c8 100644 (file)
@@ -1,15 +1,60 @@
-ODLCluster{
 
-actor {
-        serializers {
-          java = "akka.serialization.JavaSerializer"
-          proto = "akka.remote.serialization.ProtobufSerializer"
-        }
+odl-cluster-data {
+  akka {
+    cluster {
+        roles = [
+          "member-1"
+        ]
+    }
+    actor {
+      provider = "akka.cluster.ClusterActorRefProvider"
+      serializers {
+                java = "akka.serialization.JavaSerializer"
+                proto = "akka.remote.serialization.ProtobufSerializer"
+              }
+
+              serialization-bindings {
+                  "com.google.protobuf.Message" = proto
+
+              }
+    }
+    remote {
+      log-remote-lifecycle-events = off
+      netty.tcp {
+        hostname = "127.0.0.1"
+        port = 2550
+           maximum-frame-size = 2097152
+           send-buffer-size = 52428800
+           receive-buffer-size = 52428800
+      }
+    }
 
-        serialization-bindings {
-            "com.google.protobuf.Message" = proto
+    cluster {
+      seed-nodes = ["akka.tcp://opendaylight-cluster-data@127.0.0.1:2550"]
 
-        }
+      auto-down-unreachable-after = 10s
     }
+  }
+}
+
+odl-cluster-rpc {
+  akka {
+    actor {
+      provider = "akka.cluster.ClusterActorRefProvider"
 
-}
\ No newline at end of file
+    }
+    remote {
+      log-remote-lifecycle-events = off
+      netty.tcp {
+        hostname = "127.0.0.1"
+        port = 2551
+      }
+    }
+
+    cluster {
+      seed-nodes = ["akka.tcp://opendaylight-cluster-rpc@127.0.0.1:2551"]
+
+      auto-down-unreachable-after = 10s
+    }
+  }
+}
index 05ef33f759009b480dd156dab49af8d7a3a674fd..e820703eeb5fa0e5e6806afc9145620716153ce4 100644 (file)
@@ -1,7 +1,7 @@
 modules = [
     {
         name = "inventory"
-        namespace = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test:people"
+        namespace = "urn:opendaylight:inventory"
         shard-strategy = "module"
     }
 ]
index 5d3758986c40fc8858005aad29cf74f85c9af857..6f355cbe63f612cda7e40a6f3c24e31c78e253fa 100644 (file)
@@ -40,7 +40,7 @@ module distributed-datastore-provider {
     augment "/config:modules/config:module/config:configuration" {
         case distributed-config-datastore-provider {
             when "/config:modules/config:module/config:type = 'distributed-config-datastore-provider'";
-            container schema-service {
+            container config-schema-service {
                           uses config:service-ref {
                                refine type {
                                       mandatory false;
@@ -55,7 +55,7 @@ module distributed-datastore-provider {
         augment "/config:modules/config:module/config:configuration" {
             case distributed-operational-datastore-provider {
                 when "/config:modules/config:module/config:type = 'distributed-operational-datastore-provider'";
-                container schema-service {
+                container operational-schema-service {
                               uses config:service-ref {
                                    refine type {
                                           mandatory false;
index 11ad559744a3923aebfbb07472771b98a4439ab0..6599bd8eeb0d0b0b54d9058086d836fb82aa214a 100644 (file)
@@ -12,6 +12,7 @@ import akka.actor.ActorPath;
 import akka.actor.ActorRef;
 import akka.actor.ActorSelection;
 import akka.actor.Props;
+import akka.event.Logging;
 import akka.testkit.JavaTestKit;
 import junit.framework.Assert;
 import org.junit.Test;
@@ -35,6 +36,8 @@ import scala.concurrent.duration.FiniteDuration;
 
 import java.util.Collections;
 
+import static junit.framework.Assert.assertEquals;
+
 public class BasicIntegrationTest extends AbstractActorTest {
 
     @Test
@@ -61,17 +64,24 @@ public class BasicIntegrationTest extends AbstractActorTest {
                         getRef());
 
 
-                    // Wait for Shard to become a Leader
-                    try {
-                        Thread.sleep(1000);
-                    } catch (InterruptedException e) {
-                        e.printStackTrace();
-                    }
+                    // Wait for a specific log message to show up
+                    final boolean result =
+                        new JavaTestKit.EventFilter<Boolean>(Logging.Info.class
+                        ) {
+                            protected Boolean run() {
+                                return true;
+                            }
+                        }.from(shard.path().toString())
+                            .message("Switching from state Candidate to Leader")
+                            .occurrences(1).exec();
+
+                    assertEquals(true, result);
+
                     // 1. Create a TransactionChain
                     shard.tell(new CreateTransactionChain().toSerializable(), getRef());
 
                     final ActorSelection transactionChain =
-                        new ExpectMsg<ActorSelection>("CreateTransactionChainReply") {
+                        new ExpectMsg<ActorSelection>(duration("1 seconds"), "CreateTransactionChainReply") {
                             protected ActorSelection match(Object in) {
                                 if (in.getClass().equals(CreateTransactionChainReply.SERIALIZABLE_CLASS)) {
                                     ActorPath transactionChainPath =
@@ -90,10 +100,10 @@ public class BasicIntegrationTest extends AbstractActorTest {
                     System.out.println("Successfully created transaction chain");
 
                     // 2. Create a Transaction on the TransactionChain
-                    transactionChain.tell(new CreateTransaction("txn-1").toSerializable(), getRef());
+                    transactionChain.tell(new CreateTransaction("txn-1", TransactionProxy.TransactionType.WRITE_ONLY.ordinal() ).toSerializable(), getRef());
 
                     final ActorSelection transaction =
-                        new ExpectMsg<ActorSelection>("CreateTransactionReply") {
+                        new ExpectMsg<ActorSelection>(duration("1 seconds"), "CreateTransactionReply") {
                             protected ActorSelection match(Object in) {
                                 if (CreateTransactionReply.SERIALIZABLE_CLASS.equals(in.getClass())) {
                                     CreateTransactionReply reply = CreateTransactionReply.fromSerializable(in);
@@ -115,7 +125,7 @@ public class BasicIntegrationTest extends AbstractActorTest {
                         ImmutableNodes.containerNode(TestModel.TEST_QNAME), TestModel.createTestContext()).toSerializable(),
                         getRef());
 
-                    Boolean writeDone = new ExpectMsg<Boolean>("WriteDataReply") {
+                    Boolean writeDone = new ExpectMsg<Boolean>(duration("1 seconds"), "WriteDataReply") {
                         protected Boolean match(Object in) {
                             if (in.getClass().equals(WriteDataReply.SERIALIZABLE_CLASS)) {
                                 return true;
@@ -134,7 +144,7 @@ public class BasicIntegrationTest extends AbstractActorTest {
                     transaction.tell(new ReadyTransaction().toSerializable(), getRef());
 
                     final ActorSelection cohort =
-                        new ExpectMsg<ActorSelection>("ReadyTransactionReply") {
+                        new ExpectMsg<ActorSelection>(duration("1 seconds"), "ReadyTransactionReply") {
                             protected ActorSelection match(Object in) {
                                 if (in.getClass().equals(ReadyTransactionReply.SERIALIZABLE_CLASS)) {
                                     ActorPath cohortPath =
@@ -157,7 +167,7 @@ public class BasicIntegrationTest extends AbstractActorTest {
                     cohort.tell(new PreCommitTransaction().toSerializable(), getRef());
 
                     Boolean preCommitDone =
-                        new ExpectMsg<Boolean>("PreCommitTransactionReply") {
+                        new ExpectMsg<Boolean>(duration("1 seconds"), "PreCommitTransactionReply") {
                             protected Boolean match(Object in) {
                                 if (in.getClass().equals(PreCommitTransactionReply.SERIALIZABLE_CLASS)) {
                                     return true;
index 8c1cbbbba07119884f804bd823fb7947cbcf389f..b2ee4a49fee1b40ee86730da0044f5f987b090a9 100644 (file)
@@ -94,7 +94,7 @@ public class DataChangeListenerProxyTest extends AbstractActorTest {
 
         Assert.assertEquals(1, listMessages.size());
 
-        Assert.assertTrue(listMessages.get(0).getClass().equals(DataChanged.SERIALIZABLE_CLASS));
+        Assert.assertTrue(listMessages.get(0).getClass().equals(DataChanged.class));
 
     }
 }
index 8413bac3a7b4e52ea5a3e718ea61775403787d53..920248521a297871f95c5312f1d34085900feced 100644 (file)
@@ -41,7 +41,7 @@ public class DataChangeListenerRegistrationTest extends AbstractActorTest {
 
           subject.tell(new CloseDataChangeListenerRegistration().toSerializable(), getRef());
 
-          final String out = new ExpectMsg<String>("match hint") {
+          final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
             // do not put code outside this method, will run afterwards
             protected String match(Object in) {
               if (in.getClass().equals(CloseDataChangeListenerRegistrationReply.SERIALIZABLE_CLASS)) {
index c4ec8b45fc2726cfda7911287b0c59b6b82f9edd..26ec583b3e058108f9cc18517f5f6909847f5cd6 100644 (file)
@@ -102,13 +102,13 @@ public class DataChangeListenerTest extends AbstractActorTest {
                     subject.tell(new EnableNotification(true), getRef());
 
                     subject.tell(
-                        new DataChanged(CompositeModel.createTestContext(),new MockDataChangedEvent()).toSerializable(),
+                        new DataChanged(CompositeModel.createTestContext(),new MockDataChangedEvent()),
                         getRef());
 
                     final Boolean out = new ExpectMsg<Boolean>(duration("800 millis"), "dataChanged") {
                         // do not put code outside this method, will run afterwards
                         protected Boolean match(Object in) {
-                            if (in != null && in.getClass().equals(DataChangedReply.SERIALIZABLE_CLASS)) {
+                            if (in != null && in.getClass().equals(DataChangedReply.class)) {
 
                                 return true;
                             } else {
@@ -141,7 +141,7 @@ public class DataChangeListenerTest extends AbstractActorTest {
                 protected void run() {
 
                     subject.tell(
-                        new DataChanged(CompositeModel.createTestContext(),new MockDataChangedEvent()).toSerializable(),
+                        new DataChanged(CompositeModel.createTestContext(),new MockDataChangedEvent()),
                         getRef());
 
                     expectNoMsg();
index 0a0c04b91586cbbda3d41dc24c4daca83ae78ae3..fc527b6bffe13726d89d5923cee71a6c471af055 100644 (file)
@@ -1,11 +1,12 @@
 package org.opendaylight.controller.cluster.datastore;
 
 import akka.actor.ActorSystem;
+import akka.event.Logging;
 import akka.testkit.JavaTestKit;
-
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.ListenableFuture;
 import junit.framework.Assert;
+import org.apache.commons.io.FileUtils;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -20,19 +21,29 @@ import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCoh
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 
+import java.io.File;
+import java.io.IOException;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
 
-public class DistributedDataStoreIntegrationTest{
+public class DistributedDataStoreIntegrationTest {
 
     private static ActorSystem system;
 
     @Before
-    public void setUp() {
+    public void setUp() throws IOException {
+        File journal = new File("journal");
+
+        if(journal.exists()) {
+            FileUtils.deleteDirectory(journal);
+        }
+
+
         System.setProperty("shard.persistent", "false");
         system = ActorSystem.create("test");
     }
@@ -49,82 +60,153 @@ public class DistributedDataStoreIntegrationTest{
 
     @Test
     public void integrationTest() throws Exception {
-        Configuration configuration = new ConfigurationImpl("module-shards.conf", "modules.conf");
+        final Configuration configuration = new ConfigurationImpl("module-shards.conf", "modules.conf");
         ShardStrategyFactory.setConfiguration(configuration);
-        DistributedDataStore distributedDataStore =
-            new DistributedDataStore(getSystem(), "config", new MockClusterWrapper(), configuration);
 
-        distributedDataStore.onGlobalContextUpdated(TestModel.createTestContext());
 
-        Thread.sleep(1500);
 
-        DOMStoreReadWriteTransaction transaction =
-            distributedDataStore.newReadWriteTransaction();
+        new JavaTestKit(getSystem()) {
+            {
+
+                new Within(duration("10 seconds")) {
+                    protected void run() {
+                        try {
+                            final DistributedDataStore distributedDataStore =
+                                new DistributedDataStore(getSystem(), "config", new MockClusterWrapper(), configuration);
+
+                            distributedDataStore.onGlobalContextUpdated(TestModel.createTestContext());
+
+                            // Wait for a specific log message to show up
+                            final boolean result =
+                                new JavaTestKit.EventFilter<Boolean>(Logging.Info.class
+                                    ) {
+                                    protected Boolean run() {
+                                        return true;
+                                    }
+                                }.from("akka://test/user/shardmanager-config/member-1-shard-test-1-config")
+                                    .message("Switching from state Candidate to Leader")
+                                    .occurrences(1).exec();
+
+                            assertEquals(true, result);
+
+                            DOMStoreReadWriteTransaction transaction =
+                                distributedDataStore.newReadWriteTransaction();
 
-        transaction.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
+                            transaction
+                                .write(TestModel.TEST_PATH, ImmutableNodes
+                                    .containerNode(TestModel.TEST_QNAME));
 
-        ListenableFuture<Optional<NormalizedNode<?, ?>>> future =
-            transaction.read(TestModel.TEST_PATH);
+                            ListenableFuture<Optional<NormalizedNode<?, ?>>>
+                                future =
+                                transaction.read(TestModel.TEST_PATH);
 
-        Optional<NormalizedNode<?, ?>> optional = future.get();
+                            Optional<NormalizedNode<?, ?>> optional =
+                                future.get();
 
-        Assert.assertTrue(optional.isPresent());
+                            Assert.assertTrue("Node not found", optional.isPresent());
 
-        NormalizedNode<?, ?> normalizedNode = optional.get();
+                            NormalizedNode<?, ?> normalizedNode =
+                                optional.get();
 
-        assertEquals(TestModel.TEST_QNAME, normalizedNode.getNodeType());
+                            assertEquals(TestModel.TEST_QNAME,
+                                normalizedNode.getNodeType());
 
-        DOMStoreThreePhaseCommitCohort ready = transaction.ready();
+                            DOMStoreThreePhaseCommitCohort ready =
+                                transaction.ready();
 
-        ListenableFuture<Boolean> canCommit = ready.canCommit();
+                            ListenableFuture<Boolean> canCommit =
+                                ready.canCommit();
 
-        assertTrue(canCommit.get(5, TimeUnit.SECONDS));
+                            assertTrue(canCommit.get(5, TimeUnit.SECONDS));
 
-        ListenableFuture<Void> preCommit = ready.preCommit();
+                            ListenableFuture<Void> preCommit =
+                                ready.preCommit();
 
-        preCommit.get(5, TimeUnit.SECONDS);
+                            preCommit.get(5, TimeUnit.SECONDS);
 
-        ListenableFuture<Void> commit = ready.commit();
+                            ListenableFuture<Void> commit = ready.commit();
+
+                            commit.get(5, TimeUnit.SECONDS);
+                        } catch (ExecutionException | TimeoutException | InterruptedException e){
+                            fail(e.getMessage());
+                        }
+                    }
+                };
+            }
+        };
 
-        commit.get(5, TimeUnit.SECONDS);
     }
 
 
-    @Test
+    //FIXME : Disabling test because it's flaky
+    //@Test
     public void integrationTestWithMultiShardConfiguration()
         throws ExecutionException, InterruptedException, TimeoutException {
-        Configuration configuration = new ConfigurationImpl("module-shards.conf", "modules.conf");
+        final Configuration configuration = new ConfigurationImpl("module-shards.conf", "modules.conf");
 
         ShardStrategyFactory.setConfiguration(configuration);
-        DistributedDataStore distributedDataStore =
-            new DistributedDataStore(getSystem(), "config", new MockClusterWrapper(), configuration);
 
+        new JavaTestKit(getSystem()) {
+            {
+
+                new Within(duration("10 seconds")) {
+                    protected void run() {
+                        try {
+                            final DistributedDataStore distributedDataStore =
+                                new DistributedDataStore(getSystem(), "config",
+                                    new MockClusterWrapper(), configuration);
+
+                            distributedDataStore.onGlobalContextUpdated(
+                                SchemaContextHelper.full());
+
+                            // Wait for a specific log message to show up
+                            final boolean result =
+                                new JavaTestKit.EventFilter<Boolean>(
+                                    Logging.Info.class
+                                ) {
+                                    protected Boolean run() {
+                                        return true;
+                                    }
+                                }.from(
+                                    "akka://test/user/shardmanager-config/member-1-shard-cars-1-config")
+                                    .message(
+                                        "Switching from state Candidate to Leader")
+                                    .occurrences(1)
+                                    .exec();
+
+                            Thread.sleep(1000);
+
+
+                            DOMStoreReadWriteTransaction transaction =
+                                distributedDataStore.newReadWriteTransaction();
 
-        distributedDataStore.onGlobalContextUpdated(SchemaContextHelper.full());
+                            transaction.write(CarsModel.BASE_PATH, CarsModel.emptyContainer());
+                            transaction.write(PeopleModel.BASE_PATH, PeopleModel.emptyContainer());
 
-        // This sleep is fragile - test can fail intermittently if all Shards aren't updated with
-        // the SchemaContext in time. Is there any way we can make this deterministic?
-        Thread.sleep(2000);
+                            DOMStoreThreePhaseCommitCohort ready = transaction.ready();
 
-        DOMStoreReadWriteTransaction transaction =
-            distributedDataStore.newReadWriteTransaction();
+                            ListenableFuture<Boolean> canCommit = ready.canCommit();
 
-        transaction.write(CarsModel.BASE_PATH, CarsModel.emptyContainer());
-        transaction.write(PeopleModel.BASE_PATH, PeopleModel.emptyContainer());
+                            assertTrue(canCommit.get(5, TimeUnit.SECONDS));
 
-        DOMStoreThreePhaseCommitCohort ready = transaction.ready();
+                            ListenableFuture<Void> preCommit = ready.preCommit();
 
-        ListenableFuture<Boolean> canCommit = ready.canCommit();
+                            preCommit.get(5, TimeUnit.SECONDS);
 
-        assertTrue(canCommit.get(5, TimeUnit.SECONDS));
+                            ListenableFuture<Void> commit = ready.commit();
 
-        ListenableFuture<Void> preCommit = ready.preCommit();
+                            commit.get(5, TimeUnit.SECONDS);
 
-        preCommit.get(5, TimeUnit.SECONDS);
+                            assertEquals(true, result);
+                        } catch(ExecutionException | TimeoutException | InterruptedException e){
+                            fail(e.getMessage());
+                        }
+                    }
+                };
+            }
+        };
 
-        ListenableFuture<Void> commit = ready.commit();
 
-        commit.get(5, TimeUnit.SECONDS);
     }
 
 }
index 03191f70f1ab5979d8bcc6189b2ddece6616c867..d1beab904984262cd1f83de56a039c5970dc0742 100644 (file)
@@ -73,7 +73,7 @@ public class DistributedDataStoreTest extends AbstractActorTest{
     @org.junit.Test
     public void testRegisterChangeListenerWhenShardIsLocal() throws Exception {
 
-        mockActorContext.setExecuteLocalShardOperationResponse(new RegisterChangeListenerReply(doNothingActorRef.path()).toSerializable());
+        mockActorContext.setExecuteLocalShardOperationResponse(new RegisterChangeListenerReply(doNothingActorRef.path()));
 
         ListenerRegistration registration =
             distributedDataStore.registerChangeListener(TestModel.TEST_PATH, new AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>() {
index 268ed3c27383f3254eafec08e74c8f287456456a..e9ad450ed86614ff78114ff4bb545e23ab82367f 100644 (file)
@@ -75,7 +75,7 @@ public class ShardManagerTest {
 
                     subject.tell(new FindPrimary(Shard.DEFAULT_NAME).toSerializable(), getRef());
 
-                    expectMsgClass(PrimaryFound.SERIALIZABLE_CLASS);
+                    expectMsgClass(duration("1 seconds"), PrimaryFound.SERIALIZABLE_CLASS);
 
                     expectNoMsg();
                 }
@@ -170,7 +170,7 @@ public class ShardManagerTest {
 
                     subject.tell(new FindPrimary("astronauts").toSerializable(), getRef());
 
-                    final String out = new ExpectMsg<String>("primary found") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "primary found") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in.getClass().equals(PrimaryFound.SERIALIZABLE_CLASS)) {
@@ -208,13 +208,13 @@ public class ShardManagerTest {
 
                     subject.tell(new FindPrimary("astronauts").toSerializable(), getRef());
 
-                    expectMsgClass(PrimaryFound.SERIALIZABLE_CLASS);
+                    expectMsgClass(duration("1 seconds"), PrimaryFound.SERIALIZABLE_CLASS);
 
                     MockClusterWrapper.sendMemberRemoved(subject, "member-2", getRef().path().toString());
 
                     subject.tell(new FindPrimary("astronauts").toSerializable(), getRef());
 
-                    expectMsgClass(PrimaryNotFound.SERIALIZABLE_CLASS);
+                    expectMsgClass(duration("1 seconds"), PrimaryNotFound.SERIALIZABLE_CLASS);
 
                     expectNoMsg();
                 }
index 38920d86ca36b8889276b6f9823381d0cc1a4239..431a266b148478a49766bd8f0cc173bc7b2e4062 100644 (file)
@@ -2,7 +2,9 @@ package org.opendaylight.controller.cluster.datastore;
 
 import akka.actor.ActorRef;
 import akka.actor.Props;
+import akka.event.Logging;
 import akka.testkit.JavaTestKit;
+import junit.framework.Assert;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionChain;
@@ -38,19 +40,25 @@ public class ShardTest extends AbstractActorTest {
                 getSystem().actorOf(props, "testCreateTransactionChain");
 
 
-            // Wait for Shard to become a Leader
-            try {
-                Thread.sleep(1000);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-            }
+            // Wait for a specific log message to show up
+            final boolean result =
+                new JavaTestKit.EventFilter<Boolean>(Logging.Info.class
+                ) {
+                    protected Boolean run() {
+                        return true;
+                    }
+                }.from(subject.path().toString())
+                    .message("Switching from state Candidate to Leader")
+                    .occurrences(1).exec();
+
+            Assert.assertEquals(true, result);
 
             new Within(duration("1 seconds")) {
                 protected void run() {
 
                     subject.tell(new CreateTransactionChain().toSerializable(), getRef());
 
-                    final String out = new ExpectMsg<String>("match hint") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in.getClass().equals(CreateTransactionChainReply.SERIALIZABLE_CLASS)){
@@ -91,7 +99,7 @@ public class ShardTest extends AbstractActorTest {
                         getRef());
 
                     subject.tell(new RegisterChangeListener(TestModel.TEST_PATH,
-                        getRef().path(), AsyncDataBroker.DataChangeScope.BASE).toSerializable(),
+                        getRef().path(), AsyncDataBroker.DataChangeScope.BASE),
                         getRef());
 
                     final Boolean notificationEnabled = new ExpectMsg<Boolean>("enable notification") {
@@ -107,12 +115,12 @@ public class ShardTest extends AbstractActorTest {
 
                     assertFalse(notificationEnabled);
 
-                    final String out = new ExpectMsg<String>("match hint") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
-                            if (in.getClass().equals(RegisterChangeListenerReply.SERIALIZABLE_CLASS)) {
+                            if (in.getClass().equals(RegisterChangeListenerReply.class)) {
                                 RegisterChangeListenerReply reply =
-                                    RegisterChangeListenerReply.fromSerializable(getSystem(),in);
+                                    (RegisterChangeListenerReply) in;
                                 return reply.getListenerRegistrationPath()
                                     .toString();
                             } else {
@@ -138,13 +146,18 @@ public class ShardTest extends AbstractActorTest {
                 getSystem().actorOf(props, "testCreateTransaction");
 
 
-            // Wait for Shard to become a Leader
-            try {
-                Thread.sleep(1000);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-            }
+            // Wait for a specific log message to show up
+            final boolean result =
+                new JavaTestKit.EventFilter<Boolean>(Logging.Info.class
+                ) {
+                    protected Boolean run() {
+                        return true;
+                    }
+                }.from(subject.path().toString())
+                    .message("Switching from state Candidate to Leader")
+                    .occurrences(1).exec();
 
+            Assert.assertEquals(true, result);
 
             new Within(duration("1 seconds")) {
                 protected void run() {
@@ -153,10 +166,10 @@ public class ShardTest extends AbstractActorTest {
                         new UpdateSchemaContext(TestModel.createTestContext()),
                         getRef());
 
-                    subject.tell(new CreateTransaction("txn-1").toSerializable(),
+                    subject.tell(new CreateTransaction("txn-1", TransactionProxy.TransactionType.READ_ONLY.ordinal() ).toSerializable(),
                         getRef());
 
-                    final String out = new ExpectMsg<String>("match hint") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in instanceof CreateTransactionReply) {
index 6330ad8acca33ab6c05f3263aa45ca459f0c283d..b35880a6a501367a4c1155b3cae4ef405352ddb6 100644 (file)
@@ -33,9 +33,9 @@ public class ShardTransactionChainTest extends AbstractActorTest {
      new Within(duration("1 seconds")) {
         protected void run() {
 
-          subject.tell(new CreateTransaction("txn-1").toSerializable(), getRef());
+          subject.tell(new CreateTransaction("txn-1", TransactionProxy.TransactionType.READ_ONLY.ordinal() ).toSerializable(), getRef());
 
-          final String out = new ExpectMsg<String>("match hint") {
+          final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
             // do not put code outside this method, will run afterwards
             protected String match(Object in) {
               if (in.getClass().equals(CreateTransactionReply.SERIALIZABLE_CLASS)) {
@@ -70,7 +70,7 @@ public class ShardTransactionChainTest extends AbstractActorTest {
 
           subject.tell(new CloseTransactionChain().toSerializable(), getRef());
 
-          final String out = new ExpectMsg<String>("match hint") {
+          final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
             // do not put code outside this method, will run afterwards
             protected String match(Object in) {
               if (in.getClass().equals(CloseTransactionChainReply.SERIALIZABLE_CLASS)) {
index 7884eeccdae7874f8d19c9090bf08d755cc991be..632ecc29cd31b727f714be859154a53182ade178 100644 (file)
@@ -4,8 +4,10 @@ import akka.actor.ActorRef;
 import akka.actor.Props;
 import akka.actor.Terminated;
 import akka.testkit.JavaTestKit;
+import akka.testkit.TestActorRef;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
+import org.junit.Assert;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
@@ -53,7 +55,7 @@ public class ShardTransactionTest extends AbstractActorTest {
         new JavaTestKit(getSystem()) {{
             final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
             final Props props =
-                ShardTransaction.props(store.newReadWriteTransaction(), shard, testSchemaContext);
+                ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
             final ActorRef subject = getSystem().actorOf(props, "testReadData");
 
             new Within(duration("1 seconds")) {
@@ -63,7 +65,7 @@ public class ShardTransactionTest extends AbstractActorTest {
                         new ReadData(YangInstanceIdentifier.builder().build()).toSerializable(),
                         getRef());
 
-                    final String out = new ExpectMsg<String>("match hint") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)) {
@@ -93,7 +95,7 @@ public class ShardTransactionTest extends AbstractActorTest {
         new JavaTestKit(getSystem()) {{
             final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
             final Props props =
-                ShardTransaction.props(store.newReadWriteTransaction(), shard, testSchemaContext);
+                ShardTransaction.props( store.newReadOnlyTransaction(), shard, testSchemaContext);
             final ActorRef subject = getSystem().actorOf(props, "testReadDataWhenDataNotFound");
 
             new Within(duration("1 seconds")) {
@@ -103,7 +105,7 @@ public class ShardTransactionTest extends AbstractActorTest {
                         new ReadData(TestModel.TEST_PATH).toSerializable(),
                         getRef());
 
-                    final String out = new ExpectMsg<String>("match hint") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)) {
@@ -139,7 +141,7 @@ public class ShardTransactionTest extends AbstractActorTest {
                             getRef());
 
                     final CompositeModification compositeModification =
-                        new ExpectMsg<CompositeModification>("match hint") {
+                        new ExpectMsg<CompositeModification>(duration("1 seconds"), "match hint") {
                             // do not put code outside this method, will run afterwards
                             protected CompositeModification match(Object in) {
                                 if (in instanceof ShardTransaction.GetCompositeModificationReply) {
@@ -167,7 +169,7 @@ public class ShardTransactionTest extends AbstractActorTest {
         new JavaTestKit(getSystem()) {{
             final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
             final Props props =
-                ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
+                ShardTransaction.props(store.newWriteOnlyTransaction(), shard, TestModel.createTestContext());
             final ActorRef subject =
                 getSystem().actorOf(props, "testWriteData");
 
@@ -178,7 +180,7 @@ public class ShardTransactionTest extends AbstractActorTest {
                         ImmutableNodes.containerNode(TestModel.TEST_QNAME), TestModel.createTestContext()).toSerializable(),
                         getRef());
 
-                    final String out = new ExpectMsg<String>("match hint") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in.getClass().equals(WriteDataReply.SERIALIZABLE_CLASS)) {
@@ -244,7 +246,7 @@ public class ShardTransactionTest extends AbstractActorTest {
         new JavaTestKit(getSystem()) {{
             final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
             final Props props =
-                ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
+                ShardTransaction.props( store.newWriteOnlyTransaction(), shard, TestModel.createTestContext());
             final ActorRef subject =
                 getSystem().actorOf(props, "testDeleteData");
 
@@ -253,7 +255,7 @@ public class ShardTransactionTest extends AbstractActorTest {
 
                     subject.tell(new DeleteData(TestModel.TEST_PATH).toSerializable(), getRef());
 
-                    final String out = new ExpectMsg<String>("match hint") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in.getClass().equals(DeleteDataReply.SERIALIZABLE_CLASS)) {
@@ -281,7 +283,7 @@ public class ShardTransactionTest extends AbstractActorTest {
         new JavaTestKit(getSystem()) {{
             final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
             final Props props =
-                ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
+                ShardTransaction.props( store.newReadWriteTransaction(), shard, TestModel.createTestContext());
             final ActorRef subject =
                 getSystem().actorOf(props, "testReadyTransaction");
 
@@ -290,7 +292,7 @@ public class ShardTransactionTest extends AbstractActorTest {
 
                     subject.tell(new ReadyTransaction().toSerializable(), getRef());
 
-                    final String out = new ExpectMsg<String>("match hint") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in.getClass().equals(ReadyTransactionReply.SERIALIZABLE_CLASS)) {
@@ -328,7 +330,7 @@ public class ShardTransactionTest extends AbstractActorTest {
 
                     subject.tell(new CloseTransaction().toSerializable(), getRef());
 
-                    final String out = new ExpectMsg<String>("match hint") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in.getClass().equals(CloseTransactionReply.SERIALIZABLE_CLASS)) {
@@ -341,7 +343,7 @@ public class ShardTransactionTest extends AbstractActorTest {
 
                     assertEquals("match", out);
 
-                    final String termination = new ExpectMsg<String>("match hint") {
+                    final String termination = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in instanceof Terminated) {
@@ -361,4 +363,24 @@ public class ShardTransactionTest extends AbstractActorTest {
         }};
 
     }
+
+
+  @Test
+  public void testNegativePerformingWriteOperationOnReadTransaction() throws Exception {
+    try {
+
+        final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
+        final Props props =
+            ShardTransaction.props(store.newReadOnlyTransaction(), shard, TestModel.createTestContext());
+         final TestActorRef subject = TestActorRef.apply(props,getSystem());
+
+        subject.receive(new DeleteData(TestModel.TEST_PATH).toSerializable(), ActorRef.noSender());
+        Assert.assertFalse(true);
+
+
+    } catch (Exception cs) {
+      assertEquals(cs.getClass().getSimpleName(), Exception.class.getSimpleName());
+      assertTrue(cs.getMessage().startsWith("ShardTransaction:handleRecieve received an unknown message"));
+    }
+  }
 }
index 88753e4b0a56165ed6cba8e2433f9bbc0089e8dc..3394cdc959757e167cb71988cf3d8e208fde041d 100644 (file)
@@ -1,6 +1,5 @@
 package org.opendaylight.controller.cluster.datastore.shardstrategy;
 
-import junit.framework.Assert;
 import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
@@ -8,6 +7,10 @@ import org.junit.rules.ExpectedException;
 import org.opendaylight.controller.cluster.datastore.Configuration;
 import org.opendaylight.controller.cluster.datastore.ConfigurationImpl;
 import org.opendaylight.controller.md.cluster.datastore.model.CarsModel;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import static junit.framework.Assert.assertEquals;
 
 public class ModuleShardStrategyTest {
     @Rule
@@ -28,6 +31,23 @@ public class ModuleShardStrategyTest {
 
         String shard = moduleShardStrategy.findShard(CarsModel.BASE_PATH);
 
-        Assert.assertEquals("cars-1", shard);
+        assertEquals("cars-1", shard);
+    }
+
+    @Test
+    public void testFindShardWhenModuleConfigurationPresentInModulesButMissingInModuleShards() {
+
+        final QName BASE_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test:missing", "2014-03-13",
+            "missing");
+
+        final YangInstanceIdentifier BASE_PATH = YangInstanceIdentifier.of(BASE_QNAME);
+
+        ModuleShardStrategy moduleShardStrategy =
+            new ModuleShardStrategy("missing", configuration);
+
+        String shard = moduleShardStrategy.findShard(BASE_PATH);
+
+        assertEquals(DefaultShardStrategy.DEFAULT_SHARD, shard);
+
     }
 }
index aebff27c7dc0345864bfb8ecff9f5b30789ecf24..eda1c304e42bcac73e3e8597a3028324732e223e 100644 (file)
@@ -1,4 +1,5 @@
 akka {
+    loggers = [akka.testkit.TestEventListener]
     actor {
          serializers {
                   java = "akka.serialization.JavaSerializer"
index 22854cb11a968bd66f1b969d95a5cc07da7941de..f4919e7895a88d48840365effc16b4d55c6deda6 100644 (file)
@@ -15,4 +15,10 @@ modules = [
      shard-strategy = "module"
     }
 
+    {
+     name = "missing"
+     namespace = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:missing"
+     shard-strategy = "module"
+    }
+
 ]
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcImplementationUnavailableException.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcImplementationUnavailableException.java
new file mode 100644 (file)
index 0000000..3710822
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.core.api;
+
+/**
+ * Exception reported when no RPC implementation is found in the system.
+ */
+public class RpcImplementationUnavailableException extends RuntimeException {
+    private static final long serialVersionUID = 1L;
+
+    public RpcImplementationUnavailableException(final String message) {
+        super(message);
+    }
+
+    public RpcImplementationUnavailableException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+}
index 667c0fc2826a100b2fc6ae77f4c0344a52d723f6..22dad6af23c1464b63f8a4aa25075551b64ef686 100644 (file)
@@ -10,9 +10,11 @@ package org.opendaylight.controller.config.yang.md.sal.dom.impl;
 import java.util.concurrent.Executors;
 
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitDeadlockException;
 import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
+import org.opendaylight.yangtools.util.concurrent.DeadlockDetectingListeningExecutorService;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.util.concurrent.ListeningExecutorService;
@@ -64,7 +66,9 @@ public final class DomInmemoryDataBrokerModule extends
                 .<LogicalDatastoreType, DOMStore> builder().put(LogicalDatastoreType.OPERATIONAL, operStore)
                 .put(LogicalDatastoreType.CONFIGURATION, configStore).build();
 
-        DOMDataBrokerImpl newDataBroker = new DOMDataBrokerImpl(datastores, MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()));
+        DOMDataBrokerImpl newDataBroker = new DOMDataBrokerImpl(datastores,
+                new DeadlockDetectingListeningExecutorService(Executors.newSingleThreadExecutor(),
+                                              TransactionCommitDeadlockException.DEADLOCK_EXECUTOR_FUNCTION));
 
         return newDataBroker;
     }
index 41650666cd80c022931a7877b2d9fd9bbbd6a708..8944e197cc7338b717f8658f71177d41dc2dc10d 100644 (file)
@@ -21,7 +21,7 @@ import org.opendaylight.controller.md.sal.dom.broker.spi.mount.SimpleDOMMountPoi
 import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.ObjectRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
index b01db3d515d23af89cbd062865863f5d28ff1a9d..fef2a808c318dc4ceed1375e4c4935d3805f7456 100644 (file)
@@ -18,7 +18,7 @@ import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
 import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener;
 import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 
 public class BackwardsCompatibleMountPointManager implements MountProvisionService, MountProvisionListener {
index f0dd5b921c7624ae985adc5cdf15bcc9546813fa..df4549f1f8ec34c7aa5b707b4a58b42701166f4e 100644 (file)
@@ -11,7 +11,7 @@ import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataTransaction;
 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 
index d84f1dc03105389b81f9a8c239c5b33d7fcf3c6c..434cf85becb4f311c78a90a8b4745adc17769eb2 100644 (file)
@@ -17,7 +17,7 @@ import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
 import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener;
 import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 
 @Deprecated
index 19ff03b7d2ca14fa4facb72d855bbf2b14f77b7d..c8e3c0b6e0ca535e4e10ab464c47c2f00c8f220a 100644 (file)
@@ -8,7 +8,9 @@
 package org.opendaylight.controller.sal.dom.broker.impl;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.ListenableFuture;
 
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
@@ -22,11 +24,8 @@ import org.opendaylight.yangtools.concepts.Identifiable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 
 class RoutedRpcSelector implements RpcImplementation, AutoCloseable, Identifiable<RpcRoutingContext> {
 
@@ -81,9 +80,9 @@ class RoutedRpcSelector implements RpcImplementation, AutoCloseable, Identifiabl
         }
         if (potential == null) {
             return router.invokeRpc(rpc, (YangInstanceIdentifier) route, input);
+        } else {
+            return potential.invokeRpc(rpc, input);
         }
-        checkState(potential != null, "No implementation is available for rpc:%s path:%s", rpc, route);
-        return potential.invokeRpc(rpc, input);
     }
 
     public void addPath(final QName context, final YangInstanceIdentifier path, final RoutedRpcRegImpl routedRpcRegImpl) {
index 44e7abc3aa117fcb778d56f7b1423f5bd07c2649..b4d7d2d00109b394f36c1ef138176da4fda364ab 100644 (file)
@@ -10,6 +10,13 @@ package org.opendaylight.controller.sal.dom.broker.impl;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
 
+import com.google.common.base.Preconditions;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
@@ -22,12 +29,13 @@ import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
 import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
 import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
 import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcImplementationUnavailableException;
 import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
 import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
 import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter;
 import org.opendaylight.yangtools.concepts.Identifiable;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
@@ -38,12 +46,9 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Preconditions;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.util.concurrent.ListenableFuture;
-
+/**
+ * RPC broker responsible for routing requests to remote systems.
+ */
 public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, RoutedRpcDefaultImplementation {
 
     private static final Logger LOG = LoggerFactory.getLogger(SchemaAwareRpcBroker.class);
@@ -217,8 +222,12 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
 
     @Override
     public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final YangInstanceIdentifier route, final CompositeNode input) {
-      checkState(defaultDelegate != null, "No implementation is available for rpc:%s path:%s", rpc, route);
-      return defaultDelegate.invokeRpc(rpc, route, input);
+        if (defaultDelegate == null) {
+            return Futures.immediateFailedCheckedFuture(new RpcImplementationUnavailableException("No RPC implementation found"));
+        }
+
+        LOG.debug("Forwarding RPC {} path {} to delegate {}", rpc, route);
+        return defaultDelegate.invokeRpc(rpc, route, input);
     }
 
     void remove(final GlobalRpcRegistration registration) {
index b006ca94e5d1387bfd84e7a76eccba3700756905..0bb16a39b90f7eb513093b18faa20815061fad3c 100644 (file)
@@ -3,26 +3,40 @@ package org.opendaylight.controller.md.sal.dom.broker.impl;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
 
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitDeadlockException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
 import org.opendaylight.controller.md.sal.dom.store.impl.TestModel;
 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
+import org.opendaylight.yangtools.util.concurrent.DeadlockDetectingListeningExecutorService;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
@@ -31,6 +45,7 @@ public class DOMBrokerTest {
 
     private SchemaContext schemaContext;
     private DOMDataBrokerImpl domBroker;
+    private ListeningExecutorService executor;
 
     @Before
     public void setupStore() {
@@ -46,11 +61,19 @@ public class DOMBrokerTest {
                 .put(OPERATIONAL, operStore) //
                 .build();
 
-        ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
+        executor = new DeadlockDetectingListeningExecutorService(Executors.newSingleThreadExecutor(),
+                                          TransactionCommitDeadlockException.DEADLOCK_EXECUTOR_FUNCTION);
         domBroker = new DOMDataBrokerImpl(stores, executor);
     }
 
-    @Test
+    @After
+    public void tearDown() {
+        if( executor != null ) {
+            executor.shutdownNow();
+        }
+    }
+
+    @Test(timeout=10000)
     public void testTransactionIsolation() throws InterruptedException, ExecutionException {
 
         assertNotNull(domBroker);
@@ -86,7 +109,7 @@ public class DOMBrokerTest {
         assertFalse(readTxContainer.get().isPresent());
     }
 
-    @Test
+    @Test(timeout=10000)
     public void testTransactionCommit() throws InterruptedException, ExecutionException {
 
         DOMDataReadWriteTransaction writeTx = domBroker.newReadWriteTransaction();
@@ -114,6 +137,173 @@ public class DOMBrokerTest {
         assertTrue(afterCommitRead.isPresent());
     }
 
+    /**
+     * Tests a simple DataChangeListener notification after a write.
+     */
+    @Test
+    public void testDataChangeListener() throws Throwable {
+
+        final NormalizedNode<?, ?> testNode = ImmutableNodes.containerNode( TestModel.TEST_QNAME );
+
+        TestDOMDataChangeListener dcListener = new TestDOMDataChangeListener();
+
+        domBroker.registerDataChangeListener( OPERATIONAL, TestModel.TEST_PATH,
+                                              dcListener, DataChangeScope.BASE );
+
+        final DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+        assertNotNull( writeTx );
+
+        writeTx.put( OPERATIONAL, TestModel.TEST_PATH, testNode );
+
+        AtomicReference<Throwable> caughtEx = submitTxAsync( writeTx );
+
+        dcListener.waitForChange();
+
+        if( caughtEx.get() != null ) {
+            throw caughtEx.get();
+        }
+
+        NormalizedNode<?, ?> actualNode = dcListener.change.getCreatedData().get( TestModel.TEST_PATH );
+        assertEquals( "Created node", testNode, actualNode );
+    }
+
+    /**
+     * Tests a DataChangeListener that does an async submit of a write Tx in its onDataChanged method.
+     * This should succeed without deadlock.
+     */
+    @Test
+    public void testDataChangeListenerDoingAsyncWriteTxSubmit() throws Throwable {
+
+        final AtomicReference<Throwable> caughtCommitEx = new AtomicReference<>();
+        final CountDownLatch commitCompletedLatch = new CountDownLatch( 1 );
+
+        TestDOMDataChangeListener dcListener = new TestDOMDataChangeListener() {
+            @Override
+            public void onDataChanged( AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change ) {
+
+                DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+                writeTx.put( OPERATIONAL, TestModel.TEST2_PATH,
+                             ImmutableNodes.containerNode( TestModel.TEST2_QNAME ) );
+                Futures.addCallback( writeTx.submit(), new FutureCallback<Void>() {
+                    @Override
+                    public void onSuccess( Void result ) {
+                        commitCompletedLatch.countDown();
+                    }
+
+                    @Override
+                    public void onFailure( Throwable t ) {
+                        caughtCommitEx.set( t );
+                        commitCompletedLatch.countDown();
+                    }
+                } );
+
+                super.onDataChanged( change );
+            }
+        };
+
+        domBroker.registerDataChangeListener( OPERATIONAL, TestModel.TEST_PATH,
+                                              dcListener, DataChangeScope.BASE );
+
+        final DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+        assertNotNull( writeTx );
+
+        writeTx.put( OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode( TestModel.TEST_QNAME ) );
+
+        AtomicReference<Throwable> caughtEx = submitTxAsync( writeTx );
+
+        dcListener.waitForChange();
+
+        if( caughtEx.get() != null ) {
+            throw caughtEx.get();
+        }
+
+        assertTrue( "Commit Future was not invoked", commitCompletedLatch.await( 5, TimeUnit.SECONDS ) );
+
+        if( caughtCommitEx.get() != null ) {
+            throw caughtCommitEx.get();
+        }
+    }
+
+    /**
+     * Tests a DataChangeListener that does a blocking submit of a write Tx in its onDataChanged method.
+     * This should throw an exception and not deadlock.
+     */
+    @Test(expected=TransactionCommitDeadlockException.class)
+    public void testDataChangeListenerDoingBlockingWriteTxSubmit() throws Throwable {
+
+        final AtomicReference<Throwable> caughtCommitEx = new AtomicReference<>();
+
+        TestDOMDataChangeListener dcListener = new TestDOMDataChangeListener() {
+            @Override
+            public void onDataChanged( AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change ) {
+                DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+                writeTx.put( OPERATIONAL, TestModel.TEST2_PATH,
+                             ImmutableNodes.containerNode( TestModel.TEST2_QNAME ) );
+                try {
+                    writeTx.submit().get();
+                } catch( ExecutionException e ) {
+                    caughtCommitEx.set( e.getCause() );
+                } catch( Exception e ) {
+                    caughtCommitEx.set( e );
+                }
+                finally {
+                    super.onDataChanged( change );
+                }
+            }
+        };
+
+        domBroker.registerDataChangeListener( OPERATIONAL, TestModel.TEST_PATH,
+                                              dcListener, DataChangeScope.BASE );
+
+        final DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+        assertNotNull( writeTx );
+
+        writeTx.put( OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode( TestModel.TEST_QNAME ) );
+
+        AtomicReference<Throwable> caughtEx = submitTxAsync( writeTx );
 
+        dcListener.waitForChange();
 
+        if( caughtEx.get() != null ) {
+            throw caughtEx.get();
+        }
+
+        if( caughtCommitEx.get() != null ) {
+            throw caughtCommitEx.get();
+        }
+    }
+
+    AtomicReference<Throwable> submitTxAsync( final DOMDataWriteTransaction writeTx ) {
+        final AtomicReference<Throwable> caughtEx = new AtomicReference<>();
+        new Thread() {
+            @Override
+            public void run() {
+
+                try {
+                    writeTx.submit();
+                } catch( Throwable e ) {
+                    caughtEx.set( e );
+                }
+            }
+
+        }.start();
+
+        return caughtEx;
+    }
+
+    static class TestDOMDataChangeListener implements DOMDataChangeListener {
+
+        volatile AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change;
+        private final CountDownLatch latch = new CountDownLatch( 1 );
+
+        @Override
+        public void onDataChanged( AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change ) {
+            this.change = change;
+            latch.countDown();
+        }
+
+        void waitForChange() throws InterruptedException {
+            assertTrue( "onDataChanged was not called", latch.await( 5, TimeUnit.SECONDS ) );
+        }
+    }
 }
index d5ba2a2b9a50212e0b75c4036f1afc5fc890b065..09835ec5e37dcd92db413be12cfe5d35967d0910 100644 (file)
@@ -21,6 +21,8 @@ public class TestModel {
 
     public static final QName TEST_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test", "2014-03-13",
             "test");
+    public static final QName TEST2_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test", "2014-03-13",
+            "test2");
     public static final QName OUTER_LIST_QNAME = QName.create(TEST_QNAME, "outer-list");
     public static final QName INNER_LIST_QNAME = QName.create(TEST_QNAME, "inner-list");
     public static final QName OUTER_CHOICE_QNAME = QName.create(TEST_QNAME, "outer-choice");
@@ -30,6 +32,7 @@ public class TestModel {
     private static final String DATASTORE_TEST_YANG = "/odl-datastore-test.yang";
 
     public static final YangInstanceIdentifier TEST_PATH = YangInstanceIdentifier.of(TEST_QNAME);
+    public static final YangInstanceIdentifier TEST2_PATH = YangInstanceIdentifier.of(TEST2_QNAME);
     public static final YangInstanceIdentifier OUTER_LIST_PATH = YangInstanceIdentifier.builder(TEST_PATH).node(OUTER_LIST_QNAME).build();
     public static final QName TWO_QNAME = QName.create(TEST_QNAME,"two");
     public static final QName THREE_QNAME = QName.create(TEST_QNAME,"three");
index 17541fecab02c62f35c7a64cd679ad3ca52849e6..5fbf470f090e44e9e3c080998baa1c1a3a948c46 100644 (file)
@@ -39,4 +39,7 @@ module odl-datastore-test {
             }
         }
     }
+
+    container test2 {
+    }
 }
\ No newline at end of file
index ff64cd64c412d57b12da080468f188d457948c6b..3ddf0b60faf07323f7f26cb4d7488851015ef688 100644 (file)
@@ -9,9 +9,15 @@ package org.opendaylight.controller.md.sal.dom.store.impl;
 
 import static org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.builder;
 
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map.Entry;
@@ -37,13 +43,6 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Multimap;
-
 /**
  * Resolve Data Change Events based on modifications and listeners
  *
@@ -278,6 +277,11 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
             final Collection<Node> listeners, final NormalizedNode<?, ?> beforeData,
             final NormalizedNode<?, ?> afterData) {
 
+        // FIXME: BUG-1493: check the listeners to prune unneeded changes:
+        //                  for subtrees, we have to do all
+        //                  for one, we need to expand children
+        //                  for base, we just report replacement
+
         if (beforeData instanceof NormalizedNodeContainer<?, ?, ?>) {
             // Node is container (contains child) and we have interested
             // listeners registered for it, that means we need to do
@@ -306,14 +310,12 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
             final Collection<Node> listeners,
             final NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> beforeCont,
                     final NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> afterCont) {
-        final Set<PathArgument> alreadyProcessed = new HashSet<>();
         final List<DOMImmutableDataChangeEvent> childChanges = new LinkedList<>();
 
-        DataChangeScope potentialScope = DataChangeScope.BASE;
         // We look at all children from before and compare it with after state.
         for (NormalizedNode<PathArgument, ?> beforeChild : beforeCont.getValue()) {
-            PathArgument childId = beforeChild.getIdentifier();
-            alreadyProcessed.add(childId);
+            final PathArgument childId = beforeChild.getIdentifier();
+
             YangInstanceIdentifier childPath = path.node(childId);
             Collection<ListenerTree.Node> childListeners = getListenerChildrenWildcarded(listeners, childId);
             Optional<NormalizedNode<PathArgument, ?>> afterChild = afterCont.getChild(childId);
@@ -323,15 +325,17 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
             if (childChange != NO_CHANGE) {
                 childChanges.add(childChange);
             }
-
         }
 
         for (NormalizedNode<PathArgument, ?> afterChild : afterCont.getValue()) {
-            PathArgument childId = afterChild.getIdentifier();
-            if (!alreadyProcessed.contains(childId)) {
-                // We did not processed that child already
-                // and it was not present in previous loop, that means it is
-                // created.
+            final PathArgument childId = afterChild.getIdentifier();
+
+            /*
+             * We have already iterated of the before-children, so have already
+             * emitted modify/delete events. This means the child has been
+             * created.
+             */
+            if (!beforeCont.getChild(childId).isPresent()) {
                 Collection<ListenerTree.Node> childListeners = getListenerChildrenWildcarded(listeners, childId);
                 YangInstanceIdentifier childPath = path.node(childId);
                 childChanges.add(resolveSameEventRecursivelly(childPath , childListeners, afterChild,
@@ -342,7 +346,7 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
             return NO_CHANGE;
         }
 
-        Builder eventBuilder = builder(potentialScope) //
+        Builder eventBuilder = builder(DataChangeScope.BASE) //
                 .setBefore(beforeCont) //
                 .setAfter(afterCont)
                 .addUpdated(path, beforeCont, afterCont);
index 07d3c087740c811d4f8404c34d4d90c12ed17143..350132cf99a5dfb05681b0732912e7a4220335d2 100644 (file)
@@ -7,17 +7,11 @@
  */
 package org.opendaylight.controller.sal.connect.netconf;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
 import java.io.InputStream;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.ExecutorService;
+
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.controller.sal.connect.api.MessageTransformer;
@@ -40,6 +34,14 @@ import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
 /**
  *  This is a mediator between NetconfDeviceCommunicator and NetconfDeviceSalFacade
  */
@@ -54,11 +56,20 @@ public final class NetconfDevice implements RemoteDevice<NetconfSessionCapabilit
     private final MessageTransformer<NetconfMessage> messageTransformer;
     private final SchemaContextProviderFactory schemaContextProviderFactory;
     private final SchemaSourceProviderFactory<InputStream> sourceProviderFactory;
+    private final NetconfStateSchemas.NetconfStateSchemasResolver stateSchemasResolver;
     private final NotificationHandler notificationHandler;
 
     public static NetconfDevice createNetconfDevice(final RemoteDeviceId id,
             final AbstractCachingSchemaSourceProvider<String, InputStream> schemaSourceProvider,
             final ExecutorService executor, final RemoteDeviceHandler<NetconfSessionCapabilities> salFacade) {
+        return createNetconfDevice(id, schemaSourceProvider, executor, salFacade, new NetconfStateSchemas.NetconfStateSchemasResolverImpl());
+    }
+
+    @VisibleForTesting
+    protected static NetconfDevice createNetconfDevice(final RemoteDeviceId id,
+            final AbstractCachingSchemaSourceProvider<String, InputStream> schemaSourceProvider,
+            final ExecutorService executor, final RemoteDeviceHandler<NetconfSessionCapabilities> salFacade,
+            final NetconfStateSchemas.NetconfStateSchemasResolver stateSchemasResolver) {
 
         return new NetconfDevice(id, salFacade, executor, new NetconfMessageTransformer(),
                 new NetconfDeviceSchemaProviderFactory(id), new SchemaSourceProviderFactory<InputStream>() {
@@ -67,18 +78,20 @@ public final class NetconfDevice implements RemoteDevice<NetconfSessionCapabilit
                         return schemaSourceProvider.createInstanceFor(new NetconfRemoteSchemaSourceProvider(id,
                                 deviceRpc));
                     }
-                });
+                }, stateSchemasResolver);
     }
 
     @VisibleForTesting
     protected NetconfDevice(final RemoteDeviceId id, final RemoteDeviceHandler<NetconfSessionCapabilities> salFacade,
-            final ExecutorService processingExecutor, final MessageTransformer<NetconfMessage> messageTransformer,
-            final SchemaContextProviderFactory schemaContextProviderFactory,
-            final SchemaSourceProviderFactory<InputStream> sourceProviderFactory) {
+                            final ExecutorService processingExecutor, final MessageTransformer<NetconfMessage> messageTransformer,
+                            final SchemaContextProviderFactory schemaContextProviderFactory,
+                            final SchemaSourceProviderFactory<InputStream> sourceProviderFactory,
+                            final NetconfStateSchemas.NetconfStateSchemasResolver stateSchemasResolver) {
         this.id = id;
         this.messageTransformer = messageTransformer;
         this.salFacade = salFacade;
         this.sourceProviderFactory = sourceProviderFactory;
+        this.stateSchemasResolver = stateSchemasResolver;
         this.processingExecutor = MoreExecutors.listeningDecorator(processingExecutor);
         this.schemaContextProviderFactory = schemaContextProviderFactory;
         this.notificationHandler = new NotificationHandler(salFacade, messageTransformer, id);
@@ -98,6 +111,11 @@ public final class NetconfDevice implements RemoteDevice<NetconfSessionCapabilit
             @Override
             public void run() {
                 final NetconfDeviceRpc deviceRpc = setUpDeviceRpc(remoteSessionCapabilities, listener);
+
+                final NetconfStateSchemas availableSchemas = stateSchemasResolver.resolve(deviceRpc, remoteSessionCapabilities, id);
+                logger.warn("{}: Schemas exposed by ietf-netconf-monitoring: {}", id, availableSchemas.getAvailableYangSchemasQNames());
+                // TODO use this for shared schema context
+
                 final SchemaSourceProvider<InputStream> delegate = sourceProviderFactory.createSourceProvider(deviceRpc);
                 final SchemaContextProvider schemaContextProvider = setUpSchemaContext(delegate, remoteSessionCapabilities);
                 updateMessageTransformer(schemaContextProvider);
@@ -204,6 +222,6 @@ public final class NetconfDevice implements RemoteDevice<NetconfSessionCapabilit
             Preconditions.checkNotNull(parsedNotification);
             salFacade.onNotification(parsedNotification);
         }
-
     }
+
 }
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfStateSchemas.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfStateSchemas.java
new file mode 100644 (file)
index 0000000..b540034
--- /dev/null
@@ -0,0 +1,213 @@
+package org.opendaylight.controller.sal.connect.netconf;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import java.net.URI;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import org.opendaylight.controller.sal.connect.netconf.listener.NetconfSessionCapabilities;
+import org.opendaylight.controller.sal.connect.netconf.sal.NetconfDeviceRpc;
+import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.Yang;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.Schema;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Holds QNames for all yang modules reported by ietf-netconf-monitoring/state/schemas
+ */
+public final class NetconfStateSchemas {
+
+    private static final Logger logger = LoggerFactory.getLogger(NetconfStateSchemas.class);
+
+    /**
+     * Factory for NetconfStateSchemas
+     */
+    public interface NetconfStateSchemasResolver {
+        NetconfStateSchemas resolve(final NetconfDeviceRpc deviceRpc, final NetconfSessionCapabilities remoteSessionCapabilities, final RemoteDeviceId id);
+    }
+
+    /**
+     * Default implementation resolving schemas QNames from netconf-state
+     */
+    public static final class NetconfStateSchemasResolverImpl implements NetconfStateSchemasResolver {
+
+        @Override
+        public NetconfStateSchemas resolve(final NetconfDeviceRpc deviceRpc, final NetconfSessionCapabilities remoteSessionCapabilities, final RemoteDeviceId id) {
+            return NetconfStateSchemas.create(deviceRpc, remoteSessionCapabilities, id);
+        }
+    }
+
+    public static final NetconfStateSchemas EMPTY = new NetconfStateSchemas(Collections.<RemoteYangSchema>emptySet());
+
+    private static final YangInstanceIdentifier STATE_SCHEMAS_IDENTIFIER =
+            YangInstanceIdentifier.builder().node(NetconfState.QNAME).node(Schemas.QNAME).build();
+    private static final YangInstanceIdentifier DATA_STATE_SCHEMAS_IDENTIFIER =
+            YangInstanceIdentifier.builder().node(NetconfMessageTransformUtil.NETCONF_DATA_QNAME)
+                    .node(NetconfState.QNAME).node(Schemas.QNAME).build();
+
+    private static final CompositeNode GET_SCHEMAS_RPC;
+    static {
+        final Node<?> filter = NetconfMessageTransformUtil.toFilterStructure(STATE_SCHEMAS_IDENTIFIER);
+        GET_SCHEMAS_RPC
+                = NodeFactory.createImmutableCompositeNode(NetconfMessageTransformUtil.NETCONF_GET_QNAME, null, Lists.<Node<?>>newArrayList(filter));
+    }
+
+    private final Set<RemoteYangSchema> availableYangSchemas;
+
+    public NetconfStateSchemas(final Set<RemoteYangSchema> availableYangSchemas) {
+        this.availableYangSchemas = availableYangSchemas;
+    }
+
+    public Set<RemoteYangSchema> getAvailableYangSchemas() {
+        return availableYangSchemas;
+    }
+
+    public Set<QName> getAvailableYangSchemasQNames() {
+        return Sets.newHashSet(Collections2.transform(getAvailableYangSchemas(), new Function<RemoteYangSchema, QName>() {
+            @Override
+            public QName apply(final RemoteYangSchema input) {
+                return input.getQName();
+            }
+        }));
+    }
+
+    /**
+     * Issue get request to remote device and parse response to find all schemas under netconf-state/schemas
+     */
+    private static NetconfStateSchemas create(final NetconfDeviceRpc deviceRpc, final NetconfSessionCapabilities remoteSessionCapabilities, final RemoteDeviceId id) {
+        if(remoteSessionCapabilities.isMonitoringSupported() == false) {
+            logger.warn("{}: Netconf monitoring not supported on device, cannot detect available schemas");
+            return EMPTY;
+        }
+
+        final RpcResult<CompositeNode> schemasNodeResult;
+        try {
+            schemasNodeResult = deviceRpc.invokeRpc(NetconfMessageTransformUtil.NETCONF_GET_QNAME, GET_SCHEMAS_RPC).get();
+        } catch (final InterruptedException e) {
+            Thread.currentThread().interrupt();
+            throw new RuntimeException(id + ": Interrupted while waiting for response to " + STATE_SCHEMAS_IDENTIFIER, e);
+        } catch (final ExecutionException e) {
+            logger.warn("{}: Unable to detect available schemas, get to {} failed", id, STATE_SCHEMAS_IDENTIFIER, e);
+            return EMPTY;
+        }
+
+        if(schemasNodeResult.isSuccessful() == false) {
+            logger.warn("{}: Unable to detect available schemas, get to {} failed, {}", id, STATE_SCHEMAS_IDENTIFIER, schemasNodeResult.getErrors());
+            return EMPTY;
+        }
+
+        final CompositeNode schemasNode =
+                (CompositeNode) NetconfMessageTransformUtil.findNode(schemasNodeResult.getResult(), DATA_STATE_SCHEMAS_IDENTIFIER);
+        return create(schemasNode);
+    }
+
+    /**
+     * Parse response of get(netconf-state/schemas) to find all schemas under netconf-state/schemas
+     */
+    @VisibleForTesting
+    protected static NetconfStateSchemas create(final CompositeNode schemasNode) {
+        final Set<RemoteYangSchema> availableYangSchemas = Sets.newHashSet();
+
+        for (final CompositeNode schemaNode : schemasNode.getCompositesByName(Schema.QNAME.withoutRevision())) {
+            availableYangSchemas.add(RemoteYangSchema.createFromCompositeNode(schemaNode));
+        }
+
+        return new NetconfStateSchemas(availableYangSchemas);
+    }
+
+    public final static class RemoteYangSchema {
+        private final QName qname;
+
+        private RemoteYangSchema(final QName qname) {
+            this.qname = qname;
+        }
+
+        public QName getQName() {
+            return qname;
+        }
+
+        static RemoteYangSchema createFromCompositeNode(final CompositeNode schemaNode) {
+            Preconditions.checkArgument(schemaNode.getKey().equals(Schema.QNAME.withoutRevision()), "Wrong QName %s", schemaNode.getKey());
+
+            QName childNode = NetconfMessageTransformUtil.IETF_NETCONF_MONITORING_SCHEMA_FORMAT.withoutRevision();
+
+            final String formatAsString = getSingleChildNodeValue(schemaNode, childNode).get();
+            Preconditions.checkArgument(formatAsString.equals(Yang.QNAME.getLocalName()),
+                    "Expecting format to be only %s, not %s", Yang.QNAME.getLocalName(), formatAsString);
+
+            childNode = NetconfMessageTransformUtil.IETF_NETCONF_MONITORING_SCHEMA_LOCATION.withoutRevision();
+            final Set<String> locationsAsString = getAllChildNodeValues(schemaNode, childNode);
+            Preconditions.checkArgument(locationsAsString.contains(Schema.Location.Enumeration.NETCONF.toString()),
+                    "Expecting location to be %s, not %s", Schema.Location.Enumeration.NETCONF.toString(), locationsAsString);
+
+            childNode = NetconfMessageTransformUtil.IETF_NETCONF_MONITORING_SCHEMA_NAMESPACE.withoutRevision();
+            final String namespaceAsString = getSingleChildNodeValue(schemaNode, childNode).get();
+
+            childNode = NetconfMessageTransformUtil.IETF_NETCONF_MONITORING_SCHEMA_VERSION.withoutRevision();
+            // Revision does not have to be filled
+            final Optional<String> revisionAsString = getSingleChildNodeValue(schemaNode, childNode);
+
+            childNode = NetconfMessageTransformUtil.IETF_NETCONF_MONITORING_SCHEMA_IDENTIFIER.withoutRevision();
+            final String moduleNameAsString = getSingleChildNodeValue(schemaNode, childNode).get();
+
+            final QName moduleQName = revisionAsString.isPresent()
+                    ? QName.create(namespaceAsString, revisionAsString.get(), moduleNameAsString)
+                    : QName.create(URI.create(namespaceAsString), null, moduleNameAsString).withoutRevision();
+
+            return new RemoteYangSchema(moduleQName);
+        }
+
+        private static Set<String> getAllChildNodeValues(final CompositeNode schemaNode, final QName childNodeQName) {
+            final Set<String> extractedValues = Sets.newHashSet();
+            for (final SimpleNode<?> childNode : schemaNode.getSimpleNodesByName(childNodeQName)) {
+                extractedValues.add(getValueOfSimpleNode(childNodeQName, childNode).get());
+            }
+            return extractedValues;
+        }
+
+        private static Optional<String> getSingleChildNodeValue(final CompositeNode schemaNode, final QName childNode) {
+            final SimpleNode<?> node = schemaNode.getFirstSimpleByName(childNode);
+            return getValueOfSimpleNode(childNode, node);
+        }
+
+        private static Optional<String> getValueOfSimpleNode(final QName childNode, final SimpleNode<?> node) {
+            Preconditions.checkNotNull(node, "Child node %s not present", childNode);
+            final Object value = node.getValue();
+            return value == null ? Optional.<String>absent() : Optional.of(value.toString().trim());
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            final RemoteYangSchema that = (RemoteYangSchema) o;
+
+            if (!qname.equals(that.qname)) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            return qname.hashCode();
+        }
+    }
+}
index 3871cdfa4f4cb7556313d8419407e1d3326dc802..2f24adcdbed9eee793b5833b04d108dafada12d6 100644 (file)
@@ -229,7 +229,7 @@ public class NetconfDeviceCommunicator implements NetconfClientSessionListener,
             try {
                 NetconfMessageTransformUtil.checkSuccessReply(message);
             }
-            catch( NetconfDocumentedException e ) {
+            catch(final NetconfDocumentedException e) {
                 logger.warn( "{}: Error reply from remote device, request: {}, response: {}", id,
                              msgToS( request.request ), msgToS( message ), e );
 
index 533df9cce7f06575c75419a80f8b43e591dd3e7b..04a99511a1dfaa6154a9894e47906d859de0c199 100644 (file)
@@ -30,8 +30,6 @@ import org.opendaylight.controller.sal.core.api.RpcImplementation;
 import org.opendaylight.yangtools.util.concurrent.MappingCheckedFuture;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.slf4j.Logger;
@@ -63,7 +61,7 @@ public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction
                 checkReadSuccess(result, path);
 
                 final CompositeNode data = result.getResult().getFirstCompositeByName(NETCONF_DATA_QNAME);
-                final CompositeNode node = (CompositeNode) findNode(data, path);
+                final CompositeNode node = (CompositeNode) NetconfMessageTransformUtil.findNode(data, path);
 
                 return data == null ?
                         Optional.<NormalizedNode<?, ?>>absent() :
@@ -105,7 +103,7 @@ public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction
                 checkReadSuccess(result, path);
 
                 final CompositeNode data = result.getResult().getFirstCompositeByName(NETCONF_DATA_QNAME);
-                final CompositeNode node = (CompositeNode) findNode(data, path);
+                final CompositeNode node = (CompositeNode) NetconfMessageTransformUtil.findNode(data, path);
 
                 return data == null ?
                         Optional.<NormalizedNode<?, ?>>absent() :
@@ -116,33 +114,6 @@ public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction
         return MappingCheckedFuture.create(transformedFuture, ReadFailedException.MAPPER);
     }
 
-    private static Node<?> findNode(final CompositeNode node, final YangInstanceIdentifier identifier) {
-
-        Node<?> current = node;
-        for (final YangInstanceIdentifier.PathArgument arg : identifier.getPathArguments()) {
-            if (current instanceof SimpleNode<?>) {
-                return null;
-            } else if (current instanceof CompositeNode) {
-                final CompositeNode currentComposite = (CompositeNode) current;
-
-                current = currentComposite.getFirstCompositeByName(arg.getNodeType());
-                if (current == null) {
-                    current = currentComposite.getFirstCompositeByName(arg.getNodeType().withoutRevision());
-                }
-                if (current == null) {
-                    current = currentComposite.getFirstSimpleByName(arg.getNodeType());
-                }
-                if (current == null) {
-                    current = currentComposite.getFirstSimpleByName(arg.getNodeType().withoutRevision());
-                }
-                if (current == null) {
-                    return null;
-                }
-            }
-        }
-        return current;
-    }
-
     @Override
     public void close() {
         // NOOP
index 80d0f67ac49c72b47d35e6ca094ec4610099c1b1..5e61dfb028e33551c72c63e7b4ff89bcf1554119 100644 (file)
@@ -70,10 +70,15 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
                 if (NetconfMessageTransformUtil.isDataEditOperation(rpc)) {
                     final DataNodeContainer schemaForEdit = NetconfMessageTransformUtil.createSchemaForEdit(schemaContext.get());
                     w3cPayload = XmlDocumentUtils.toDocument(rpcPayload, schemaForEdit, codecProvider);
+                } else if (NetconfMessageTransformUtil.isGetOperation(rpc)) {
+                    final DataNodeContainer schemaForGet = NetconfMessageTransformUtil.createSchemaForGet(schemaContext.get());
+                    w3cPayload = XmlDocumentUtils.toDocument(rpcPayload, schemaForGet, codecProvider);
+                } else if (NetconfMessageTransformUtil.isGetConfigOperation(rpc)) {
+                    final DataNodeContainer schemaForGetConfig = NetconfMessageTransformUtil.createSchemaForGetConfig(schemaContext.get());
+                    w3cPayload = XmlDocumentUtils.toDocument(rpcPayload, schemaForGetConfig, codecProvider);
                 } else {
-                    // FIXME get and get-config needs schema as well to transform filter using schema context
-                    // e.g. Identityref nodes in filter fail to serialize properly to xml without schema
-                    w3cPayload = XmlDocumentUtils.toDocument(rpcPayload, schemaContext.get(), codecProvider);
+                    final DataNodeContainer schemaForGetConfig = NetconfMessageTransformUtil.createSchemaForRpc(rpc, schemaContext.get());
+                    w3cPayload = XmlDocumentUtils.toDocument(rpcPayload, schemaForGetConfig, codecProvider);
                 }
             } else {
                 w3cPayload = XmlDocumentUtils.toDocument(rpcPayload, codecProvider);
@@ -91,30 +96,29 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
             return toRpcResult(message, rpc, schemaContext.get());
         } else {
             final CompositeNode node = (CompositeNode) XmlDocumentUtils.toDomNode(message.getDocument());
-            return RpcResultBuilder.success( node ).build();
+            return RpcResultBuilder.success(node).build();
         }
     }
 
     private static RpcResult<CompositeNode> toRpcResult(final NetconfMessage message, final QName rpc, final SchemaContext context) {
         final CompositeNode compositeNode;
-
         if (NetconfMessageTransformUtil.isDataRetrievalOperation(rpc)) {
-
             final Element xmlData = NetconfMessageTransformUtil.getDataSubtree(message.getDocument());
-
             final List<org.opendaylight.yangtools.yang.data.api.Node<?>> dataNodes = XmlDocumentUtils.toDomNodes(xmlData,
                     Optional.of(context.getDataDefinitions()), context);
 
             final CompositeNodeBuilder<ImmutableCompositeNode> it = ImmutableCompositeNode.builder();
             it.setQName(NetconfMessageTransformUtil.NETCONF_RPC_REPLY_QNAME);
             it.add(ImmutableCompositeNode.create(NetconfMessageTransformUtil.NETCONF_DATA_QNAME, dataNodes));
-
             compositeNode = it.toInstance();
         } else {
-            // TODO map rpc with schema
-            compositeNode = (CompositeNode) XmlDocumentUtils.toDomNode(message.getDocument());
+            final CompositeNode rpcReply = XmlDocumentUtils.rpcReplyToDomNodes(message.getDocument(), rpc, context);
+            if (rpcReply != null) {
+                compositeNode = rpcReply;
+            } else {
+                compositeNode = (CompositeNode) XmlDocumentUtils.toDomNode(message.getDocument());
+            }
         }
-
         return RpcResultBuilder.success( compositeNode ).build();
     }
 
index d3faddd471d0533c221b00cbe867a8b9d6431a12..1e3cf4b6fce9f30917ef4c3bc3c19a61bf9b7d64 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.sal.connect.netconf.util;
 
+import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableList;
@@ -26,6 +27,7 @@ import javax.annotation.Nullable;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfState;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
@@ -33,6 +35,7 @@ import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
@@ -48,7 +51,13 @@ public class NetconfMessageTransformUtil {
 
     private NetconfMessageTransformUtil() {}
 
-    public static final QName IETF_NETCONF_MONITORING = QName.create("urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring", "2010-10-04", "ietf-netconf-monitoring");
+    public static final QName IETF_NETCONF_MONITORING = QName.create(NetconfState.QNAME, "ietf-netconf-monitoring");
+    public static final QName IETF_NETCONF_MONITORING_SCHEMA_FORMAT = QName.create(IETF_NETCONF_MONITORING, "format");
+    public static final QName IETF_NETCONF_MONITORING_SCHEMA_LOCATION = QName.create(IETF_NETCONF_MONITORING, "location");
+    public static final QName IETF_NETCONF_MONITORING_SCHEMA_IDENTIFIER = QName.create(IETF_NETCONF_MONITORING, "identifier");
+    public static final QName IETF_NETCONF_MONITORING_SCHEMA_VERSION = QName.create(IETF_NETCONF_MONITORING, "version");
+    public static final QName IETF_NETCONF_MONITORING_SCHEMA_NAMESPACE = QName.create(IETF_NETCONF_MONITORING, "namespace");
+
     public static URI NETCONF_URI = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0");
     public static QName NETCONF_QNAME = QName.create(NETCONF_URI, null, "netconf");
     public static QName NETCONF_DATA_QNAME = QName.create(NETCONF_QNAME, "data");
@@ -226,6 +235,14 @@ public class NetconfMessageTransformUtil {
                         NETCONF_GET_QNAME.getLocalName()));
     }
 
+    public static boolean isGetOperation(final QName rpc) {
+        return NETCONF_URI.equals(rpc.getNamespace()) && rpc.getLocalName().equals(NETCONF_GET_QNAME.getLocalName());
+    }
+
+    public static boolean isGetConfigOperation(final QName rpc) {
+        return NETCONF_URI.equals(rpc.getNamespace()) && rpc.getLocalName().equals(NETCONF_GET_CONFIG_QNAME.getLocalName());
+    }
+
     public static boolean isDataEditOperation(final QName rpc) {
         return NETCONF_URI.equals(rpc.getNamespace())
                 && rpc.getLocalName().equals(NETCONF_EDIT_CONFIG_QNAME.getLocalName());
@@ -256,6 +273,80 @@ public class NetconfMessageTransformUtil {
         return new NodeContainerProxy(NETCONF_RPC_QNAME, Sets.<DataSchemaNode>newHashSet(editConfigProxy));
     }
 
+    /**
+     * Creates artificial schema node for edit-config rpc. This artificial schema looks like:
+     * <pre>
+     * {@code
+     * rpc
+     *   get
+     *     filter
+     *         // All schema nodes from remote schema
+     *     filter
+     *   get
+     * rpc
+     * }
+     * </pre>
+     *
+     * This makes the translation of rpc get request(especially the config node)
+     * to xml use schema which is crucial for some types of nodes e.g. identity-ref.
+     */
+    public static DataNodeContainer createSchemaForGet(final SchemaContext schemaContext) {
+        final QName filter = QName.create(NETCONF_GET_QNAME, "filter");
+        final QName get = QName.create(NETCONF_GET_QNAME, "get");
+        final NodeContainerProxy configProxy = new NodeContainerProxy(filter, schemaContext.getChildNodes());
+        final NodeContainerProxy editConfigProxy = new NodeContainerProxy(get, Sets.<DataSchemaNode>newHashSet(configProxy));
+        return new NodeContainerProxy(NETCONF_RPC_QNAME, Sets.<DataSchemaNode>newHashSet(editConfigProxy));
+    }
+
+    /**
+     * Creates artificial schema node for get rpc. This artificial schema looks like:
+     * <pre>
+     * {@code
+     * rpc
+     *   get-config
+     *     filter
+     *         // All schema nodes from remote schema
+     *     filter
+     *   get-config
+     * rpc
+     * }
+     * </pre>
+     *
+     * This makes the translation of rpc get-config request(especially the config node)
+     * to xml use schema which is crucial for some types of nodes e.g. identity-ref.
+     */
+    public static DataNodeContainer createSchemaForGetConfig(final SchemaContext schemaContext) {
+        final QName filter = QName.create(NETCONF_GET_CONFIG_QNAME, "filter");
+        final QName getConfig = QName.create(NETCONF_GET_CONFIG_QNAME, "get-config");
+        final NodeContainerProxy configProxy = new NodeContainerProxy(filter, schemaContext.getChildNodes());
+        final NodeContainerProxy editConfigProxy = new NodeContainerProxy(getConfig, Sets.<DataSchemaNode>newHashSet(configProxy));
+        return new NodeContainerProxy(NETCONF_RPC_QNAME, Sets.<DataSchemaNode>newHashSet(editConfigProxy));
+    }
+
+    /**
+     * Creates artificial schema node for schema defined rpc. This artificial schema looks like:
+     * <pre>
+     * {@code
+     * rpc
+     *   rpc-name
+     *      // All schema nodes from remote schema
+     *   rpc-name
+     * rpc
+     * }
+     * </pre>
+     *
+     * This makes the translation of schema defined rpc request
+     * to xml use schema which is crucial for some types of nodes e.g. identity-ref.
+     */
+    public static DataNodeContainer createSchemaForRpc(final QName rpcName, final SchemaContext schemaContext) {
+        Preconditions.checkNotNull(rpcName);
+        Preconditions.checkNotNull(schemaContext);
+
+        final NodeContainerProxy rpcBodyProxy = new NodeContainerProxy(rpcName, schemaContext.getChildNodes());
+        return new NodeContainerProxy(NETCONF_RPC_QNAME, Sets.<DataSchemaNode>newHashSet(rpcBodyProxy));
+
+    }
+
     public static CompositeNodeTOImpl wrap(final QName name, final Node<?> node) {
         if (node != null) {
             return new CompositeNodeTOImpl(name, null, Collections.<Node<?>> singletonList(node));
@@ -282,4 +373,31 @@ public class NetconfMessageTransformUtil {
             return it.toInstance();
         }
     }
+
+    public static Node<?> findNode(final CompositeNode node, final YangInstanceIdentifier identifier) {
+
+        Node<?> current = node;
+        for (final YangInstanceIdentifier.PathArgument arg : identifier.getPathArguments()) {
+            if (current instanceof SimpleNode<?>) {
+                return null;
+            } else if (current instanceof CompositeNode) {
+                final CompositeNode currentComposite = (CompositeNode) current;
+
+                current = currentComposite.getFirstCompositeByName(arg.getNodeType());
+                if (current == null) {
+                    current = currentComposite.getFirstCompositeByName(arg.getNodeType().withoutRevision());
+                }
+                if (current == null) {
+                    current = currentComposite.getFirstSimpleByName(arg.getNodeType());
+                }
+                if (current == null) {
+                    current = currentComposite.getFirstSimpleByName(arg.getNodeType().withoutRevision());
+                }
+                if (current == null) {
+                    return null;
+                }
+            }
+        }
+        return current;
+    }
 }
index 46ea4ff73c40ae0d29ec267d834a19e2d88faa19..fa488dadd3efb4afefc48327b683a44f296727dc 100644 (file)
@@ -15,6 +15,9 @@ import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.Futures;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -23,7 +26,6 @@ import java.util.List;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
-
 import org.junit.Test;
 import org.mockito.Mockito;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
@@ -34,6 +36,7 @@ import org.opendaylight.controller.sal.connect.api.RemoteDeviceHandler;
 import org.opendaylight.controller.sal.connect.api.SchemaContextProviderFactory;
 import org.opendaylight.controller.sal.connect.api.SchemaSourceProviderFactory;
 import org.opendaylight.controller.sal.connect.netconf.listener.NetconfSessionCapabilities;
+import org.opendaylight.controller.sal.connect.netconf.sal.NetconfDeviceRpc;
 import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
 import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.controller.sal.core.api.RpcImplementation;
@@ -47,10 +50,6 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
 import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.Futures;
-
 public class NetconfDeviceTest {
 
     private static final NetconfMessage netconfMessage;
@@ -71,13 +70,20 @@ public class NetconfDeviceTest {
     public static final String TEST_NAMESPACE = "test:namespace";
     public static final String TEST_MODULE = "test-module";
     public static final String TEST_REVISION = "2013-07-22";
+    private NetconfStateSchemas.NetconfStateSchemasResolver stateSchemasResolver = new NetconfStateSchemas.NetconfStateSchemasResolver() {
+
+        @Override
+        public NetconfStateSchemas resolve(final NetconfDeviceRpc deviceRpc, final NetconfSessionCapabilities remoteSessionCapabilities, final RemoteDeviceId id) {
+            return NetconfStateSchemas.EMPTY;
+        }
+    };
 
     @Test
     public void testNetconfDeviceWithoutMonitoring() throws Exception {
         final RemoteDeviceHandler<NetconfSessionCapabilities> facade = getFacade();
         final RemoteDeviceCommunicator<NetconfMessage> listener = getListener();
 
-        final NetconfDevice device = new NetconfDevice(getId(), facade, getExecutor(), getMessageTransformer(), getSchemaContextProviderFactory(), getSourceProviderFactory());
+        final NetconfDevice device = new NetconfDevice(getId(), facade, getExecutor(), getMessageTransformer(), getSchemaContextProviderFactory(), getSourceProviderFactory(), stateSchemasResolver);
         device.onRemoteSessionUp(getSessionCaps(false, Collections.<String>emptyList()), listener);
 
         Mockito.verify(facade, Mockito.timeout(5000)).onDeviceDisconnected();
@@ -89,7 +95,7 @@ public class NetconfDeviceTest {
         final RemoteDeviceCommunicator<NetconfMessage> listener = getListener();
 
         final MessageTransformer<NetconfMessage> messageTransformer = getMessageTransformer();
-        final NetconfDevice device = new NetconfDevice(getId(), facade, getExecutor(), messageTransformer, getSchemaContextProviderFactory(), getSourceProviderFactory());
+        final NetconfDevice device = new NetconfDevice(getId(), facade, getExecutor(), messageTransformer, getSchemaContextProviderFactory(), getSourceProviderFactory(), stateSchemasResolver);
 
         device.onNotification(netconfMessage);
         device.onNotification(netconfMessage);
@@ -118,7 +124,7 @@ public class NetconfDeviceTest {
         final SchemaSourceProviderFactory<InputStream> sourceProviderFactory = getSourceProviderFactory();
         final MessageTransformer<NetconfMessage> messageTransformer = getMessageTransformer();
 
-        final NetconfDevice device = new NetconfDevice(getId(), facade, getExecutor(), messageTransformer, schemaContextProviderFactory, sourceProviderFactory);
+        final NetconfDevice device = new NetconfDevice(getId(), facade, getExecutor(), messageTransformer, schemaContextProviderFactory, sourceProviderFactory, stateSchemasResolver);
         final NetconfSessionCapabilities sessionCaps = getSessionCaps(true,
                 Lists.newArrayList(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&amp;revision=" + TEST_REVISION));
         device.onRemoteSessionUp(sessionCaps, listener);
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfStateSchemasTest.java b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfStateSchemasTest.java
new file mode 100644 (file)
index 0000000..16a915e
--- /dev/null
@@ -0,0 +1,29 @@
+package org.opendaylight.controller.sal.connect.netconf;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.hasItem;
+
+import java.util.Set;
+import org.junit.Test;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.w3c.dom.Document;
+
+public class NetconfStateSchemasTest {
+
+    @Test
+    public void testCreate() throws Exception {
+        final Document schemasXml = XmlUtil.readXmlToDocument(getClass().getResourceAsStream("/netconf-state.schemas.payload.xml"));
+        final CompositeNode compositeNodeSchemas = (CompositeNode) XmlDocumentUtils.toDomNode(schemasXml);
+        final NetconfStateSchemas schemas = NetconfStateSchemas.create(compositeNodeSchemas);
+
+        final Set<QName> availableYangSchemasQNames = schemas.getAvailableYangSchemasQNames();
+        assertEquals(73, availableYangSchemasQNames.size());
+
+        assertThat(availableYangSchemasQNames,
+                hasItem(QName.create("urn:TBD:params:xml:ns:yang:network-topology", "2013-07-12", "network-topology")));
+    }
+}
index 521a55df682340cfacdcf4e11513641ce64c0107..127b0cbfcdd510f569af8b1d71d0e773d9e1f740 100644 (file)
@@ -31,6 +31,7 @@ public class NetconfToNotificationTest {
 
     NetconfMessage userNotification;
 
+    @SuppressWarnings("deprecation")
     @Before
     public void setup() throws Exception {
         final List<InputStream> modelsToParse = Collections.singletonList(getClass().getResourceAsStream("/schemas/user-notification.yang"));
index 18a3b9f0ff65d9055daf13d6f7e70f01653de6ea..e744e11bc9212fc58666654b454a804e1e7f06ce 100644 (file)
@@ -9,7 +9,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
-import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.sal.connect.netconf.schema.mapping.NetconfMessageTransformer;
@@ -22,6 +22,8 @@ import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.w3c.dom.Document;
+
 
 /**
  * Test case for reported bug 1355
@@ -32,33 +34,195 @@ import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
  */
 public class NetconfToRpcRequestTest {
 
-    private String TEST_MODEL_NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:rpc-test";
-    private String REVISION = "2014-07-14";
-    private QName INPUT_QNAME = QName.create(TEST_MODEL_NAMESPACE, REVISION, "input");
-    private QName STREAM_NAME = QName.create(TEST_MODEL_NAMESPACE, REVISION, "stream-name");
-    private QName RPC_NAME = QName.create(TEST_MODEL_NAMESPACE, REVISION, "subscribe");
+    private final static String TEST_MODEL_NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:rpc-test";
+    private final static String REVISION = "2014-07-14";
+    private final static QName INPUT_QNAME = QName.create(TEST_MODEL_NAMESPACE, REVISION, "input");
+    private final static QName STREAM_NAME = QName.create(TEST_MODEL_NAMESPACE, REVISION, "stream-name");
+    private final static QName SUBSCRIBE_RPC_NAME = QName.create(TEST_MODEL_NAMESPACE, REVISION, "subscribe");
+
+    private final static String CONFIG_TEST_NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:test:rpc:config:defs";
+    private final static String CONFIG_TEST_REVISION = "2014-07-21";
+    private final static QName EDIT_CONFIG_QNAME = QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "edit-config");
+    private final static QName GET_QNAME = QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "get");
+    private final static QName GET_CONFIG_QNAME = QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "get-config");
 
-    NetconfMessageTransformer messageTransformer;
+    static SchemaContext notifCtx;
+    static SchemaContext cfgCtx;
+    static NetconfMessageTransformer messageTransformer;
 
     @SuppressWarnings("deprecation")
-    @Before
-    public void setup() throws Exception {
-        final List<InputStream> modelsToParse = Collections
-            .singletonList(getClass().getResourceAsStream("/schemas/rpc-notification-subscription.yang"));
-        final YangContextParser parser = new YangParserImpl();
-        final Set<Module> modules = parser.parseYangModelsFromStreams(modelsToParse);
-        assertTrue(!modules.isEmpty());
-        final SchemaContext schemaContext = parser.resolveSchemaContext(modules);
-        assertNotNull(schemaContext);
+    @BeforeClass
+    public static void setup() throws Exception {
+        List<InputStream> modelsToParse = Collections
+            .singletonList(NetconfToRpcRequestTest.class.getResourceAsStream("/schemas/rpc-notification-subscription.yang"));
+        YangContextParser parser = new YangParserImpl();
+        final Set<Module> notifModules = parser.parseYangModelsFromStreams(modelsToParse);
+        assertTrue(!notifModules.isEmpty());
+
+        notifCtx = parser.resolveSchemaContext(notifModules);
+        assertNotNull(notifCtx);
+
+        modelsToParse = Collections
+            .singletonList(NetconfToRpcRequestTest.class.getResourceAsStream("/schemas/config-test-rpc.yang"));
+        parser = new YangParserImpl();
+        final Set<Module> configModules = parser.parseYangModelsFromStreams(modelsToParse);
+        cfgCtx = parser.resolveSchemaContext(configModules);
+        assertNotNull(cfgCtx);
 
         messageTransformer = new NetconfMessageTransformer();
-        messageTransformer.onGlobalContextUpdated(schemaContext);
     }
 
     @Test
-    public void test() throws Exception {
+    public void testIsDataEditOperation() throws Exception {
+        messageTransformer.onGlobalContextUpdated(cfgCtx);
+
         final CompositeNodeBuilder<ImmutableCompositeNode> rootBuilder = ImmutableCompositeNode.builder();
-        rootBuilder.setQName(RPC_NAME);
+        rootBuilder.setQName(EDIT_CONFIG_QNAME);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> inputBuilder = ImmutableCompositeNode.builder();
+        inputBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "input"));
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> targetBuilder = ImmutableCompositeNode.builder();
+        targetBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "target"));
+        targetBuilder.addLeaf(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "running"), null);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> configBuilder = ImmutableCompositeNode.builder();
+        configBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "config"));
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> anyxmlTopBuilder = ImmutableCompositeNode.builder();
+        anyxmlTopBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "top"));
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> anyxmlInterfBuilder = ImmutableCompositeNode.builder();
+        anyxmlInterfBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "interface"));
+
+        anyxmlInterfBuilder.addLeaf(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "name"), "Ethernet0/0");
+        anyxmlInterfBuilder.addLeaf(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "mtu"), "1500");
+
+        anyxmlTopBuilder.add(anyxmlInterfBuilder.toInstance());
+        configBuilder.add(anyxmlTopBuilder.toInstance());
+
+        inputBuilder.add(targetBuilder.toInstance());
+        inputBuilder.add(configBuilder.toInstance());
+
+        rootBuilder.add(inputBuilder.toInstance());
+        final ImmutableCompositeNode root = rootBuilder.toInstance();
+
+        final NetconfMessage message = messageTransformer.toRpcRequest(EDIT_CONFIG_QNAME, root);
+        assertNotNull(message);
+
+        final Document xmlDoc = message.getDocument();
+        org.w3c.dom.Node rpcChild = xmlDoc.getFirstChild();
+        assertEquals(rpcChild.getLocalName(), "rpc");
+
+        final org.w3c.dom.Node editConfigNode = rpcChild.getFirstChild();
+        assertEquals(editConfigNode.getLocalName(), "edit-config");
+
+        final org.w3c.dom.Node targetNode = editConfigNode.getFirstChild();
+        assertEquals(targetNode.getLocalName(), "target");
+
+        final org.w3c.dom.Node runningNode = targetNode.getFirstChild();
+        assertEquals(runningNode.getLocalName(), "running");
+
+        final org.w3c.dom.Node configNode = targetNode.getNextSibling();
+        assertEquals(configNode.getLocalName(), "config");
+
+        final org.w3c.dom.Node topNode = configNode.getFirstChild();
+        assertEquals(topNode.getLocalName(), "top");
+
+        final org.w3c.dom.Node interfaceNode = topNode.getFirstChild();
+        assertEquals(interfaceNode.getLocalName(), "interface");
+
+        final org.w3c.dom.Node nameNode = interfaceNode.getFirstChild();
+        assertEquals(nameNode.getLocalName(), "name");
+
+        final org.w3c.dom.Node mtuNode = nameNode.getNextSibling();
+        assertEquals(mtuNode.getLocalName(), "mtu");
+    }
+
+    @Test
+    public void testIsGetOperation() throws Exception {
+        messageTransformer.onGlobalContextUpdated(cfgCtx);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> rootBuilder = ImmutableCompositeNode.builder();
+        rootBuilder.setQName(GET_QNAME);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> inputBuilder = ImmutableCompositeNode.builder();
+        inputBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "input"));
+
+        rootBuilder.add(inputBuilder.toInstance());
+        final ImmutableCompositeNode root = rootBuilder.toInstance();
+
+        final NetconfMessage message = messageTransformer.toRpcRequest(GET_QNAME, root);
+        assertNotNull(message);
+
+        final Document xmlDoc = message.getDocument();
+        final org.w3c.dom.Node rpcChild = xmlDoc.getFirstChild();
+        assertEquals(rpcChild.getLocalName(), "rpc");
+
+        final org.w3c.dom.Node get = rpcChild.getFirstChild();
+        assertEquals(get.getLocalName(), "get");
+    }
+
+    @Test
+    public void testIsGetConfigOperation() throws Exception {
+        messageTransformer.onGlobalContextUpdated(cfgCtx);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> rootBuilder = ImmutableCompositeNode.builder();
+        rootBuilder.setQName(GET_CONFIG_QNAME);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> inputBuilder = ImmutableCompositeNode.builder();
+        inputBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "input"));
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> sourceBuilder = ImmutableCompositeNode.builder();
+        sourceBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "source"));
+        sourceBuilder.addLeaf(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "running"), null);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> anyxmlFilterBuilder = ImmutableCompositeNode.builder();
+        anyxmlFilterBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "filter"));
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> anyxmlTopBuilder = ImmutableCompositeNode.builder();
+        anyxmlTopBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "top"));
+        anyxmlTopBuilder.addLeaf(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "users"), null);
+
+        anyxmlFilterBuilder.add(anyxmlTopBuilder.toInstance());
+
+        inputBuilder.add(sourceBuilder.toInstance());
+        inputBuilder.add(anyxmlFilterBuilder.toInstance());
+        rootBuilder.add(inputBuilder.toInstance());
+        final ImmutableCompositeNode root = rootBuilder.toInstance();
+
+        final NetconfMessage message = messageTransformer.toRpcRequest(GET_CONFIG_QNAME, root);
+        assertNotNull(message);
+
+        final Document xmlDoc = message.getDocument();
+        final org.w3c.dom.Node rpcChild = xmlDoc.getFirstChild();
+        assertEquals(rpcChild.getLocalName(), "rpc");
+
+        final org.w3c.dom.Node getConfig = rpcChild.getFirstChild();
+        assertEquals(getConfig.getLocalName(), "get-config");
+
+        final org.w3c.dom.Node sourceNode = getConfig.getFirstChild();
+        assertEquals(sourceNode.getLocalName(), "source");
+
+        final org.w3c.dom.Node runningNode = sourceNode.getFirstChild();
+        assertEquals(runningNode.getLocalName(), "running");
+
+        final org.w3c.dom.Node filterNode = sourceNode.getNextSibling();
+        assertEquals(filterNode.getLocalName(), "filter");
+
+        final org.w3c.dom.Node topNode = filterNode.getFirstChild();
+        assertEquals(topNode.getLocalName(), "top");
+
+        final org.w3c.dom.Node usersNode = topNode.getFirstChild();
+        assertEquals(usersNode.getLocalName(), "users");
+    }
+
+    @Test
+    public void testUserDefinedRpcCall() throws Exception {
+        messageTransformer.onGlobalContextUpdated(notifCtx);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> rootBuilder = ImmutableCompositeNode.builder();
+        rootBuilder.setQName(SUBSCRIBE_RPC_NAME);
 
         final CompositeNodeBuilder<ImmutableCompositeNode> inputBuilder = ImmutableCompositeNode.builder();
         inputBuilder.setQName(INPUT_QNAME);
@@ -75,7 +239,51 @@ public class NetconfToRpcRequestTest {
         assertNotNull(inputNode);
         assertTrue(inputNode.isEmpty());
 
-        final NetconfMessage message = messageTransformer.toRpcRequest(RPC_NAME, root);
+        final NetconfMessage message = messageTransformer.toRpcRequest(SUBSCRIBE_RPC_NAME, root);
+        assertNotNull(message);
+
+        final Document xmlDoc = message.getDocument();
+        final org.w3c.dom.Node rpcChild = xmlDoc.getFirstChild();
+        assertEquals(rpcChild.getLocalName(), "rpc");
+
+        final org.w3c.dom.Node subscribeName = rpcChild.getFirstChild();
+        assertEquals(subscribeName.getLocalName(), "subscribe");
+
+        final org.w3c.dom.Node streamName = subscribeName.getFirstChild();
+        assertEquals(streamName.getLocalName(), "stream-name");
+    }
+
+    @Test
+    public void testNoSchemaContextToRpcRequest() throws Exception {
+        final String exampleNamespace = "http://example.net/me/my-own/1.0";
+        final String exampleRevision = "2014-07-22";
+        final QName myOwnMethodRpcQName = QName.create(exampleNamespace, exampleRevision, "my-own-method");
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> rootBuilder = ImmutableCompositeNode.builder();
+        rootBuilder.setQName(myOwnMethodRpcQName);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> inputBuilder = ImmutableCompositeNode.builder();
+        inputBuilder.setQName(QName.create(exampleNamespace, exampleRevision, "input"));
+        inputBuilder.addLeaf(QName.create(exampleNamespace, exampleRevision, "my-first-parameter"), "14");
+        inputBuilder.addLeaf(QName.create(exampleNamespace, exampleRevision, "another-parameter"), "fred");
+
+        rootBuilder.add(inputBuilder.toInstance());
+        final ImmutableCompositeNode root = rootBuilder.toInstance();
+
+        final NetconfMessage message = messageTransformer.toRpcRequest(myOwnMethodRpcQName, root);
         assertNotNull(message);
+
+        final Document xmlDoc = message.getDocument();
+        final org.w3c.dom.Node rpcChild = xmlDoc.getFirstChild();
+        assertEquals(rpcChild.getLocalName(), "rpc");
+
+        final org.w3c.dom.Node myOwnMethodNode = rpcChild.getFirstChild();
+        assertEquals(myOwnMethodNode.getLocalName(), "my-own-method");
+
+        final org.w3c.dom.Node firstParamNode = myOwnMethodNode.getFirstChild();
+        assertEquals(firstParamNode.getLocalName(), "my-first-parameter");
+
+        final org.w3c.dom.Node secParamNode = firstParamNode.getNextSibling();
+        assertEquals(secParamNode.getLocalName(), "another-parameter");
     }
 }
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/resources/netconf-state.schemas.payload.xml b/opendaylight/md-sal/sal-netconf-connector/src/test/resources/netconf-state.schemas.payload.xml
new file mode 100644 (file)
index 0000000..649ecb7
--- /dev/null
@@ -0,0 +1,514 @@
+<ncm:schemas xmlns:ncm="urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring">
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:threadpool</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>threadpool</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-04-09</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:logback:config</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>config-logging</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-07-16</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:model:statistics:types</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-statistics-types</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-09-25</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:config-dom-store</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-config-dom-datastore</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2014-06-17</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:flow:table:statistics</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-flow-table-statistics</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-12-15</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:meter:service</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>sal-meter</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-09-18</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>toaster-provider-impl</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2014-01-31</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:table:types</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-table-types</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-10-26</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:table:service</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>sal-table</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-10-26</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:shutdown</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>shutdown</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-12-18</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:port:service</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>sal-port</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-11-07</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>netty-event-executor</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-11-12</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>sal-remote</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2014-01-14</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:model:topology:view</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-topology-view</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-10-30</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>threadgroup</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-11-07</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:TBD:params:xml:ns:yang:network-topology</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>network-topology</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-07-12</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:fixed</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>threadpool-impl-fixed</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-12-01</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-sal-binding-broker-impl</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-10-28</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:ietf:params:xml:ns:yang:ietf-restconf</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>ietf-restconf</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-10-19</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:node:error:service</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>node-error</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2014-04-10</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:flow:errors</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>flow-errors</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-11-16</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:flow:service</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>sal-flow</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-08-19</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:ietf:params:xml:ns:yang:rpc-context</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>rpc-context</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-06-17</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:operational-dom-store
+        </ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-operational-dom-datastore</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2014-06-17</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:flow:types:queue</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-queue-types</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-09-25</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>ietf-netconf-monitoring</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2010-10-04</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:netconf-node-inventory</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>netconf-node-inventory</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2014-01-08</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:ietf:params:xml:ns:yang:ietf-yang-types</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>ietf-yang-types</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-07-15</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:meter:statistics</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-meter-statistics</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-11-11</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:flow:inventory</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>flow-node-inventory</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-08-19</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>odl-sal-netconf-connector-cfg</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-10-28</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:scheduled</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>threadpool-impl-scheduled</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-12-01</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:TBD:params:xml:ns:yang:network-topology</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>network-topology</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-10-21</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>http://netconfcentral.org/ns/toaster</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>toaster</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2009-11-20</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:config:netconf</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>odl-netconf-cfg</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2014-04-08</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:meter:types</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-meter-types</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-09-18</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-sal-dom-broker-impl</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-10-28</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:flow:topology:discovery</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>flow-topology-discovery</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-08-19</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:yang:extension:yang-ext</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>yang-ext</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-07-09</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>threadpool-impl</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-04-05</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:flow:types:port</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-port-types</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-09-25</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-md-sal-binding</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-10-28</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:packet:service</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>packet-processing</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-07-09</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>threadpool-impl-flexible</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-12-01</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:queue:service</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>sal-queue</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-11-07</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:ietf:params:xml:ns:yang:ietf-inet-types</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>ietf-inet-types</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2010-09-24</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:rest:connector</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-rest-connector</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2014-07-24</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:flow:transaction</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>flow-capable-transaction</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-11-03</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:flow:statistics</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-flow-statistics</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-08-19</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:protocol:framework</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>protocol-framework</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2014-03-13</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:model:match:types</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-match-types</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-10-26</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:ietf:params:xml:ns:yang:ietf-yang-types</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>ietf-yang-types</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2010-09-24</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:group:service</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>sal-group</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-09-18</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:inmemory-datastore-provider</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-inmemory-datastore-provider</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2014-06-17</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:netty:timer</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>netty-timer</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-11-19</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:group:statistics</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-group-statistics</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-11-11</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:config</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>config</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-04-05</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>odl-netconfig-client-cfg</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2014-04-08</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:l2:types</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-l2-types</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-08-27</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:action:types</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-action-types</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-11-12</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-md-sal-dom</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-10-28</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:common</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-md-sal-common</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-10-28</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:group:types</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-group-types</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-10-18</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring-extension</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>ietf-netconf-monitoring-extension</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-12-10</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:inventory</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-inventory</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-08-19</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:netty</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>netty</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-11-19</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:model:topology:general</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-topology</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-10-30</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:port:statistics</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-port-statistics</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version></ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:queue:statistics</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-queue-statistics</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-12-16</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>kitchen-service-impl</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2014-01-31</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:flow:types</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-flow-types</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-10-26</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:shutdown:impl</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>shutdown-impl</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-12-18</ncm:version>
+    </ncm:schema>
+    <ncm:schema>
+        <ncm:namespace>urn:opendaylight:model:topology:inventory</ncm:namespace>
+        <ncm:location>NETCONF</ncm:location>
+        <ncm:identifier>opendaylight-topology-inventory</ncm:identifier>
+        <ncm:format>yang</ncm:format>
+        <ncm:version>2013-10-30</ncm:version>
+    </ncm:schema>
+</ncm:schemas>
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/resources/schemas/config-test-rpc.yang b/opendaylight/md-sal/sal-netconf-connector/src/test/resources/schemas/config-test-rpc.yang
new file mode 100644 (file)
index 0000000..f67c2df
--- /dev/null
@@ -0,0 +1,167 @@
+module config-test-rpc {
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:test:rpc:config:defs";
+    prefix "rpc";
+
+    organization
+    "Cisco Systems, Inc.";
+
+    contact
+    "lsedlak@cisco.com";
+
+    description "Test model containing hacked definition of rpc edit-config and definitions for
+        get and get-config rpc operations.
+        The rpc definition is copied from rfc 6241 Appendix C: http://tools.ietf.org/html/rfc6241#appendix-C";
+
+    revision 2014-07-21 {
+        description "Initial revision.";
+    }
+    
+    extension get-filter-element-attributes {
+          description
+            "If this extension is present within an 'anyxml'
+             statement named 'filter', which must be conceptually
+             defined within the RPC input section for the <get>
+             and <get-config> protocol operations, then the
+             following unqualified XML attribute is supported
+             within the <filter> element, within a <get> or
+             <get-config> protocol operation:
+    
+               type : optional attribute with allowed
+                      value strings 'subtree' and 'xpath'.
+                      If missing, the default value is 'subtree'.
+    
+             If the 'xpath' feature is supported, then the
+             following unqualified XML attribute is
+             also supported:
+    
+               select: optional attribute containing a
+                       string representing an XPath expression.
+                       The 'type' attribute must be equal to 'xpath'
+                       if this attribute is present.";
+    }
+    
+    rpc edit-config {
+        description "The <edit-config> operation loads all or part of a specified
+             configuration to the specified target configuration.";
+
+        reference "RFC 6241, Section 7.2";
+
+        input {
+            container target {
+                description "Particular configuration to edit.";
+
+                choice config-target {
+                    mandatory true;
+                    description "The configuration target.";
+
+                    leaf candidate {
+                        if-feature candidate;
+                        type empty;
+                        description "The candidate configuration is the config target.";
+                    }
+
+                    leaf running {
+                        if-feature writable-running;
+                        type empty;
+                        description "The running configuration is the config source.";
+                    }
+                }
+            }
+
+            choice edit-content {
+                mandatory true;
+                description "The content for the edit operation.";
+
+                anyxml config {
+                    description
+                      "Inline Config content.";
+                }
+
+                leaf url {
+                    if-feature url;
+                    type string;
+                    description
+                      "URL-based config content.";
+                }
+            }
+        }
+    }
+
+    rpc get-config {
+      description
+        "Retrieve all or part of a specified configuration.";
+
+      reference "RFC 6241, Section 7.1";
+
+      input {
+        container source {
+          description "Particular configuration to retrieve.";
+
+            choice config-source {
+                mandatory true;
+                description
+                  "The configuration to retrieve.";
+                leaf candidate {
+                  if-feature candidate;
+                  type empty;
+                  description
+                    "The candidate configuration is the config source.";
+                }
+                leaf running {
+                  type empty;
+                  description
+                    "The running configuration is the config source.";
+                }
+                leaf startup {
+                  if-feature startup;
+                  type empty;
+                  description
+                    "The startup configuration is the config source.
+                     This is optional-to-implement on the server because
+                     not all servers will support filtering for this
+                     datastore.";
+                }
+            }
+        }
+
+        anyxml filter {
+            description "Subtree or XPath filter to use.";
+                get-filter-element-attributes;
+            }
+        }
+
+        output {
+            anyxml data {
+              description
+                "Copy of the source datastore subset that matched
+                 the filter criteria (if any).  An empty data container
+                 indicates that the request did not produce any results.";
+            }
+        }
+    }
+
+    rpc get {
+        description "Retrieve running configuration and device state information.";
+
+        reference "RFC 6241, Section 7.7";
+
+        input {
+            anyxml filter {
+              description
+                "This parameter specifies the portion of the system
+                 configuration and state data to retrieve.";
+              get-filter-element-attributes;
+            }
+        }
+
+        output {
+            anyxml data {
+              description
+                "Copy of the running datastore subset and/or state
+                 data that matched the filter criteria (if any).
+                 An empty data container indicates that the request did not
+                 produce any results.";
+            }
+        }
+    }
+}
index ce3bfe9a4c81a65decaf51625c7505c07cafc05e..674c5bf5a596bb03a34f785d854ffdb305aac12b 100644 (file)
       <groupId>com.typesafe.akka</groupId>
       <artifactId>akka-testkit_${scala.version}</artifactId>
     </dependency>
+    <dependency>
+      <groupId>com.typesafe.akka</groupId>
+      <artifactId>akka-osgi_${scala.version}</artifactId>
+    </dependency>
 
+  <dependency>
+     <groupId>com.typesafe.akka</groupId>
+     <artifactId>akka-slf4j_${scala.version}</artifactId>
+  </dependency>
     <!-- SAL Dependencies -->
 
     <dependency>
       <scope>test</scope>
     </dependency>
 
-    <dependency>
+      <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-simple</artifactId>
       <version>${slf4j.version}</version>
index 9824889b8023d4e31e20d835731c59ef7047c314..2be8ba47b99f9881304f58eeee3dede71497821c 100644 (file)
@@ -2,8 +2,10 @@ package org.opendaylight.controller.config.yang.config.remote_rpc_connector;
 
 import org.opendaylight.controller.remote.rpc.RemoteRpcProviderFactory;
 import org.opendaylight.controller.sal.core.api.Broker;
+import org.osgi.framework.BundleContext;
 
 public class RemoteRPCBrokerModule extends org.opendaylight.controller.config.yang.config.remote_rpc_connector.AbstractRemoteRPCBrokerModule {
+  private BundleContext bundleContext;
   public RemoteRPCBrokerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
     super(identifier, dependencyResolver);
   }
@@ -20,6 +22,10 @@ public class RemoteRPCBrokerModule extends org.opendaylight.controller.config.ya
   @Override
   public java.lang.AutoCloseable createInstance() {
     Broker broker = getDomBrokerDependency();
-    return RemoteRpcProviderFactory.createInstance(broker);
+    return RemoteRpcProviderFactory.createInstance(broker, bundleContext);
+  }
+
+  public void setBundleContext(BundleContext bundleContext) {
+    this.bundleContext = bundleContext;
   }
 }
index 330845b14fc28bedbc9268467a2fa5075addc5a4..f97338d32971c277de5f258c15c94102f94120a6 100644 (file)
 package org.opendaylight.controller.config.yang.config.remote_rpc_connector;
 
 
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
+import org.opendaylight.controller.config.spi.Module;
+import org.osgi.framework.BundleContext;
+
 public class RemoteRPCBrokerModuleFactory extends org.opendaylight.controller.config.yang.config.remote_rpc_connector.AbstractRemoteRPCBrokerModuleFactory {
+  @Override
+  public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
+    RemoteRPCBrokerModule module = (RemoteRPCBrokerModule)super.createModule(instanceName,dependencyResolver,bundleContext);
+    module.setBundleContext(bundleContext);
+    return module;
+  }
 
+  @Override
+  public Module createModule(String instanceName, DependencyResolver dependencyResolver,
+                             DynamicMBeanWithInstance old, BundleContext bundleContext) throws Exception {
+    RemoteRPCBrokerModule module = (RemoteRPCBrokerModule)super.createModule(instanceName, dependencyResolver,
+        old, bundleContext);
+    module.setBundleContext(bundleContext);
+    return module;
+  }
 }
index 4a6124a3bc37fbf2a46079dd82df6f1d3ba80283..f1ca3ccd505e1b1732ad906f75f3662368fdc4a2 100644 (file)
@@ -9,25 +9,38 @@
 package org.opendaylight.controller.remote.rpc;
 
 import akka.actor.ActorSystem;
-import akka.actor.Props;
-import com.google.common.base.Function;
+import akka.osgi.BundleDelegatingClassLoader;
 import com.typesafe.config.ConfigFactory;
+import org.osgi.framework.BundleContext;
 
-import javax.annotation.Nullable;
 
 public class ActorSystemFactory {
-    private static final ActorSystem actorSystem = (new Function<Void, ActorSystem>(){
+ private static volatile ActorSystem actorSystem = null;
 
-        @Nullable @Override public ActorSystem apply(@Nullable Void aVoid) {
-                ActorSystem system =
-                    ActorSystem.create("opendaylight-rpc", ConfigFactory
-                        .load().getConfig("odl-cluster"));
-                system.actorOf(Props.create(TerminationMonitor.class), "termination-monitor");
-                return system;
-        }
-    }).apply(null);
+  public static final ActorSystem getInstance(){
+     return actorSystem;
+  }
 
-    public static final ActorSystem getInstance(){
-        return actorSystem;
+  /**
+   * This method should be called only once during initialization
+   *
+   * @param bundleContext
+   */
+  public static final void createInstance(final BundleContext bundleContext) {
+    if(actorSystem == null) {
+      // Create an OSGi bundle classloader for actor system
+      BundleDelegatingClassLoader classLoader = new BundleDelegatingClassLoader(bundleContext.getBundle(),
+          Thread.currentThread().getContextClassLoader());
+      synchronized (ActorSystemFactory.class) {
+        // Double check
+        if (actorSystem == null) {
+          ActorSystem system = ActorSystem.create("opendaylight-cluster-rpc",
+              ConfigFactory.load().getConfig("odl-cluster-rpc"), classLoader);
+          actorSystem = system;
+        }
+      }
+    } else {
+      throw new IllegalStateException("Actor system should be created only once. Use getInstance method to access existing actor system");
     }
+  }
 }
index 4c40ca177756877f121f0c5187b747241342655c..fc75f7747a0d25361c96f96e77aac30538bb05a5 100644 (file)
@@ -11,9 +11,12 @@ package org.opendaylight.controller.remote.rpc;
 
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.osgi.framework.BundleContext;
 
 public class RemoteRpcProviderFactory {
-    public static RemoteRpcProvider createInstance(final Broker broker){
+    public static RemoteRpcProvider createInstance(final Broker broker, final BundleContext bundleContext){
+
+      ActorSystemFactory.createInstance(bundleContext);
       RemoteRpcProvider rpcProvider =
           new RemoteRpcProvider(ActorSystemFactory.getInstance(), (RpcProvisionRegistry) broker);
       broker.registerProvider(rpcProvider);
index 5c56455bd0c208a40709b4a221fb6a22ed0b65a1..514a2f141daea13e5e71ec1f0f0a8acf9eadcf9d 100644 (file)
@@ -17,7 +17,7 @@ import akka.japi.Creator;
 import akka.japi.Function;
 import org.opendaylight.controller.remote.rpc.messages.UpdateSchemaContext;
 import org.opendaylight.controller.remote.rpc.registry.ClusterWrapper;
-import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
+import org.opendaylight.controller.remote.rpc.registry.RpcRegistryOld;
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -72,7 +72,7 @@ public class RpcManager extends AbstractUntypedActor {
   private void createRpcActors() {
     LOG.debug("Create rpc registry and broker actors");
 
-    rpcRegistry = getContext().actorOf(RpcRegistry.props(clusterWrapper), ActorConstants.RPC_REGISTRY);
+    rpcRegistry = getContext().actorOf(RpcRegistryOld.props(clusterWrapper), ActorConstants.RPC_REGISTRY);
     rpcBroker = getContext().actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext), ActorConstants.RPC_BROKER);
   }
 
index 5e19653a22d21ed83ae3eec370290dc37f50c1ce..c25aa523e2e0823769a28e9dc01b32da711b0ae5 100644 (file)
  * 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.remote.rpc.registry;
 
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import akka.actor.ActorRef;
+import akka.japi.Option;
+import akka.japi.Pair;
+import org.opendaylight.controller.remote.rpc.registry.gossip.Copier;
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
 
+import java.io.Serializable;
 import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-public class RoutingTable<I, R> {
-
-  private final Logger LOG = LoggerFactory.getLogger(RoutingTable.class);
-
-  private ConcurrentMap<I,R> globalRpcMap = new ConcurrentHashMap<>();
-  private ConcurrentMap<I, LinkedHashSet<R>> routedRpcMap = new ConcurrentHashMap<>();
-
-  public ConcurrentMap<I, R> getGlobalRpcMap() {
-    return globalRpcMap;
-  }
-
-  public ConcurrentMap<I, LinkedHashSet<R>> getRoutedRpcMap() {
-    return routedRpcMap;
-  }
-
-  public R getGlobalRoute(final I routeId) {
-    Preconditions.checkNotNull(routeId, "getGlobalRoute: routeId cannot be null!");
-    return globalRpcMap.get(routeId);
-  }
-
-  public void addGlobalRoute(final I routeId, final R route) {
-    Preconditions.checkNotNull(routeId, "addGlobalRoute: routeId cannot be null!");
-    Preconditions.checkNotNull(route, "addGlobalRoute: route cannot be null!");
-    LOG.debug("addGlobalRoute: adding  a new route with id[{}] and value [{}]", routeId, route);
-    if(globalRpcMap.putIfAbsent(routeId, route) != null) {
-      LOG.debug("A route already exist for route id [{}] ", routeId);
-    }
-  }
+import java.util.HashMap;
+import java.util.Map;
 
-  public void removeGlobalRoute(final I routeId) {
-    Preconditions.checkNotNull(routeId, "removeGlobalRoute: routeId cannot be null!");
-    LOG.debug("removeGlobalRoute: removing  a new route with id [{}]", routeId);
-    globalRpcMap.remove(routeId);
-  }
+public class RoutingTable implements Copier<RoutingTable>, Serializable {
 
-  public Set<R> getRoutedRpc(final I routeId) {
-    Preconditions.checkNotNull(routeId, "getRoutes: routeId cannot be null!");
-    Set<R> routes = routedRpcMap.get(routeId);
-
-    if (routes == null) {
-      return Collections.emptySet();
-    }
+    private Map<RpcRouter.RouteIdentifier<?, ?, ?>, Long> table = new HashMap<>();
+    private ActorRef router;
 
-    return ImmutableSet.copyOf(routes);
-  }
+    @Override
+    public RoutingTable copy() {
+        RoutingTable copy = new RoutingTable();
+        copy.setTable(Collections.unmodifiableMap(table));
+        copy.setRouter(this.getRouter());
 
-  public R getLastAddedRoutedRpc(final I routeId) {
+        return copy;
+    }
 
-    Set<R> routes = getRoutedRpc(routeId);
+    public Option<Pair<ActorRef, Long>> getRouterFor(RpcRouter.RouteIdentifier<?, ?, ?> routeId){
+        Long updatedTime = table.get(routeId);
 
-    if (routes.isEmpty()) {
-      return null;
+        if (updatedTime == null || router == null)
+            return Option.none();
+        else
+            return Option.option(new Pair<>(router, updatedTime));
     }
 
-    R route = null;
-    Iterator<R> iter = routes.iterator();
-    while (iter.hasNext()) {
-      route = iter.next();
+    public void addRoute(RpcRouter.RouteIdentifier<?,?,?> routeId){
+        table.put(routeId, System.currentTimeMillis());
     }
 
-    return route;
-  }
-
-  public void addRoutedRpc(final I routeId, final R route)   {
-    Preconditions.checkNotNull(routeId, "addRoute: routeId cannot be null");
-    Preconditions.checkNotNull(route, "addRoute: route cannot be null");
-    LOG.debug("addRoute: adding a route with k/v [{}/{}]", routeId, route);
-    threadSafeAdd(routeId, route);
-  }
-
-  public void addRoutedRpcs(final Set<I> routeIds, final R route) {
-    Preconditions.checkNotNull(routeIds, "addRoutes: routeIds must not be null");
-    for (I routeId : routeIds){
-      addRoutedRpc(routeId, route);
+    public void removeRoute(RpcRouter.RouteIdentifier<?, ?, ?> routeId){
+        table.remove(routeId);
     }
-  }
 
-  public void removeRoute(final I routeId, final R route) {
-    Preconditions.checkNotNull(routeId, "removeRoute: routeId cannot be null!");
-    Preconditions.checkNotNull(route, "removeRoute: route cannot be null!");
-
-    LinkedHashSet<R> routes = routedRpcMap.get(routeId);
-    if (routes == null) {
-      return;
-    }
-    LOG.debug("removeRoute: removing  a new route with k/v [{}/{}]", routeId, route);
-    threadSafeRemove(routeId, route);
-  }
-
-  public void removeRoutes(final Set<I> routeIds, final R route) {
-    Preconditions.checkNotNull(routeIds, "removeRoutes: routeIds must not be null");
-    for (I routeId : routeIds){
-      removeRoute(routeId, route);
+    public Boolean contains(RpcRouter.RouteIdentifier<?, ?, ?> routeId){
+        return table.containsKey(routeId);
     }
-  }
-
-  /**
-   * This method guarantees that no 2 thread over write each other's changes.
-   * Just so that we dont end up in infinite loop, it tries for 100 times then throw
-   */
-  private void threadSafeAdd(final I routeId, final R route) {
 
-    for (int i=0;i<100;i++){
+    ///
+    /// Getter, Setters
+    ///
+    //TODO: Remove public
+    public Map<RpcRouter.RouteIdentifier<?, ?, ?>, Long> getTable() {
+        return table;
+    }
 
-      LinkedHashSet<R> updatedRoutes = new LinkedHashSet<>();
-      updatedRoutes.add(route);
-      LinkedHashSet<R> oldRoutes = routedRpcMap.putIfAbsent(routeId, updatedRoutes);
-      if (oldRoutes == null) {
-        return;
-      }
+    void setTable(Map<RpcRouter.RouteIdentifier<?, ?, ?>, Long> table) {
+        this.table = table;
+    }
 
-      updatedRoutes = new LinkedHashSet<>(oldRoutes);
-      updatedRoutes.add(route);
+    public ActorRef getRouter() {
+        return router;
+    }
 
-      if (routedRpcMap.replace(routeId, oldRoutes, updatedRoutes)) {
-        return;
-      }
+    public void setRouter(ActorRef router) {
+        this.router = router;
     }
-    //the method did not already return means it failed to add route in 100 attempts
-    throw new IllegalStateException("Failed to add route [" + routeId + "]");
-  }
-
-  /**
-   * This method guarantees that no 2 thread over write each other's changes.
-   * Just so that we dont end up in infinite loop, it tries for 100 times then throw
-   */
-  private void threadSafeRemove(final I routeId, final R route) {
-    LinkedHashSet<R> updatedRoutes = null;
-    for (int i=0;i<100;i++){
-      LinkedHashSet<R> oldRoutes = routedRpcMap.get(routeId);
-
-      // if route to be deleted is the only entry in the set then remove routeId from the cache
-      if ((oldRoutes.size() == 1) && oldRoutes.contains(route)){
-        routedRpcMap.remove(routeId);
-        return;
-      }
-
-      // if there are multiple routes for this routeId, remove the route to be deleted only from the set.
-      updatedRoutes = new LinkedHashSet<>(oldRoutes);
-      updatedRoutes.remove(route);
-      if (routedRpcMap.replace(routeId, oldRoutes, updatedRoutes)) {
-        return;
-      }
 
+    @Override
+    public String toString() {
+        return "RoutingTable{" +
+                "table=" + table +
+                ", router=" + router +
+                '}';
     }
-    //the method did not already return means it failed to remove route in 100 attempts
-    throw new IllegalStateException("Failed to remove route [" + routeId + "]");
-  }
 }
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RoutingTableOld.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RoutingTableOld.java
new file mode 100644 (file)
index 0000000..5951776
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.remote.rpc.registry;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public class RoutingTableOld<I, R> {
+
+  private final Logger LOG = LoggerFactory.getLogger(RoutingTableOld.class);
+
+  private ConcurrentMap<I,R> globalRpcMap = new ConcurrentHashMap<>();
+  private ConcurrentMap<I, LinkedHashSet<R>> routedRpcMap = new ConcurrentHashMap<>();
+
+  public ConcurrentMap<I, R> getGlobalRpcMap() {
+    return globalRpcMap;
+  }
+
+  public ConcurrentMap<I, LinkedHashSet<R>> getRoutedRpcMap() {
+    return routedRpcMap;
+  }
+
+  public R getGlobalRoute(final I routeId) {
+    Preconditions.checkNotNull(routeId, "getGlobalRoute: routeId cannot be null!");
+    return globalRpcMap.get(routeId);
+  }
+
+  public void addGlobalRoute(final I routeId, final R route) {
+    Preconditions.checkNotNull(routeId, "addGlobalRoute: routeId cannot be null!");
+    Preconditions.checkNotNull(route, "addGlobalRoute: route cannot be null!");
+    LOG.debug("addGlobalRoute: adding  a new route with id[{}] and value [{}]", routeId, route);
+    if(globalRpcMap.putIfAbsent(routeId, route) != null) {
+      LOG.debug("A route already exist for route id [{}] ", routeId);
+    }
+  }
+
+  public void removeGlobalRoute(final I routeId) {
+    Preconditions.checkNotNull(routeId, "removeGlobalRoute: routeId cannot be null!");
+    LOG.debug("removeGlobalRoute: removing  a new route with id [{}]", routeId);
+    globalRpcMap.remove(routeId);
+  }
+
+  public Set<R> getRoutedRpc(final I routeId) {
+    Preconditions.checkNotNull(routeId, "getRoutes: routeId cannot be null!");
+    Set<R> routes = routedRpcMap.get(routeId);
+
+    if (routes == null) {
+      return Collections.emptySet();
+    }
+
+    return ImmutableSet.copyOf(routes);
+  }
+
+  public R getLastAddedRoutedRpc(final I routeId) {
+
+    Set<R> routes = getRoutedRpc(routeId);
+
+    if (routes.isEmpty()) {
+      return null;
+    }
+
+    R route = null;
+    Iterator<R> iter = routes.iterator();
+    while (iter.hasNext()) {
+      route = iter.next();
+    }
+
+    return route;
+  }
+
+  public void addRoutedRpc(final I routeId, final R route)   {
+    Preconditions.checkNotNull(routeId, "addRoute: routeId cannot be null");
+    Preconditions.checkNotNull(route, "addRoute: route cannot be null");
+    LOG.debug("addRoute: adding a route with k/v [{}/{}]", routeId, route);
+    threadSafeAdd(routeId, route);
+  }
+
+  public void addRoutedRpcs(final Set<I> routeIds, final R route) {
+    Preconditions.checkNotNull(routeIds, "addRoutes: routeIds must not be null");
+    for (I routeId : routeIds){
+      addRoutedRpc(routeId, route);
+    }
+  }
+
+  public void removeRoute(final I routeId, final R route) {
+    Preconditions.checkNotNull(routeId, "removeRoute: routeId cannot be null!");
+    Preconditions.checkNotNull(route, "removeRoute: route cannot be null!");
+
+    LinkedHashSet<R> routes = routedRpcMap.get(routeId);
+    if (routes == null) {
+      return;
+    }
+    LOG.debug("removeRoute: removing  a new route with k/v [{}/{}]", routeId, route);
+    threadSafeRemove(routeId, route);
+  }
+
+  public void removeRoutes(final Set<I> routeIds, final R route) {
+    Preconditions.checkNotNull(routeIds, "removeRoutes: routeIds must not be null");
+    for (I routeId : routeIds){
+      removeRoute(routeId, route);
+    }
+  }
+
+  /**
+   * This method guarantees that no 2 thread over write each other's changes.
+   * Just so that we dont end up in infinite loop, it tries for 100 times then throw
+   */
+  private void threadSafeAdd(final I routeId, final R route) {
+
+    for (int i=0;i<100;i++){
+
+      LinkedHashSet<R> updatedRoutes = new LinkedHashSet<>();
+      updatedRoutes.add(route);
+      LinkedHashSet<R> oldRoutes = routedRpcMap.putIfAbsent(routeId, updatedRoutes);
+      if (oldRoutes == null) {
+        return;
+      }
+
+      updatedRoutes = new LinkedHashSet<>(oldRoutes);
+      updatedRoutes.add(route);
+
+      if (routedRpcMap.replace(routeId, oldRoutes, updatedRoutes)) {
+        return;
+      }
+    }
+    //the method did not already return means it failed to add route in 100 attempts
+    throw new IllegalStateException("Failed to add route [" + routeId + "]");
+  }
+
+  /**
+   * This method guarantees that no 2 thread over write each other's changes.
+   * Just so that we dont end up in infinite loop, it tries for 100 times then throw
+   */
+  private void threadSafeRemove(final I routeId, final R route) {
+    LinkedHashSet<R> updatedRoutes = null;
+    for (int i=0;i<100;i++){
+      LinkedHashSet<R> oldRoutes = routedRpcMap.get(routeId);
+
+      // if route to be deleted is the only entry in the set then remove routeId from the cache
+      if ((oldRoutes.size() == 1) && oldRoutes.contains(route)){
+        routedRpcMap.remove(routeId);
+        return;
+      }
+
+      // if there are multiple routes for this routeId, remove the route to be deleted only from the set.
+      updatedRoutes = new LinkedHashSet<>(oldRoutes);
+      updatedRoutes.remove(route);
+      if (routedRpcMap.replace(routeId, oldRoutes, updatedRoutes)) {
+        return;
+      }
+
+    }
+    //the method did not already return means it failed to remove route in 100 attempts
+    throw new IllegalStateException("Failed to remove route [" + routeId + "]");
+  }
+}
index e36060cc13ece309f04f10adebdb74a62f158146..51609870cc4aad1c8789dfdcd0b68f04563b5cdf 100644 (file)
  */
 package org.opendaylight.controller.remote.rpc.registry;
 
-import akka.actor.ActorSelection;
+import akka.actor.ActorRef;
 import akka.actor.Address;
 import akka.actor.Props;
-import akka.cluster.ClusterEvent;
-import akka.cluster.Member;
-import akka.japi.Creator;
-import org.opendaylight.controller.remote.rpc.AbstractUntypedActor;
-import org.opendaylight.controller.remote.rpc.ActorConstants;
-import org.opendaylight.controller.remote.rpc.messages.AddRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.AddRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpcReply;
-import org.opendaylight.controller.remote.rpc.messages.GetRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRpcReply;
-import org.opendaylight.controller.remote.rpc.messages.RemoveRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.RemoveRpc;
-import org.opendaylight.controller.remote.rpc.messages.RoutingTableData;
+import akka.actor.UntypedActor;
+import akka.dispatch.Mapper;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import akka.japi.Option;
+import akka.japi.Pair;
+import akka.pattern.Patterns;
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.remote.rpc.registry.gossip.Bucket;
+import org.opendaylight.controller.remote.rpc.registry.gossip.BucketStore;
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import scala.collection.JavaConversions;
+import scala.concurrent.Future;
 
-import java.util.LinkedHashSet;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
+
+import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.AddOrUpdateRoute;
+import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.RemoveRoute;
+import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.SetLocalRouter;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetAllBuckets;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetAllBucketsReply;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetLocalBucket;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetLocalBucketReply;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.UpdateBucket;
 
 /**
- * This Actor maintains the routing table state and sync it with other nodes in the cluster.
- *
- * A scheduler runs after an interval of time, which pick a random member from the cluster
- * and send the current state of routing table to the member.
+ * Registry to look up cluster nodes that have registered for a given rpc.
+ * <p>
+ * It uses {@link org.opendaylight.controller.remote.rpc.registry.gossip.BucketStore} to maintain this
+ * cluster wide information.
  *
- * when a message of routing table data is received, it gets merged with the local routing table
- * to keep the latest data.
  */
+public class RpcRegistry extends UntypedActor {
+
+    final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
+
+    /**
+     * Store to keep the registry. Bucket store sync's it across nodes in the cluster
+     */
+    private ActorRef bucketStore;
+
+    /**
+     * Rpc broker that would use the registry to route requests.
+     */
+    private ActorRef localRouter;
 
-public class RpcRegistry extends AbstractUntypedActor {
-
-  private static final Logger LOG = LoggerFactory.getLogger(RpcRegistry.class);
-  private RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable;
-  private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
-  private final ClusterWrapper clusterWrapper;
-  private final ScheduledFuture<?> syncScheduler;
-
-  private RpcRegistry(ClusterWrapper clusterWrapper){
-    this.routingTable = new RoutingTable<>();
-    this.clusterWrapper = clusterWrapper;
-    this.syncScheduler = scheduler.scheduleAtFixedRate(new SendRoutingTable(), 10, 10, TimeUnit.SECONDS);
-  }
-
-  public static Props props(final ClusterWrapper clusterWrapper){
-    return Props.create(new Creator<RpcRegistry>(){
-
-      @Override
-      public RpcRegistry create() throws Exception {
-        return new RpcRegistry(clusterWrapper);
-      }
-    });
-  }
-
-  @Override
-  protected void handleReceive(Object message) throws Exception {
-    LOG.debug("Received message {}", message);
-    if(message instanceof RoutingTableData) {
-      syncRoutingTable((RoutingTableData) message);
-    } else if(message instanceof GetRoutedRpc) {
-      getRoutedRpc((GetRoutedRpc) message);
-    } else if(message instanceof GetRpc) {
-      getRpc((GetRpc) message);
-    } else if(message instanceof AddRpc) {
-      addRpc((AddRpc) message);
-    } else if(message instanceof RemoveRpc) {
-      removeRpc((RemoveRpc) message);
-    } else if(message instanceof AddRoutedRpc) {
-      addRoutedRpc((AddRoutedRpc) message);
-    } else if(message instanceof RemoveRoutedRpc) {
-      removeRoutedRpc((RemoveRoutedRpc) message);
+    public RpcRegistry() {
+        bucketStore = getContext().actorOf(Props.create(BucketStore.class), "store");
     }
-  }
 
-  private void getRoutedRpc(GetRoutedRpc rpcMsg){
-    LOG.debug("Get latest routed Rpc location from routing table {}", rpcMsg);
-    String remoteActorPath = routingTable.getLastAddedRoutedRpc(rpcMsg.getRouteId());
-    GetRoutedRpcReply routedRpcReply = new GetRoutedRpcReply(remoteActorPath);
+    public RpcRegistry(ActorRef bucketStore) {
+        this.bucketStore = bucketStore;
+    }
+
+    @Override
+    public void onReceive(Object message) throws Exception {
 
-    getSender().tell(routedRpcReply, self());
-  }
+        log.debug("Received message: message [{}]", message);
 
-  private void getRpc(GetRpc rpcMsg) {
-    LOG.debug("Get global Rpc location from routing table {}", rpcMsg);
-    String remoteActorPath = routingTable.getGlobalRoute(rpcMsg.getRouteId());
-    GetRpcReply rpcReply = new GetRpcReply(remoteActorPath);
+        //TODO: if sender is remote, reject message
 
-    getSender().tell(rpcReply, self());
-  }
+        if (message instanceof SetLocalRouter)
+            receiveSetLocalRouter((SetLocalRouter) message);
 
-  private void addRpc(AddRpc rpcMsg) {
-    LOG.debug("Add Rpc to routing table {}", rpcMsg);
-    routingTable.addGlobalRoute(rpcMsg.getRouteId(), rpcMsg.getActorPath());
+        if (message instanceof AddOrUpdateRoute)
+            receiveAddRoute((AddOrUpdateRoute) message);
 
-    getSender().tell("Success", self());
-  }
+        else if (message instanceof RemoveRoute)
+            receiveRemoveRoute((RemoveRoute) message);
 
-  private void removeRpc(RemoveRpc rpcMsg) {
-    LOG.debug("Removing Rpc to routing table {}", rpcMsg);
-    routingTable.removeGlobalRoute(rpcMsg.getRouteId());
+        else if (message instanceof Messages.FindRouters)
+            receiveGetRouter((Messages.FindRouters) message);
+
+        else
+            unhandled(message);
+    }
 
-    getSender().tell("Success", self());
-  }
+    /**
+     * Register's rpc broker
+     *
+     * @param message contains {@link akka.actor.ActorRef} for rpc broker
+     */
+    private void receiveSetLocalRouter(SetLocalRouter message) {
+        if (message == null || message.getRouter() == null)
+            return;//ignore
 
-  private void addRoutedRpc(AddRoutedRpc rpcMsg) {
-    routingTable.addRoutedRpcs(rpcMsg.getAnnouncements(), rpcMsg.getActorPath());
-    getSender().tell("Success", self());
-  }
+        localRouter = message.getRouter();
+    }
 
-  private void removeRoutedRpc(RemoveRoutedRpc rpcMsg) {
-    routingTable.removeRoutes(rpcMsg.getAnnouncements(), rpcMsg.getActorPath());
-    getSender().tell("Success", self());
-  }
+    /**
+     * //TODO: update this to accept multiple route registration
+     * @param msg
+     */
+    private void receiveAddRoute(AddOrUpdateRoute msg) {
+        if (msg.getRouteIdentifier() == null)
+            return;//ignore
 
-  private void syncRoutingTable(RoutingTableData routingTableData) {
-    LOG.debug("Syncing routing table {}", routingTableData);
+        Preconditions.checkState(localRouter != null, "Router must be set first");
 
-    Map<RpcRouter.RouteIdentifier<?, ?, ?>, String> newRpcMap = routingTableData.getRpcMap();
-    Set<RpcRouter.RouteIdentifier<?, ?, ?>> routeIds = newRpcMap.keySet();
-    for(RpcRouter.RouteIdentifier<?, ?, ?> routeId : routeIds) {
-      routingTable.addGlobalRoute(routeId, newRpcMap.get(routeId));
+        Future<Object> futureReply = Patterns.ask(bucketStore, new GetLocalBucket(), 1000);
+        futureReply.map(getMapperToAddRoute(msg.getRouteIdentifier()), getContext().dispatcher());
     }
 
-    Map<RpcRouter.RouteIdentifier<?, ?, ?>, LinkedHashSet<String>> newRoutedRpcMap =
-        routingTableData.getRoutedRpcMap();
-    routeIds = newRoutedRpcMap.keySet();
+    /**
+     * //TODO: update this to accept multiple routes
+     * @param msg
+     */
+    private void receiveRemoveRoute(RemoveRoute msg) {
+        if (msg.getRouteIdentifier() == null)
+            return;//ignore
+
+        Future<Object> futureReply = Patterns.ask(bucketStore, new GetLocalBucket(), 1000);
+        futureReply.map(getMapperToRemoveRoute(msg.getRouteIdentifier()), getContext().dispatcher());
 
-    for(RpcRouter.RouteIdentifier<?, ?, ?> routeId : routeIds) {
-      Set<String> routeAddresses = newRoutedRpcMap.get(routeId);
-      for(String routeAddress : routeAddresses) {
-        routingTable.addRoutedRpc(routeId, routeAddress);
-      }
     }
-  }
-
-  private ActorSelection getRandomRegistryActor() {
-    ClusterEvent.CurrentClusterState clusterState = clusterWrapper.getState();
-    ActorSelection actor = null;
-    Set<Member> members = JavaConversions.asJavaSet(clusterState.members());
-    int memberSize = members.size();
-    // Don't select yourself
-    if(memberSize > 1) {
-      Address currentNodeAddress = clusterWrapper.getAddress();
-      int index = new Random().nextInt(memberSize);
-      int i = 0;
-      // keeping previous member, in case when random index member is same as current actor
-      // and current actor member is last in set
-      Member previousMember = null;
-      for(Member member : members){
-        if(i == index-1) {
-          previousMember = member;
+
+    /**
+     * Finds routers for the given rpc.
+     * @param msg
+     */
+    private void receiveGetRouter(Messages.FindRouters msg) {
+        final ActorRef sender = getSender();
+
+        //if empty message, return empty list
+        if (msg.getRouteIdentifier() == null) {
+            sender.tell(createEmptyReply(), getSelf());
+            return;
         }
-        if(i == index) {
-          if(!currentNodeAddress.equals(member.address())) {
-            actor = this.context().actorSelection(member.address() + ActorConstants.RPC_REGISTRY_PATH);
-            break;
-          } else if(index < memberSize-1){ // pick the next element in the set
-            index++;
-          }
+
+        Future<Object> futureReply = Patterns.ask(bucketStore, new GetAllBuckets(), 1000);
+        futureReply.map(getMapperToGetRouter(msg.getRouteIdentifier(), sender), getContext().dispatcher());
+
+    }
+
+    /**
+     * Helper to create empty reply when no routers are found
+     *
+     * @return
+     */
+    private Messages.FindRoutersReply createEmptyReply() {
+        List<Pair<ActorRef, Long>> routerWithUpdateTime = Collections.emptyList();
+        return new Messages.FindRoutersReply(routerWithUpdateTime);
+    }
+
+    /**
+     * Helper to create a reply when routers are found for the given rpc
+     * @param buckets
+     * @param routeId
+     * @return
+     */
+    private Messages.FindRoutersReply createReplyWithRouters(Map<Address, Bucket> buckets, RpcRouter.RouteIdentifier<?, ?, ?> routeId) {
+
+        List<Pair<ActorRef, Long>> routers = new ArrayList<>();
+
+        Option<Pair<ActorRef, Long>> routerWithUpdateTime = null;
+
+        for (Bucket bucket : buckets.values()) {
+
+            RoutingTable table = (RoutingTable) bucket.getData();
+
+            if (table == null)
+                continue;
+
+            routerWithUpdateTime = table.getRouterFor(routeId);
+
+            if (routerWithUpdateTime.isEmpty())
+                continue;
+
+            routers.add(routerWithUpdateTime.get());
         }
-        i++;
-      }
-      if(actor == null && previousMember != null) {
-        actor = this.context().actorSelection(previousMember.address() + ActorConstants.RPC_REGISTRY_PATH);
-      }
+
+        return new Messages.FindRoutersReply(routers);
     }
-    return actor;
-  }
 
-  private class SendRoutingTable implements Runnable {
 
-    @Override
-    public void run() {
-      RoutingTableData routingTableData =
-          new RoutingTableData(routingTable.getGlobalRpcMap(), routingTable.getRoutedRpcMap());
-      LOG.debug("Sending routing table for sync {}", routingTableData);
-      ActorSelection actor = getRandomRegistryActor();
-      if(actor != null) {
-        actor.tell(routingTableData, self());
-      }
+    ///
+    ///private factories to create Mapper
+    ///
+
+    /**
+     *  Receives all buckets returned from bucket store and finds routers for the buckets where given rpc(routeId) is found
+     *
+     * @param routeId the rpc
+     * @param sender  client who asked to find the routers.
+     * @return
+     */
+    private Mapper<Object, Void> getMapperToGetRouter(final RpcRouter.RouteIdentifier<?, ?, ?> routeId, final ActorRef sender) {
+        return new Mapper<Object, Void>() {
+            @Override
+            public Void apply(Object replyMessage) {
+
+                if (replyMessage instanceof GetAllBucketsReply) {
+
+                    GetAllBucketsReply reply = (GetAllBucketsReply) replyMessage;
+                    Map<Address, Bucket> buckets = reply.getBuckets();
+
+                    if (buckets == null || buckets.isEmpty()) {
+                        sender.tell(createEmptyReply(), getSelf());
+                        return null;
+                    }
+
+                    sender.tell(createReplyWithRouters(buckets, routeId), getSelf());
+                }
+                return null;
+            }
+        };
+    }
+
+    /**
+     * Receives local bucket from bucket store and updates routing table in it by removing the route. Subsequently,
+     * it updates the local bucket in bucket store.
+     *
+     * @param routeId rpc to remote
+     * @return
+     */
+    private Mapper<Object, Void> getMapperToRemoveRoute(final RpcRouter.RouteIdentifier<?, ?, ?> routeId) {
+        return new Mapper<Object, Void>() {
+            @Override
+            public Void apply(Object replyMessage) {
+                if (replyMessage instanceof GetLocalBucketReply) {
+
+                    GetLocalBucketReply reply = (GetLocalBucketReply) replyMessage;
+                    Bucket<RoutingTable> bucket = reply.getBucket();
+
+                    if (bucket == null) {
+                        log.debug("Local bucket is null");
+                        return null;
+                    }
+
+                    RoutingTable table = bucket.getData();
+                    if (table == null)
+                        table = new RoutingTable();
+
+                    table.setRouter(localRouter);
+                    table.removeRoute(routeId);
+
+                    bucket.setData(table);
+
+                    UpdateBucket updateBucketMessage = new UpdateBucket(bucket);
+                    bucketStore.tell(updateBucketMessage, getSelf());
+                }
+                return null;
+            }
+        };
+    }
+
+    /**
+     * Receives local bucket from bucket store and updates routing table in it by adding the route. Subsequently,
+     * it updates the local bucket in bucket store.
+     *
+     * @param routeId rpc to add
+     * @return
+     */
+    private Mapper<Object, Void> getMapperToAddRoute(final RpcRouter.RouteIdentifier<?, ?, ?> routeId) {
+
+        return new Mapper<Object, Void>() {
+            @Override
+            public Void apply(Object replyMessage) {
+                if (replyMessage instanceof GetLocalBucketReply) {
+
+                    GetLocalBucketReply reply = (GetLocalBucketReply) replyMessage;
+                    Bucket<RoutingTable> bucket = reply.getBucket();
+
+                    if (bucket == null) {
+                        log.debug("Local bucket is null");
+                        return null;
+                    }
+
+                    RoutingTable table = bucket.getData();
+                    if (table == null)
+                        table = new RoutingTable();
+
+                    table.setRouter(localRouter);
+                    table.addRoute(routeId);
+
+                    bucket.setData(table);
+
+                    UpdateBucket updateBucketMessage = new UpdateBucket(bucket);
+                    bucketStore.tell(updateBucketMessage, getSelf());
+                }
+
+                return null;
+            }
+        };
+    }
+
+    /**
+     * All messages used by the RpcRegistry
+     */
+    public static class Messages {
+
+
+        public static class ContainsRoute {
+            final RpcRouter.RouteIdentifier<?,?,?> routeIdentifier;
+
+            public ContainsRoute(RpcRouter.RouteIdentifier<?, ?, ?> routeIdentifier) {
+                Preconditions.checkArgument(routeIdentifier != null);
+                this.routeIdentifier = routeIdentifier;
+            }
+
+            public RpcRouter.RouteIdentifier<?,?,?> getRouteIdentifier(){
+                return this.routeIdentifier;
+            }
+
+            @Override
+            public String toString() {
+                return this.getClass().getSimpleName() + "{" +
+                        "routeIdentifier=" + routeIdentifier +
+                        '}';
+            }
+        }
+
+        public static class AddOrUpdateRoute extends ContainsRoute{
+
+            public AddOrUpdateRoute(RpcRouter.RouteIdentifier<?, ?, ?> routeIdentifier) {
+                super(routeIdentifier);
+            }
+        }
+
+        public static class RemoveRoute extends ContainsRoute {
+
+            public RemoveRoute(RpcRouter.RouteIdentifier<?, ?, ?> routeIdentifier) {
+                super(routeIdentifier);
+            }
+        }
+
+        public static class SetLocalRouter{
+            private final ActorRef router;
+
+            public SetLocalRouter(ActorRef router) {
+                this.router = router;
+            }
+
+            public ActorRef getRouter(){
+                return this.router;
+            }
+
+            @Override
+            public String toString() {
+                return "SetLocalRouter{" +
+                        "router=" + router +
+                        '}';
+            }
+        }
+
+        public static class FindRouters extends ContainsRoute {
+            public FindRouters(RpcRouter.RouteIdentifier<?, ?, ?> routeIdentifier) {
+                super(routeIdentifier);
+            }
+        }
+
+        public static class FindRoutersReply {
+            final List<Pair<ActorRef, Long>> routerWithUpdateTime;
+
+            public FindRoutersReply(List<Pair<ActorRef, Long>> routerWithUpdateTime) {
+                this.routerWithUpdateTime = routerWithUpdateTime;
+            }
+
+            public List<Pair<ActorRef, Long>> getRouterWithUpdateTime(){
+                return routerWithUpdateTime;
+            }
+
+            @Override
+            public String toString() {
+                return "FindRoutersReply{" +
+                        "routerWithUpdateTime=" + routerWithUpdateTime +
+                        '}';
+            }
+        }
     }
-  }
 }
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistryOld.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistryOld.java
new file mode 100644 (file)
index 0000000..96c8802
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.remote.rpc.registry;
+
+import akka.actor.ActorSelection;
+import akka.actor.Address;
+import akka.actor.Props;
+import akka.cluster.ClusterEvent;
+import akka.cluster.Member;
+import akka.japi.Creator;
+import org.opendaylight.controller.remote.rpc.AbstractUntypedActor;
+import org.opendaylight.controller.remote.rpc.ActorConstants;
+import org.opendaylight.controller.remote.rpc.messages.AddRoutedRpc;
+import org.opendaylight.controller.remote.rpc.messages.AddRpc;
+import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpc;
+import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpcReply;
+import org.opendaylight.controller.remote.rpc.messages.GetRpc;
+import org.opendaylight.controller.remote.rpc.messages.GetRpcReply;
+import org.opendaylight.controller.remote.rpc.messages.RemoveRoutedRpc;
+import org.opendaylight.controller.remote.rpc.messages.RemoveRpc;
+import org.opendaylight.controller.remote.rpc.messages.RoutingTableData;
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import scala.collection.JavaConversions;
+
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * This Actor maintains the routing table state and sync it with other nodes in the cluster.
+ *
+ * A scheduler runs after an interval of time, which pick a random member from the cluster
+ * and send the current state of routing table to the member.
+ *
+ * when a message of routing table data is received, it gets merged with the local routing table
+ * to keep the latest data.
+ */
+
+public class RpcRegistryOld extends AbstractUntypedActor {
+
+  private static final Logger LOG = LoggerFactory.getLogger(RpcRegistryOld.class);
+  private RoutingTableOld<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable;
+  private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
+  private final ClusterWrapper clusterWrapper;
+  private final ScheduledFuture<?> syncScheduler;
+
+  private RpcRegistryOld(ClusterWrapper clusterWrapper){
+    this.routingTable = new RoutingTableOld<>();
+    this.clusterWrapper = clusterWrapper;
+    this.syncScheduler = scheduler.scheduleAtFixedRate(new SendRoutingTable(), 10, 10, TimeUnit.SECONDS);
+  }
+
+  public static Props props(final ClusterWrapper clusterWrapper){
+    return Props.create(new Creator<RpcRegistryOld>(){
+
+      @Override
+      public RpcRegistryOld create() throws Exception {
+        return new RpcRegistryOld(clusterWrapper);
+      }
+    });
+  }
+
+  @Override
+  protected void handleReceive(Object message) throws Exception {
+    LOG.debug("Received message {}", message);
+    if(message instanceof RoutingTableData) {
+      syncRoutingTable((RoutingTableData) message);
+    } else if(message instanceof GetRoutedRpc) {
+      getRoutedRpc((GetRoutedRpc) message);
+    } else if(message instanceof GetRpc) {
+      getRpc((GetRpc) message);
+    } else if(message instanceof AddRpc) {
+      addRpc((AddRpc) message);
+    } else if(message instanceof RemoveRpc) {
+      removeRpc((RemoveRpc) message);
+    } else if(message instanceof AddRoutedRpc) {
+      addRoutedRpc((AddRoutedRpc) message);
+    } else if(message instanceof RemoveRoutedRpc) {
+      removeRoutedRpc((RemoveRoutedRpc) message);
+    }
+  }
+
+  private void getRoutedRpc(GetRoutedRpc rpcMsg){
+    LOG.debug("Get latest routed Rpc location from routing table {}", rpcMsg);
+    String remoteActorPath = routingTable.getLastAddedRoutedRpc(rpcMsg.getRouteId());
+    GetRoutedRpcReply routedRpcReply = new GetRoutedRpcReply(remoteActorPath);
+
+    getSender().tell(routedRpcReply, self());
+  }
+
+  private void getRpc(GetRpc rpcMsg) {
+    LOG.debug("Get global Rpc location from routing table {}", rpcMsg);
+    String remoteActorPath = routingTable.getGlobalRoute(rpcMsg.getRouteId());
+    GetRpcReply rpcReply = new GetRpcReply(remoteActorPath);
+
+    getSender().tell(rpcReply, self());
+  }
+
+  private void addRpc(AddRpc rpcMsg) {
+    LOG.debug("Add Rpc to routing table {}", rpcMsg);
+    routingTable.addGlobalRoute(rpcMsg.getRouteId(), rpcMsg.getActorPath());
+
+    getSender().tell("Success", self());
+  }
+
+  private void removeRpc(RemoveRpc rpcMsg) {
+    LOG.debug("Removing Rpc to routing table {}", rpcMsg);
+    routingTable.removeGlobalRoute(rpcMsg.getRouteId());
+
+    getSender().tell("Success", self());
+  }
+
+  private void addRoutedRpc(AddRoutedRpc rpcMsg) {
+    routingTable.addRoutedRpcs(rpcMsg.getAnnouncements(), rpcMsg.getActorPath());
+    getSender().tell("Success", self());
+  }
+
+  private void removeRoutedRpc(RemoveRoutedRpc rpcMsg) {
+    routingTable.removeRoutes(rpcMsg.getAnnouncements(), rpcMsg.getActorPath());
+    getSender().tell("Success", self());
+  }
+
+  private void syncRoutingTable(RoutingTableData routingTableData) {
+    LOG.debug("Syncing routing table {}", routingTableData);
+
+    Map<RpcRouter.RouteIdentifier<?, ?, ?>, String> newRpcMap = routingTableData.getRpcMap();
+    Set<RpcRouter.RouteIdentifier<?, ?, ?>> routeIds = newRpcMap.keySet();
+    for(RpcRouter.RouteIdentifier<?, ?, ?> routeId : routeIds) {
+      routingTable.addGlobalRoute(routeId, newRpcMap.get(routeId));
+    }
+
+    Map<RpcRouter.RouteIdentifier<?, ?, ?>, LinkedHashSet<String>> newRoutedRpcMap =
+        routingTableData.getRoutedRpcMap();
+    routeIds = newRoutedRpcMap.keySet();
+
+    for(RpcRouter.RouteIdentifier<?, ?, ?> routeId : routeIds) {
+      Set<String> routeAddresses = newRoutedRpcMap.get(routeId);
+      for(String routeAddress : routeAddresses) {
+        routingTable.addRoutedRpc(routeId, routeAddress);
+      }
+    }
+  }
+
+  private ActorSelection getRandomRegistryActor() {
+    ClusterEvent.CurrentClusterState clusterState = clusterWrapper.getState();
+    ActorSelection actor = null;
+    Set<Member> members = JavaConversions.asJavaSet(clusterState.members());
+    int memberSize = members.size();
+    // Don't select yourself
+    if(memberSize > 1) {
+      Address currentNodeAddress = clusterWrapper.getAddress();
+      int index = new Random().nextInt(memberSize);
+      int i = 0;
+      // keeping previous member, in case when random index member is same as current actor
+      // and current actor member is last in set
+      Member previousMember = null;
+      for(Member member : members){
+        if(i == index-1) {
+          previousMember = member;
+        }
+        if(i == index) {
+          if(!currentNodeAddress.equals(member.address())) {
+            actor = this.context().actorSelection(member.address() + ActorConstants.RPC_REGISTRY_PATH);
+            break;
+          } else if(index < memberSize-1){ // pick the next element in the set
+            index++;
+          }
+        }
+        i++;
+      }
+      if(actor == null && previousMember != null) {
+        actor = this.context().actorSelection(previousMember.address() + ActorConstants.RPC_REGISTRY_PATH);
+      }
+    }
+    return actor;
+  }
+
+  private class SendRoutingTable implements Runnable {
+
+    @Override
+    public void run() {
+      RoutingTableData routingTableData =
+          new RoutingTableData(routingTable.getGlobalRpcMap(), routingTable.getRoutedRpcMap());
+      LOG.debug("Sending routing table for sync {}", routingTableData);
+      ActorSelection actor = getRandomRegistryActor();
+      if(actor != null) {
+        actor.tell(routingTableData, self());
+      }
+    }
+  }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/Bucket.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/Bucket.java
new file mode 100644 (file)
index 0000000..f5dfbc5
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.remote.rpc.registry.gossip;
+
+
+public interface Bucket<T extends Copier<T>> {
+    public Long getVersion();
+    public T getData();
+    public void setData(T data);
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/BucketImpl.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/BucketImpl.java
new file mode 100644 (file)
index 0000000..3cdd924
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.remote.rpc.registry.gossip;
+
+import java.io.Serializable;
+
+public class BucketImpl<T extends Copier<T>> implements Bucket<T>, Serializable {
+
+    private Long version = System.currentTimeMillis();;
+
+    private T data;
+
+    @Override
+    public Long getVersion() {
+        return version;
+    }
+
+    @Override
+    public T getData() {
+        if (this.data == null)
+            return null;
+
+        return data.copy();
+    }
+
+    public void setData(T data){
+        this.version = System.currentTimeMillis()+1;
+        this.data = data;
+    }
+
+    @Override
+    public String toString() {
+        return "BucketImpl{" +
+                "version=" + version +
+                ", data=" + data +
+                '}';
+    }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/BucketStore.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/BucketStore.java
new file mode 100644 (file)
index 0000000..2f634ce
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.remote.rpc.registry.gossip;
+
+import akka.actor.ActorRef;
+import akka.actor.Address;
+import akka.actor.Props;
+import akka.actor.UntypedActor;
+import akka.cluster.Cluster;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetAllBuckets;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetAllBucketsReply;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketVersions;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketVersionsReply;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketsByMembers;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketsByMembersReply;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetLocalBucket;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetLocalBucketReply;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.UpdateBucket;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.UpdateRemoteBuckets;
+
+/**
+ * A store that syncs its data across nodes in the cluster.
+ * It maintains a {@link org.opendaylight.controller.remote.rpc.registry.gossip.Bucket} per node. Buckets are versioned.
+ * A node can write ONLY to its bucket. This way, write conflicts are avoided.
+ * <p>
+ * Buckets are sync'ed across nodes using Gossip protocol (http://en.wikipedia.org/wiki/Gossip_protocol)<p>
+ * This store uses a {@link org.opendaylight.controller.remote.rpc.registry.gossip.Gossiper}.
+ *
+ */
+public class BucketStore extends UntypedActor {
+
+    final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
+
+    /**
+     * Bucket owned by the node
+     */
+    private BucketImpl localBucket = new BucketImpl();;
+
+    /**
+     * Buckets ownded by other known nodes in the cluster
+     */
+    private ConcurrentMap<Address, Bucket> remoteBuckets = new ConcurrentHashMap<>();
+
+    /**
+     * Bucket version for every known node in the cluster including this node
+     */
+    private ConcurrentMap<Address, Long> versions = new ConcurrentHashMap<>();
+
+    /**
+     * Cluster address for this node
+     */
+    private final Address selfAddress = Cluster.get(getContext().system()).selfAddress();
+
+    /**
+     * Our private gossiper
+     */
+    private ActorRef gossiper;
+
+    public BucketStore(){
+        gossiper = getContext().actorOf(Props.create(Gossiper.class), "gossiper");
+    }
+
+    /**
+     * This constructor is useful for testing.
+     * TODO: Pass Props instead of ActorRef
+     *
+     * @param gossiper
+     */
+    public BucketStore(ActorRef gossiper){
+        this.gossiper = gossiper;
+    }
+
+    @Override
+    public void onReceive(Object message) throws Exception {
+
+        log.debug("Received message: node[{}], message[{}]", selfAddress, message);
+
+        if (message instanceof UpdateBucket)
+            receiveUpdateBucket(((UpdateBucket) message).getBucket());
+
+        else if (message instanceof GetAllBuckets)
+            receiveGetAllBucket();
+
+        else if (message instanceof GetLocalBucket)
+            receiveGetLocalBucket();
+
+        else if (message instanceof GetBucketsByMembers)
+            receiveGetBucketsByMembers(((GetBucketsByMembers) message).getMembers());
+
+        else if (message instanceof GetBucketVersions)
+            receiveGetBucketVersions();
+
+        else if (message instanceof UpdateRemoteBuckets)
+            receiveUpdateRemoteBuckets(((UpdateRemoteBuckets) message).getBuckets());
+
+        else {
+            log.debug("Unhandled message [{}]", message);
+            unhandled(message);
+        }
+
+    }
+
+    /**
+     * Returns a copy of bucket owned by this node
+     */
+    private void receiveGetLocalBucket() {
+        final ActorRef sender = getSender();
+        GetLocalBucketReply reply = new GetLocalBucketReply(localBucket);
+        sender.tell(reply, getSelf());
+    }
+
+    /**
+     * Updates the bucket owned by this node
+     *
+     * @param updatedBucket
+     */
+    void receiveUpdateBucket(Bucket updatedBucket){
+
+        localBucket = (BucketImpl) updatedBucket;
+        versions.put(selfAddress, localBucket.getVersion());
+    }
+
+    /**
+     * Returns all the buckets the this node knows about, self owned + remote
+     */
+    void receiveGetAllBucket(){
+        final ActorRef sender = getSender();
+        sender.tell(new GetAllBucketsReply(getAllBuckets()), getSelf());
+    }
+
+    /**
+     * Helper to collect all known buckets
+     *
+     * @return self owned + remote buckets
+     */
+    Map<Address, Bucket> getAllBuckets(){
+        Map<Address, Bucket> all = new HashMap<>(remoteBuckets.size() + 1);
+
+        //first add the local bucket
+        all.put(selfAddress, localBucket);
+
+        //then get all remote buckets
+        all.putAll(remoteBuckets);
+
+        return all;
+    }
+
+    /**
+     * Returns buckets for requested members that this node knows about
+     *
+     * @param members requested members
+     */
+    void receiveGetBucketsByMembers(Set<Address> members){
+        final ActorRef sender = getSender();
+        Map<Address, Bucket> buckets = getBucketsByMembers(members);
+        sender.tell(new GetBucketsByMembersReply(buckets), getSelf());
+    }
+
+    /**
+     * Helper to collect buckets for requested memebers
+     *
+     * @param members requested members
+     * @return buckets for requested memebers
+     */
+    Map<Address, Bucket> getBucketsByMembers(Set<Address> members) {
+        Map<Address, Bucket> buckets = new HashMap<>();
+
+        //first add the local bucket if asked
+        if (members.contains(selfAddress))
+            buckets.put(selfAddress, localBucket);
+
+        //then get buckets for requested remote nodes
+        for (Address address : members){
+            if (remoteBuckets.containsKey(address))
+                buckets.put(address, remoteBuckets.get(address));
+        }
+
+        return buckets;
+    }
+
+    /**
+     * Returns versions for all buckets known
+     */
+    void receiveGetBucketVersions(){
+        final ActorRef sender = getSender();
+        GetBucketVersionsReply reply = new GetBucketVersionsReply(versions);
+        sender.tell(reply, getSelf());
+    }
+
+    /**
+     * Update local copy of remote buckets where local copy's version is older
+     *
+     * @param receivedBuckets buckets sent by remote
+     *                        {@link org.opendaylight.controller.remote.rpc.registry.gossip.Gossiper}
+     */
+    void receiveUpdateRemoteBuckets(Map<Address, Bucket> receivedBuckets){
+
+        if (receivedBuckets == null || receivedBuckets.isEmpty())
+            return; //nothing to do
+
+        //Remote cant update self's bucket
+        receivedBuckets.remove(selfAddress);
+
+        for (Map.Entry<Address, Bucket> entry : receivedBuckets.entrySet()){
+
+            Long localVersion = versions.get(entry.getKey());
+            if (localVersion == null) localVersion = -1L;
+
+            Bucket receivedBucket = entry.getValue();
+
+            if (receivedBucket == null)
+                continue;
+
+            Long remoteVersion = receivedBucket.getVersion();
+            if (remoteVersion == null) remoteVersion = -1L;
+
+            //update only if remote version is newer
+            if ( remoteVersion > localVersion ) {
+                remoteBuckets.put(entry.getKey(), receivedBucket);
+                versions.put(entry.getKey(), remoteVersion);
+            }
+        }
+
+        log.debug("State after update - Local Bucket [{}], Remote Buckets [{}]", localBucket, remoteBuckets);
+    }
+
+    ///
+    ///Getter Setters
+    ///
+
+    BucketImpl getLocalBucket() {
+        return localBucket;
+    }
+
+    void setLocalBucket(BucketImpl localBucket) {
+        this.localBucket = localBucket;
+    }
+
+    ConcurrentMap<Address, Bucket> getRemoteBuckets() {
+        return remoteBuckets;
+    }
+
+    void setRemoteBuckets(ConcurrentMap<Address, Bucket> remoteBuckets) {
+        this.remoteBuckets = remoteBuckets;
+    }
+
+    ConcurrentMap<Address, Long> getVersions() {
+        return versions;
+    }
+
+    void setVersions(ConcurrentMap<Address, Long> versions) {
+        this.versions = versions;
+    }
+
+    Address getSelfAddress() {
+        return selfAddress;
+    }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/Copier.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/Copier.java
new file mode 100644 (file)
index 0000000..45279eb
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.remote.rpc.registry.gossip;
+
+/**
+ * Type of data that goes in {@link org.opendaylight.controller.remote.rpc.registry.gossip.Bucket}.
+ * The implementers should do deep cloning in copy() method.
+ */
+public interface Copier<T> {
+    public T copy();
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/Gossiper.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/Gossiper.java
new file mode 100644 (file)
index 0000000..0b64136
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.remote.rpc.registry.gossip;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSelection;
+import akka.actor.Address;
+import akka.actor.Cancellable;
+import akka.actor.UntypedActor;
+import akka.cluster.Cluster;
+import akka.cluster.ClusterEvent;
+import akka.cluster.Member;
+import akka.dispatch.Mapper;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import akka.pattern.Patterns;
+import scala.concurrent.Future;
+import scala.concurrent.duration.FiniteDuration;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketVersions;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketVersionsReply;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketsByMembers;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketsByMembersReply;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.UpdateRemoteBuckets;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.GossiperMessages.GossipEnvelope;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.GossiperMessages.GossipStatus;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.GossiperMessages.GossipTick;
+
+/**
+ * Gossiper that syncs bucket store across nodes in the cluster.
+ * <p>
+ * It keeps a local scheduler that periodically sends Gossip ticks to itself to send bucket store's bucket versions
+ * to a randomly selected remote gossiper.
+ * <p>
+ * When bucket versions are received from a remote gossiper, it is compared with bucket store's bucket versions.
+ * Which ever buckets are newer locally, are sent to remote gossiper. If any bucket is older in bucket store, a
+ * gossip status is sent to remote gossiper so that it can send the newer buckets.
+ * <p>
+ * When a bucket is received from a remote gossiper, its sent to the bucket store for update.
+ *
+ */
+
+public class Gossiper extends UntypedActor {
+
+    final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
+
+    Cluster cluster = Cluster.get(getContext().system());
+
+    /**
+     * ActorSystem's address for the current cluster node.
+     */
+    private Address selfAddress = cluster.selfAddress();
+
+    /**
+     * All known cluster members
+     */
+    private List<Address> clusterMembers = new ArrayList<>();
+
+    private Cancellable gossipTask;
+
+    private Boolean autoStartGossipTicks = true;
+
+    public Gossiper(){}
+
+    /**
+     * Helpful for testing
+     * @param autoStartGossipTicks used for turning off gossip ticks during testing. Gossip tick can be manually sent.
+     */
+    public Gossiper(Boolean autoStartGossipTicks){
+        this.autoStartGossipTicks = autoStartGossipTicks;
+    }
+
+    @Override
+    public void preStart(){
+
+        cluster.subscribe(getSelf(),
+                          ClusterEvent.initialStateAsEvents(),
+                          ClusterEvent.MemberEvent.class,
+                          ClusterEvent.UnreachableMember.class);
+
+        if (autoStartGossipTicks) {
+            gossipTask = getContext().system().scheduler().schedule(
+                    new FiniteDuration(1, TimeUnit.SECONDS),        //initial delay
+                    new FiniteDuration(500, TimeUnit.MILLISECONDS),         //interval
+                    getSelf(),                                       //target
+                    new Messages.GossiperMessages.GossipTick(),      //message
+                    getContext().dispatcher(),                       //execution context
+                    getSelf()                                        //sender
+            );
+        }
+    }
+
+    @Override
+    public void postStop(){
+        if (cluster != null)
+            cluster.unsubscribe(getSelf());
+        if (gossipTask != null)
+            gossipTask.cancel();
+    }
+
+    @Override
+    public void onReceive(Object message) throws Exception {
+
+        log.debug("Received message: node[{}], message[{}]", selfAddress, message);
+
+        //Usually sent by self via gossip task defined above. But its not enforced.
+        //These ticks can be sent by another actor as well which is esp. useful while testing
+        if (message instanceof GossipTick)
+            receiveGossipTick();
+
+        //Message from remote gossiper with its bucket versions
+        else if (message instanceof GossipStatus)
+            receiveGossipStatus((GossipStatus) message);
+
+        //Message from remote gossiper with buckets. This is usually in response to GossipStatus message
+        //The contained buckets are newer as determined by the remote gossiper by comparing the GossipStatus
+        //message with its local versions
+        else if (message instanceof GossipEnvelope)
+            receiveGossip((GossipEnvelope) message);
+
+        else if (message instanceof ClusterEvent.MemberUp) {
+            receiveMemberUp(((ClusterEvent.MemberUp) message).member());
+
+        } else if (message instanceof ClusterEvent.MemberRemoved) {
+            receiveMemberRemoveOrUnreachable(((ClusterEvent.MemberRemoved) message).member());
+
+        } else if ( message instanceof ClusterEvent.UnreachableMember){
+            receiveMemberRemoveOrUnreachable(((ClusterEvent.UnreachableMember) message).member());
+
+        } else
+            unhandled(message);
+    }
+
+    /**
+     * Remove member from local copy of member list. If member down is self, then stop the actor
+     *
+     * @param member who went down
+     */
+    void receiveMemberRemoveOrUnreachable(Member member) {
+        //if its self, then stop itself
+        if (selfAddress.equals(member.address())){
+            getContext().stop(getSelf());
+            return;
+        }
+
+        clusterMembers.remove(member.address());
+        log.debug("Removed member [{}], Active member list [{}]", member.address(), clusterMembers);
+    }
+
+    /**
+     * Add member to the local copy of member list if it doesnt already
+     * @param member
+     */
+    void receiveMemberUp(Member member) {
+
+        if (selfAddress.equals(member.address()))
+            return; //ignore up notification for self
+
+        if (!clusterMembers.contains(member.address()))
+            clusterMembers.add(member.address());
+
+        log.debug("Added member [{}], Active member list [{}]", member.address(), clusterMembers);
+    }
+
+    /**
+     * Sends Gossip status to other members in the cluster. <br/>
+     * 1. If there are no member, ignore the tick. </br>
+     * 2. If there's only 1 member, send gossip status (bucket versions) to it. <br/>
+     * 3. If there are more than one member, randomly pick one and send gossip status (bucket versions) to it.
+     */
+    void receiveGossipTick(){
+        if (clusterMembers.size() == 0) return; //no members to send gossip status to
+
+        Address remoteMemberToGossipTo = null;
+
+        if (clusterMembers.size() == 1)
+            remoteMemberToGossipTo = clusterMembers.get(0);
+        else {
+            Integer randomIndex = ThreadLocalRandom.current().nextInt(0, clusterMembers.size());
+            remoteMemberToGossipTo = clusterMembers.get(randomIndex);
+        }
+
+        log.debug("Gossiping to [{}]", remoteMemberToGossipTo);
+        getLocalStatusAndSendTo(remoteMemberToGossipTo);
+    }
+
+    /**
+     * Process gossip status received from a remote gossiper. Remote versions are compared with
+     * the local copy. <p>
+     *
+     * For each bucket
+     * <ul>
+     *  <li>If local copy is newer, the newer buckets are sent in GossipEnvelope to remote</li>
+     *  <li>If local is older, GossipStatus is sent to remote so that it can reply with GossipEnvelope</li>
+     *  <li>If both are same, noop</li>
+     * </ul>
+     *
+     * @param status bucket versions from a remote member
+     */
+    void receiveGossipStatus(GossipStatus status){
+        //Dont want to accept messages from non-members
+        if (!clusterMembers.contains(status.from()))
+            return;
+
+        final ActorRef sender = getSender();
+
+        Future<Object> futureReply = Patterns.ask(getContext().parent(), new GetBucketVersions(), 1000);
+
+        futureReply.map(getMapperToProcessRemoteStatus(sender, status), getContext().dispatcher());
+
+    }
+
+    /**
+     * Sends the received buckets in the envelope to the parent Bucket store.
+     *
+     * @param envelope contains buckets from a remote gossiper
+     */
+    void receiveGossip(GossipEnvelope envelope){
+        //TODO: Add more validations
+        if (!selfAddress.equals(envelope.to())) {
+            log.info("Ignoring message intended for someone else. From [{}] to [{}]", envelope.from(), envelope.to());
+            return;
+        }
+        if (envelope.getBuckets() == null)
+            return; //nothing to do
+
+        updateRemoteBuckets(envelope.getBuckets());
+
+    }
+
+    /**
+     * Helper to send received buckets to bucket store
+     *
+     * @param buckets
+     */
+    void updateRemoteBuckets(Map<Address, Bucket> buckets) {
+
+        if (buckets == null || buckets.isEmpty())
+            return; //nothing to merge
+
+        UpdateRemoteBuckets updateRemoteBuckets = new UpdateRemoteBuckets(buckets);
+
+        getContext().parent().tell(updateRemoteBuckets, getSelf());
+    }
+
+    /**
+     * Gets the buckets from bucket store for the given node addresses and sends them to remote gossiper
+     *
+     * @param remote     remote node to send Buckets to
+     * @param addresses  node addresses whose buckets needs to be sent
+     */
+    void sendGossipTo(final ActorRef remote, final Set<Address> addresses){
+
+        Future<Object> futureReply = Patterns.ask(getContext().parent(), new GetBucketsByMembers(addresses), 1000);
+
+        futureReply.map(getMapperToSendGossip(remote), getContext().dispatcher());
+
+    }
+
+    /**
+     * Gets bucket versions from bucket store and sends to the supplied address
+     *
+     * @param remoteActorSystemAddress remote gossiper to send to
+     */
+    void getLocalStatusAndSendTo(Address remoteActorSystemAddress){
+
+        //Get local status from bucket store and send to remote
+        Future<Object> futureReply = Patterns.ask(getContext().parent(), new GetBucketVersions(), 1000);
+
+        ActorSelection remoteRef = getContext().system().actorSelection(
+                remoteActorSystemAddress.toString() + getSelf().path().toStringWithoutAddress());
+
+        log.debug("Sending bucket versions to [{}]", remoteRef);
+
+        futureReply.map(getMapperToSendLocalStatus(remoteRef), getContext().dispatcher());
+
+    }
+
+    /**
+     * Helper to send bucket versions received from local store
+     * @param remote        remote gossiper to send versions to
+     * @param localVersions bucket versions received from local store
+     */
+    void sendGossipStatusTo(ActorRef remote, Map<Address, Long> localVersions){
+
+        GossipStatus status = new GossipStatus(selfAddress, localVersions);
+        remote.tell(status, getSelf());
+    }
+
+    void sendGossipStatusTo(ActorSelection remote, Map<Address, Long> localVersions){
+
+        GossipStatus status = new GossipStatus(selfAddress, localVersions);
+        remote.tell(status, getSelf());
+    }
+
+    ///
+    /// Private factories to create mappers
+    ///
+
+    private Mapper<Object, Void> getMapperToSendLocalStatus(final ActorSelection remote){
+
+        return new Mapper<Object, Void>() {
+            @Override
+            public Void apply(Object replyMessage) {
+                if (replyMessage instanceof GetBucketVersionsReply) {
+                    GetBucketVersionsReply reply = (GetBucketVersionsReply) replyMessage;
+                    Map<Address, Long> localVersions = reply.getVersions();
+
+                    sendGossipStatusTo(remote, localVersions);
+
+                }
+                return null;
+            }
+        };
+    }
+
+    /**
+     * Process bucket versions received from {@link org.opendaylight.controller.remote.rpc.registry.gossip.BucketStore}.
+     * Then this method compares remote bucket versions with local bucket versions.
+     * <ul>
+     *     <li>The buckets that are newer locally, send
+     *     {@link org.opendaylight.controller.remote.rpc.registry.gossip.Messages.GossiperMessages.GossipEnvelope} to remote
+     *     <li>The buckets that are older locally, send
+     *     {@link org.opendaylight.controller.remote.rpc.registry.gossip.Messages.GossiperMessages.GossipStatus} to remote so that
+     *     remote sends GossipEnvelop.
+     * </ul>
+     *
+     * @param sender the remote member
+     * @param status bucket versions from a remote member
+     * @return a {@link akka.dispatch.Mapper} that gets evaluated in future
+     *
+     */
+    private Mapper<Object, Void> getMapperToProcessRemoteStatus(final ActorRef sender, final GossipStatus status){
+
+        final Map<Address, Long> remoteVersions = status.getVersions();
+
+        return new Mapper<Object, Void>() {
+            @Override
+            public Void apply(Object replyMessage) {
+                if (replyMessage instanceof GetBucketVersionsReply) {
+                    GetBucketVersionsReply reply = (GetBucketVersionsReply) replyMessage;
+                    Map<Address, Long> localVersions = reply.getVersions();
+
+                    //diff between remote list and local
+                    Set<Address> localIsOlder = new HashSet<>();
+                    localIsOlder.addAll(remoteVersions.keySet());
+                    localIsOlder.removeAll(localVersions.keySet());
+
+                    //diff between local list and remote
+                    Set<Address> localIsNewer = new HashSet<>();
+                    localIsNewer.addAll(localVersions.keySet());
+                    localIsNewer.removeAll(remoteVersions.keySet());
+
+
+                    for (Address address : remoteVersions.keySet()){
+
+                        if (localVersions.get(address) == null || remoteVersions.get(address) == null)
+                            continue; //this condition is taken care of by above diffs
+                        if (localVersions.get(address) <  remoteVersions.get(address))
+                            localIsOlder.add(address);
+                        else if (localVersions.get(address) > remoteVersions.get(address))
+                            localIsNewer.add(address);
+                        else
+                            continue;
+                    }
+
+                    if (!localIsOlder.isEmpty())
+                        sendGossipStatusTo(sender, localVersions );
+
+                    if (!localIsNewer.isEmpty())
+                        sendGossipTo(sender, localIsNewer);//send newer buckets to remote
+
+                }
+                return null;
+            }
+        };
+    }
+
+    /**
+     * Processes the message from {@link org.opendaylight.controller.remote.rpc.registry.gossip.BucketStore} that contains
+     * {@link org.opendaylight.controller.remote.rpc.registry.gossip.Bucket}. These buckets are sent to a remote member encapsulated
+     * in {@link org.opendaylight.controller.remote.rpc.registry.gossip.Messages.GossiperMessages.GossipEnvelope}
+     *
+     * @param sender the remote member that sent
+     *               {@link org.opendaylight.controller.remote.rpc.registry.gossip.Messages.GossiperMessages.GossipStatus}
+     *               in reply to which bucket is being sent back
+     * @return a {@link akka.dispatch.Mapper} that gets evaluated in future
+     *
+     */
+    private Mapper<Object, Void> getMapperToSendGossip(final ActorRef sender) {
+
+        return new Mapper<Object, Void>() {
+            @Override
+            public Void apply(Object msg) {
+                if (msg instanceof GetBucketsByMembersReply) {
+                    Map<Address, Bucket> buckets = ((GetBucketsByMembersReply) msg).getBuckets();
+                    log.info("Buckets to send from {}: {}", selfAddress, buckets);
+                    GossipEnvelope envelope = new GossipEnvelope(selfAddress, sender.path().address(), buckets);
+                    sender.tell(envelope, getSelf());
+                }
+                return null;
+            }
+        };
+    }
+
+    ///
+    ///Getter Setters
+    ///
+    List<Address> getClusterMembers() {
+        return clusterMembers;
+    }
+
+    void setClusterMembers(List<Address> clusterMembers) {
+        this.clusterMembers = clusterMembers;
+    }
+
+    Address getSelfAddress() {
+        return selfAddress;
+    }
+
+    void setSelfAddress(Address selfAddress) {
+        this.selfAddress = selfAddress;
+    }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/Messages.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/Messages.java
new file mode 100644 (file)
index 0000000..9a247d9
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.remote.rpc.registry.gossip;
+
+import akka.actor.Address;
+import com.google.common.base.Preconditions;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * These messages are used by {@link org.opendaylight.controller.remote.rpc.registry.gossip.BucketStore} and
+ * {@link org.opendaylight.controller.remote.rpc.registry.gossip.Gossiper} actors.
+ */
+public class Messages {
+
+    public static class BucketStoreMessages{
+
+        public static class GetLocalBucket implements Serializable{}
+
+        public static class ContainsBucket implements Serializable {
+            final private Bucket bucket;
+
+            public ContainsBucket(Bucket bucket){
+                Preconditions.checkArgument(bucket != null, "bucket can not be null");
+                this.bucket = bucket;
+            }
+
+            public Bucket getBucket(){
+                return bucket;
+            }
+
+        }
+
+        public static class UpdateBucket extends ContainsBucket implements Serializable {
+            public UpdateBucket(Bucket bucket){
+                super(bucket);
+            }
+        }
+
+        public static class GetLocalBucketReply extends ContainsBucket implements Serializable {
+            public GetLocalBucketReply(Bucket bucket){
+                super(bucket);
+            }
+        }
+
+        public static class GetAllBuckets implements Serializable{}
+
+        public static class GetBucketsByMembers implements Serializable{
+            private Set<Address> members;
+
+            public GetBucketsByMembers(Set<Address> members){
+                Preconditions.checkArgument(members != null, "members can not be null");
+                this.members = members;
+            }
+
+            public Set<Address> getMembers() {
+                return new HashSet<>(members);
+            }
+        }
+
+        public static class ContainsBuckets implements Serializable{
+            private Map<Address, Bucket> buckets;
+
+            public ContainsBuckets(Map<Address, Bucket> buckets){
+                Preconditions.checkArgument(buckets != null, "buckets can not be null");
+                this.buckets = buckets;
+            }
+
+            public Map<Address, Bucket> getBuckets() {
+                Map<Address, Bucket> copy = new HashMap<>(buckets.size());
+
+                for (Map.Entry<Address, Bucket> entry : buckets.entrySet()){
+                    //ignore null entries
+                    if ( (entry.getKey() == null) || (entry.getValue() == null) )
+                        continue;
+                    copy.put(entry.getKey(), entry.getValue());
+                }
+                return new HashMap<>(copy);
+            }
+        }
+
+        public static class GetAllBucketsReply extends ContainsBuckets implements Serializable{
+            public GetAllBucketsReply(Map<Address, Bucket> buckets) {
+                super(buckets);
+            }
+        }
+
+        public static class GetBucketsByMembersReply extends ContainsBuckets implements Serializable{
+            public GetBucketsByMembersReply(Map<Address, Bucket> buckets) {
+                super(buckets);
+            }
+        }
+
+        public static class GetBucketVersions implements Serializable{}
+
+        public static class ContainsBucketVersions implements Serializable{
+            Map<Address, Long> versions;
+
+            public ContainsBucketVersions(Map<Address, Long> versions) {
+                Preconditions.checkArgument(versions != null, "versions can not be null");
+                this.versions = versions;
+            }
+
+            public Map<Address, Long> getVersions() {
+                return Collections.unmodifiableMap(versions);
+            }
+
+        }
+
+        public static class GetBucketVersionsReply extends ContainsBucketVersions implements Serializable{
+            public GetBucketVersionsReply(Map<Address, Long> versions) {
+                super(versions);
+            }
+        }
+
+        public static class UpdateRemoteBuckets extends ContainsBuckets implements Serializable{
+            public UpdateRemoteBuckets(Map<Address, Bucket> buckets) {
+                super(buckets);
+            }
+        }
+    }
+
+    public static class GossiperMessages{
+        public static class Tick implements Serializable {}
+
+        public static final class GossipTick extends Tick {}
+
+        public static final class GossipStatus extends BucketStoreMessages.ContainsBucketVersions implements Serializable{
+            private Address from;
+
+            public GossipStatus(Address from, Map<Address, Long> versions) {
+                super(versions);
+                this.from = from;
+            }
+
+            public Address from() {
+                return from;
+            }
+        }
+
+        public static final class GossipEnvelope extends BucketStoreMessages.ContainsBuckets implements Serializable {
+            private final Address from;
+            private final Address to;
+
+            public GossipEnvelope(Address from, Address to, Map<Address, Bucket> buckets) {
+                super(buckets);
+                this.to = to;
+                this.from = from;
+            }
+
+            public Address from() {
+                return from;
+            }
+
+            public Address to() {
+                return to;
+            }
+        }
+    }
+}
index 49ba84307109e650b07e25420506e73bbae57842..b4cca1ab485c3e99373dfd731166c6615e3903d3 100644 (file)
@@ -185,7 +185,8 @@ public class XmlDocumentUtils {
       value = codec.deserialize(text);
     }
 
-    if (schema.getType() instanceof InstanceIdentifierType) {
+    final TypeDefinition<?> baseType = XmlUtils.resolveBaseTypeFrom(schema.getType());
+    if (baseType instanceof InstanceIdentifierType) {
       logger.debug("toSimpleNodeWithType: base type of node is instance identifier, deserializing element", xmlElement);
       value = InstanceIdentifierForXmlCodec.deserialize(xmlElement,schemaCtx);
     }
index 6088dd0e0ea517c27bd74e79272a92f4b5b7ef1d..daac89c4c8adaef39047034138a8318e639f54c8 100644 (file)
@@ -1,4 +1,43 @@
-odl-cluster{
+
+odl-cluster-data {
+  akka {
+    cluster {
+        roles = [
+          "member-1"
+        ]
+    }
+    actor {
+      provider = "akka.cluster.ClusterActorRefProvider"
+      serializers {
+                java = "akka.serialization.JavaSerializer"
+                proto = "akka.remote.serialization.ProtobufSerializer"
+              }
+
+              serialization-bindings {
+                  "com.google.protobuf.Message" = proto
+
+              }
+    }
+    remote {
+      log-remote-lifecycle-events = off
+      netty.tcp {
+        hostname = "127.0.0.1"
+        port = 2550
+           maximum-frame-size = 2097152
+           send-buffer-size = 52428800
+           receive-buffer-size = 52428800
+      }
+    }
+
+    cluster {
+      seed-nodes = ["akka.tcp://opendaylight-cluster-data@127.0.0.1:2550"]
+
+      auto-down-unreachable-after = 10s
+    }
+  }
+}
+
+odl-cluster-rpc {
   akka {
     actor {
       provider = "akka.cluster.ClusterActorRefProvider"
@@ -7,15 +46,15 @@ odl-cluster{
     remote {
       log-remote-lifecycle-events = off
       netty.tcp {
-        hostname = "192.168.141.141"
+        hostname = "127.0.0.1"
         port = 2551
       }
     }
 
     cluster {
-      seed-nodes = ["akka.tcp://opendaylight-rpc@192.168.141.141:2551"]
+      seed-nodes = ["akka.tcp://opendaylight-cluster-rpc@127.0.0.1:2551"]
 
       auto-down-unreachable-after = 10s
     }
   }
-}
\ No newline at end of file
+}
index 392c1e637d848e1ccc47d43b3a951011a2e25a72..55aa1d6c871d252d0a89ce1772fd078e45cac101 100644 (file)
@@ -25,7 +25,7 @@ import org.opendaylight.controller.remote.rpc.messages.InvokeRoutedRpc;
 import org.opendaylight.controller.remote.rpc.messages.InvokeRpc;
 import org.opendaylight.controller.remote.rpc.messages.RpcResponse;
 import org.opendaylight.controller.remote.rpc.registry.ClusterWrapper;
-import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
+import org.opendaylight.controller.remote.rpc.registry.RpcRegistryOld;
 import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import org.opendaylight.controller.sal.core.api.Broker;
@@ -69,7 +69,7 @@ public class RpcBrokerTest {
   @Test
   public void testInvokeRpcError() throws URISyntaxException {
     new JavaTestKit(system) {{
-      ActorRef rpcRegistry = system.actorOf(RpcRegistry.props(Mockito.mock(ClusterWrapper.class)));
+      ActorRef rpcRegistry = system.actorOf(RpcRegistryOld.props(Mockito.mock(ClusterWrapper.class)));
       Broker.ProviderSession brokerSession = Mockito.mock(Broker.ProviderSession.class);
       SchemaContext schemaContext = mock(SchemaContext.class);
       ActorRef rpcBroker = system.actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext));
@@ -100,7 +100,7 @@ public class RpcBrokerTest {
   @Test
   public void testInvokeRpc() throws URISyntaxException {
     new JavaTestKit(system) {{
-      ActorRef rpcRegistry = system.actorOf(RpcRegistry.props(mock(ClusterWrapper.class)));
+      ActorRef rpcRegistry = system.actorOf(RpcRegistryOld.props(mock(ClusterWrapper.class)));
       Broker.ProviderSession brokerSession = mock(Broker.ProviderSession.class);
       SchemaContext schemaContext = mock(SchemaContext.class);
       ActorRef rpcBroker = system.actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext));
@@ -141,7 +141,7 @@ public class RpcBrokerTest {
   @Test
   public void testInvokeRoutedRpcError() throws URISyntaxException {
     new JavaTestKit(system) {{
-      ActorRef rpcRegistry = system.actorOf(RpcRegistry.props(Mockito.mock(ClusterWrapper.class)));
+      ActorRef rpcRegistry = system.actorOf(RpcRegistryOld.props(Mockito.mock(ClusterWrapper.class)));
       Broker.ProviderSession brokerSession = Mockito.mock(Broker.ProviderSession.class);
       SchemaContext schemaContext = mock(SchemaContext.class);
       ActorRef rpcBroker = system.actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext));
@@ -172,7 +172,7 @@ public class RpcBrokerTest {
   @Test
   public void testInvokeRoutedRpc() throws URISyntaxException {
     new JavaTestKit(system) {{
-      ActorRef rpcRegistry = system.actorOf(RpcRegistry.props(mock(ClusterWrapper.class)));
+      ActorRef rpcRegistry = system.actorOf(RpcRegistryOld.props(mock(ClusterWrapper.class)));
       Broker.ProviderSession brokerSession = mock(Broker.ProviderSession.class);
       SchemaContext schemaContext = mock(SchemaContext.class);
       ActorRef rpcBroker = system.actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext));
@@ -19,10 +19,10 @@ import java.net.URISyntaxException;
 import java.util.HashSet;
 import java.util.Set;
 
-public class RoutingTableTest {
+public class RoutingTableOldTest {
 
-  private RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable =
-      new RoutingTable<>();
+  private RoutingTableOld<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable =
+      new RoutingTableOld<>();
 
   @Test
   public void addGlobalRouteNullRouteIdTest() {
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistryOldTest.java b/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistryOldTest.java
new file mode 100644 (file)
index 0000000..0f711b4
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.remote.rpc.registry;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.testkit.JavaTestKit;
+import junit.framework.Assert;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.remote.rpc.RouteIdentifierImpl;
+import org.opendaylight.controller.remote.rpc.messages.AddRoutedRpc;
+import org.opendaylight.controller.remote.rpc.messages.AddRpc;
+import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpc;
+import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpcReply;
+import org.opendaylight.controller.remote.rpc.messages.GetRpc;
+import org.opendaylight.controller.remote.rpc.messages.GetRpcReply;
+import org.opendaylight.controller.remote.rpc.messages.RemoveRoutedRpc;
+import org.opendaylight.controller.remote.rpc.messages.RemoveRpc;
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import org.opendaylight.yangtools.yang.common.QName;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashSet;
+import java.util.Set;
+
+public class RpcRegistryOldTest {
+
+  static ActorSystem system;
+
+
+  @BeforeClass
+  public static void setup() {
+    system = ActorSystem.create();
+  }
+
+  @AfterClass
+  public static void teardown() {
+    JavaTestKit.shutdownActorSystem(system);
+    system = null;
+  }
+
+  /**
+   This test add, read and remove an entry in global rpc
+   */
+  @Test
+  public void testGlobalRpc() throws URISyntaxException {
+    new JavaTestKit(system) {{
+      ActorRef rpcRegistry = system.actorOf(RpcRegistryOld.props(Mockito.mock(ClusterWrapper.class)));
+      QName type = new QName(new URI("actor1"), "actor1");
+      RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, type, null);
+      final String route = "actor1";
+
+      AddRpc rpcMsg = new AddRpc(routeId, route);
+      rpcRegistry.tell(rpcMsg, getRef());
+      expectMsgEquals(duration("2 second"), "Success");
+
+      GetRpc getRpc = new GetRpc(routeId);
+      rpcRegistry.tell(getRpc, getRef());
+
+      Boolean getMsg = new ExpectMsg<Boolean>("GetRpcReply") {
+        protected Boolean match(Object in) {
+          if (in instanceof GetRpcReply) {
+            GetRpcReply reply = (GetRpcReply)in;
+            return route.equals(reply.getRoutePath());
+          } else {
+            throw noMatch();
+          }
+        }
+      }.get(); // this extracts the received message
+
+      Assert.assertTrue(getMsg);
+
+      RemoveRpc removeMsg = new RemoveRpc(routeId);
+      rpcRegistry.tell(removeMsg, getRef());
+      expectMsgEquals(duration("2 second"), "Success");
+
+      rpcRegistry.tell(getRpc, getRef());
+
+      Boolean getNullMsg = new ExpectMsg<Boolean>("GetRpcReply") {
+        protected Boolean match(Object in) {
+          if (in instanceof GetRpcReply) {
+            GetRpcReply reply = (GetRpcReply)in;
+            return reply.getRoutePath() == null;
+          } else {
+            throw noMatch();
+          }
+        }
+      }.get();
+      Assert.assertTrue(getNullMsg);
+    }};
+
+  }
+
+  /**
+   This test add, read and remove an entry in routed rpc
+   */
+  @Test
+  public void testRoutedRpc() throws URISyntaxException {
+    new JavaTestKit(system) {{
+      ActorRef rpcRegistry = system.actorOf(RpcRegistryOld.props(Mockito.mock(ClusterWrapper.class)));
+      QName type = new QName(new URI("actor1"), "actor1");
+      RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, type, null);
+      final String route = "actor1";
+
+      Set<RpcRouter.RouteIdentifier<?, ?, ?>> routeIds = new HashSet<>();
+      routeIds.add(routeId);
+
+      AddRoutedRpc rpcMsg = new AddRoutedRpc(routeIds, route);
+      rpcRegistry.tell(rpcMsg, getRef());
+      expectMsgEquals(duration("2 second"), "Success");
+
+      GetRoutedRpc getRpc = new GetRoutedRpc(routeId);
+      rpcRegistry.tell(getRpc, getRef());
+
+      Boolean getMsg = new ExpectMsg<Boolean>("GetRoutedRpcReply") {
+        protected Boolean match(Object in) {
+          if (in instanceof GetRoutedRpcReply) {
+            GetRoutedRpcReply reply = (GetRoutedRpcReply)in;
+            return route.equals(reply.getRoutePath());
+          } else {
+            throw noMatch();
+          }
+        }
+      }.get(); // this extracts the received message
+
+      Assert.assertTrue(getMsg);
+
+      RemoveRoutedRpc removeMsg = new RemoveRoutedRpc(routeIds, route);
+      rpcRegistry.tell(removeMsg, getRef());
+      expectMsgEquals(duration("2 second"), "Success");
+
+      rpcRegistry.tell(getRpc, getRef());
+
+      Boolean getNullMsg = new ExpectMsg<Boolean>("GetRoutedRpcReply") {
+        protected Boolean match(Object in) {
+          if (in instanceof GetRoutedRpcReply) {
+            GetRoutedRpcReply reply = (GetRoutedRpcReply)in;
+            return reply.getRoutePath() == null;
+          } else {
+            throw noMatch();
+          }
+        }
+      }.get();
+      Assert.assertTrue(getNullMsg);
+    }};
+
+  }
+
+}
index d011d331a684e4f0bcbbbf395e18145364dfdf4a..ab609413dd82731466495365d0c46f28731fcdc0 100644 (file)
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
 package org.opendaylight.controller.remote.rpc.registry;
 
+import akka.actor.ActorPath;
 import akka.actor.ActorRef;
+import akka.actor.ActorSelection;
 import akka.actor.ActorSystem;
+import akka.actor.ChildActorPath;
+import akka.actor.Props;
+import akka.japi.Pair;
 import akka.testkit.JavaTestKit;
-import junit.framework.Assert;
+import com.typesafe.config.ConfigFactory;
+import org.junit.After;
 import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
-import org.mockito.Mockito;
 import org.opendaylight.controller.remote.rpc.RouteIdentifierImpl;
-import org.opendaylight.controller.remote.rpc.messages.AddRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.AddRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpcReply;
-import org.opendaylight.controller.remote.rpc.messages.GetRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRpcReply;
-import org.opendaylight.controller.remote.rpc.messages.RemoveRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.RemoveRpc;
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import org.opendaylight.yangtools.yang.common.QName;
+import scala.concurrent.Await;
+import scala.concurrent.Future;
+import scala.concurrent.duration.FiniteDuration;
 
 import java.net.URI;
 import java.net.URISyntaxException;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.AddOrUpdateRoute;
+import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.FindRouters;
+import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.FindRoutersReply;
+import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.SetLocalRouter;
 
 public class RpcRegistryTest {
 
-  static ActorSystem system;
-
-
-  @BeforeClass
-  public static void setup() {
-    system = ActorSystem.create();
-  }
-
-  @AfterClass
-  public static void teardown() {
-    JavaTestKit.shutdownActorSystem(system);
-    system = null;
-  }
-
-  /**
-   This test add, read and remove an entry in global rpc
-   */
-  @Test
-  public void testGlobalRpc() throws URISyntaxException {
-    new JavaTestKit(system) {{
-      ActorRef rpcRegistry = system.actorOf(RpcRegistry.props(Mockito.mock(ClusterWrapper.class)));
-      QName type = new QName(new URI("actor1"), "actor1");
-      RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, type, null);
-      final String route = "actor1";
-
-      AddRpc rpcMsg = new AddRpc(routeId, route);
-      rpcRegistry.tell(rpcMsg, getRef());
-      expectMsgEquals(duration("2 second"), "Success");
-
-      GetRpc getRpc = new GetRpc(routeId);
-      rpcRegistry.tell(getRpc, getRef());
-
-      Boolean getMsg = new ExpectMsg<Boolean>("GetRpcReply") {
-        protected Boolean match(Object in) {
-          if (in instanceof GetRpcReply) {
-            GetRpcReply reply = (GetRpcReply)in;
-            return route.equals(reply.getRoutePath());
-          } else {
-            throw noMatch();
-          }
-        }
-      }.get(); // this extracts the received message
+    private static ActorSystem node1;
+    private static ActorSystem node2;
+    private static ActorSystem node3;
+
+    private ActorRef registry1;
+    private ActorRef registry2;
+    private ActorRef registry3;
+
+    @BeforeClass
+    public static void setup() throws InterruptedException {
+        Thread.sleep(1000); //give some time for previous test to close netty ports
+        node1 = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("memberA"));
+        node2 = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("memberB"));
+        node3 = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("memberC"));
+    }
+
+    @AfterClass
+    public static void teardown(){
+        JavaTestKit.shutdownActorSystem(node1);
+        JavaTestKit.shutdownActorSystem(node2);
+        JavaTestKit.shutdownActorSystem(node3);
+        if (node1 != null)
+            node1.shutdown();
+        if (node2 != null)
+            node2.shutdown();
+        if (node3 != null)
+            node3.shutdown();
+
+    }
+
+    @Before
+    public void createRpcRegistry() throws InterruptedException {
+        registry1 = node1.actorOf(Props.create(RpcRegistry.class));
+        registry2 = node2.actorOf(Props.create(RpcRegistry.class));
+        registry3 = node3.actorOf(Props.create(RpcRegistry.class));
+    }
+
+    @After
+    public void stopRpcRegistry() throws InterruptedException {
+        if (registry1 != null)
+            node1.stop(registry1);
+        if (registry2 != null)
+            node2.stop(registry2);
+        if (registry3 != null)
+            node3.stop(registry3);
+    }
+
+    /**
+     * One node cluster.
+     * Register rpc. Ensure router can be found
+     *
+     * @throws URISyntaxException
+     * @throws InterruptedException
+     */
+    @Test
+    public void testWhenRpcAddedOneNodeShouldAppearOnSameNode() throws URISyntaxException, InterruptedException {
+
+        final JavaTestKit mockBroker = new JavaTestKit(node1);
+
+        //Add rpc on node 1
+        registry1.tell(new SetLocalRouter(mockBroker.getRef()), mockBroker.getRef());
+        registry1.tell(getAddRouteMessage(), mockBroker.getRef());
+
+        Thread.sleep(1000);//
+
+        //find the route on node 1's registry
+        registry1.tell(new FindRouters(createRouteId()), mockBroker.getRef());
+        FindRoutersReply message = mockBroker.expectMsgClass(JavaTestKit.duration("10 second"), FindRoutersReply.class);
+        List<Pair<ActorRef, Long>> pairs = message.getRouterWithUpdateTime();
+
+        validateRouterReceived(pairs, mockBroker.getRef());
+    }
+
+    /**
+     * Three node cluster.
+     * Register rpc on 1 node. Ensure its router can be found on other 2.
+     *
+     * @throws URISyntaxException
+     * @throws InterruptedException
+     */
+    @Test
+    public void testWhenRpcAddedOneNodeShouldAppearOnAnother() throws URISyntaxException, InterruptedException {
+
+        validateSystemStartup();
+
+        final JavaTestKit mockBroker1 = new JavaTestKit(node1);
+        final JavaTestKit mockBroker2 = new JavaTestKit(node2);
+        final JavaTestKit mockBroker3 = new JavaTestKit(node3);
+
+        //Add rpc on node 1
+        registry1.tell(new SetLocalRouter(mockBroker1.getRef()), mockBroker1.getRef());
+        registry1.tell(getAddRouteMessage(), mockBroker1.getRef());
+
+        Thread.sleep(5000);// give some time for bucket store data sync
+
+        //find the route in node 2's registry
+        registry2.tell(new FindRouters(createRouteId()), mockBroker2.getRef());
+        FindRoutersReply message = mockBroker2.expectMsgClass(JavaTestKit.duration("10 second"), FindRoutersReply.class);
+        List<Pair<ActorRef, Long>> pairs = message.getRouterWithUpdateTime();
+
+        validateRouterReceived(pairs, mockBroker1.getRef());
+
+        //find the route in node 3's registry
+        registry3.tell(new FindRouters(createRouteId()), mockBroker3.getRef());
+        message = mockBroker3.expectMsgClass(JavaTestKit.duration("10 second"), FindRoutersReply.class);
+        pairs = message.getRouterWithUpdateTime();
+
+        validateRouterReceived(pairs, mockBroker1.getRef());
+
+    }
+
+    /**
+     * Three node cluster.
+     * Register rpc on 2 nodes. Ensure 2 routers are found on 3rd.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testAnRpcAddedOnMultiNodesShouldReturnMultiRouter() throws Exception {
+
+        validateSystemStartup();
+
+        final JavaTestKit mockBroker1 = new JavaTestKit(node1);
+        final JavaTestKit mockBroker2 = new JavaTestKit(node2);
+        final JavaTestKit mockBroker3 = new JavaTestKit(node3);
+
+        //Thread.sleep(5000);//let system come up
+
+        //Add rpc on node 1
+        registry1.tell(new SetLocalRouter(mockBroker1.getRef()), mockBroker1.getRef());
+        registry1.tell(getAddRouteMessage(), mockBroker1.getRef());
+
+        //Add same rpc on node 2
+        registry2.tell(new SetLocalRouter(mockBroker2.getRef()), mockBroker2.getRef());
+        registry2.tell(getAddRouteMessage(), mockBroker2.getRef());
+
+        registry3.tell(new SetLocalRouter(mockBroker3.getRef()), mockBroker3.getRef());
+        Thread.sleep(5000);// give some time for bucket store data sync
+
+        //find the route in node 3's registry
+        registry3.tell(new FindRouters(createRouteId()), mockBroker3.getRef());
+        FindRoutersReply message = mockBroker3.expectMsgClass(JavaTestKit.duration("10 second"), FindRoutersReply.class);
+        List<Pair<ActorRef, Long>> pairs = message.getRouterWithUpdateTime();
 
-      Assert.assertTrue(getMsg);
+        validateMultiRouterReceived(pairs, mockBroker1.getRef(), mockBroker2.getRef());
 
-      RemoveRpc removeMsg = new RemoveRpc(routeId);
-      rpcRegistry.tell(removeMsg, getRef());
-      expectMsgEquals(duration("2 second"), "Success");
+    }
 
-      rpcRegistry.tell(getRpc, getRef());
+    private void validateMultiRouterReceived(List<Pair<ActorRef, Long>> actual, ActorRef... expected) {
+        Assert.assertTrue(actual != null);
+        Assert.assertTrue(actual.size() == expected.length);
+    }
 
-      Boolean getNullMsg = new ExpectMsg<Boolean>("GetRpcReply") {
-        protected Boolean match(Object in) {
-          if (in instanceof GetRpcReply) {
-            GetRpcReply reply = (GetRpcReply)in;
-            return reply.getRoutePath() == null;
-          } else {
-            throw noMatch();
-          }
-        }
-      }.get();
-      Assert.assertTrue(getNullMsg);
-    }};
-
-  }
-
-  /**
-   This test add, read and remove an entry in routed rpc
-   */
-  @Test
-  public void testRoutedRpc() throws URISyntaxException {
-    new JavaTestKit(system) {{
-      ActorRef rpcRegistry = system.actorOf(RpcRegistry.props(Mockito.mock(ClusterWrapper.class)));
-      QName type = new QName(new URI("actor1"), "actor1");
-      RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, type, null);
-      final String route = "actor1";
-
-      Set<RpcRouter.RouteIdentifier<?, ?, ?>> routeIds = new HashSet<>();
-      routeIds.add(routeId);
-
-      AddRoutedRpc rpcMsg = new AddRoutedRpc(routeIds, route);
-      rpcRegistry.tell(rpcMsg, getRef());
-      expectMsgEquals(duration("2 second"), "Success");
-
-      GetRoutedRpc getRpc = new GetRoutedRpc(routeId);
-      rpcRegistry.tell(getRpc, getRef());
-
-      Boolean getMsg = new ExpectMsg<Boolean>("GetRoutedRpcReply") {
-        protected Boolean match(Object in) {
-          if (in instanceof GetRoutedRpcReply) {
-            GetRoutedRpcReply reply = (GetRoutedRpcReply)in;
-            return route.equals(reply.getRoutePath());
-          } else {
-            throw noMatch();
-          }
+    private void validateRouterReceived(List<Pair<ActorRef, Long>> actual, ActorRef expected){
+        Assert.assertTrue(actual != null);
+        Assert.assertTrue(actual.size() == 1);
+
+        for (Pair<ActorRef, Long> pair : actual){
+            Assert.assertTrue(expected.path().uid() == pair.first().path().uid());
         }
-      }.get(); // this extracts the received message
+    }
 
-      Assert.assertTrue(getMsg);
+    private void validateSystemStartup() throws InterruptedException {
 
-      RemoveRoutedRpc removeMsg = new RemoveRoutedRpc(routeIds, route);
-      rpcRegistry.tell(removeMsg, getRef());
-      expectMsgEquals(duration("2 second"), "Success");
+        Thread.sleep(5000);
+        ActorPath gossiper1Path = new ChildActorPath(new ChildActorPath(registry1.path(), "store"), "gossiper");
+        ActorPath gossiper2Path = new ChildActorPath(new ChildActorPath(registry2.path(), "store"), "gossiper");
+        ActorPath gossiper3Path = new ChildActorPath(new ChildActorPath(registry3.path(), "store"), "gossiper");
 
-      rpcRegistry.tell(getRpc, getRef());
+        ActorSelection gossiper1 = node1.actorSelection(gossiper1Path);
+        ActorSelection gossiper2 = node2.actorSelection(gossiper2Path);
+        ActorSelection gossiper3 = node3.actorSelection(gossiper3Path);
 
-      Boolean getNullMsg = new ExpectMsg<Boolean>("GetRoutedRpcReply") {
-        protected Boolean match(Object in) {
-          if (in instanceof GetRoutedRpcReply) {
-            GetRoutedRpcReply reply = (GetRoutedRpcReply)in;
-            return reply.getRoutePath() == null;
-          } else {
-            throw noMatch();
-          }
-        }
-      }.get();
-      Assert.assertTrue(getNullMsg);
-    }};
 
-  }
+        if (!resolveReference(gossiper1, gossiper2, gossiper3))
+            Assert.fail("Could not find gossipers");
+    }
 
-}
+    private Boolean resolveReference(ActorSelection... gossipers) throws InterruptedException {
+
+        Boolean resolved = true;
+
+        for (int i=0; i< 5; i++) {
+            Thread.sleep(1000);
+            for (ActorSelection gossiper : gossipers) {
+                Future<ActorRef> future = gossiper.resolveOne(new FiniteDuration(5000, TimeUnit.MILLISECONDS));
+
+                ActorRef ref = null;
+                try {
+                    ref = Await.result(future, new FiniteDuration(10000, TimeUnit.MILLISECONDS));
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+
+                if (ref == null)
+                    resolved = false;
+            }
+
+            if (resolved) break;
+        }
+        return resolved;
+    }
+
+    private AddOrUpdateRoute getAddRouteMessage() throws URISyntaxException {
+        return new AddOrUpdateRoute(createRouteId());
+    }
+
+    private RpcRouter.RouteIdentifier<?,?,?> createRouteId() throws URISyntaxException {
+        QName type = new QName(new URI("/mockrpc"), "mockrpc");
+        return new RouteIdentifierImpl(null, type, null);
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/gossip/BucketStoreTest.java b/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/gossip/BucketStoreTest.java
new file mode 100644 (file)
index 0000000..7e87da0
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.remote.rpc.registry.gossip;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import akka.testkit.TestActorRef;
+import akka.testkit.TestProbe;
+import com.typesafe.config.ConfigFactory;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.remote.rpc.TerminationMonitor;
+
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+
+public class BucketStoreTest {
+
+    private static ActorSystem system;
+    private static BucketStore store;
+
+    private BucketStore mockStore;
+
+    @BeforeClass
+    public static void setup() {
+
+        system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("unit-test"));
+        system.actorOf(Props.create(TerminationMonitor.class), "termination-monitor");
+
+        store = createStore();
+    }
+
+    @AfterClass
+    public static void teardown() {
+        system.shutdown();
+    }
+
+    @Before
+    public void createMocks(){
+        mockStore = spy(store);
+    }
+
+    @After
+    public void resetMocks(){
+        reset(mockStore);
+    }
+
+    @Test
+    public void testReceiveUpdateBucket_WhenInputBucketShouldUpdateVersion(){
+        Bucket bucket = new BucketImpl();
+        Long expectedVersion = bucket.getVersion();
+
+        mockStore.receiveUpdateBucket(bucket);
+
+        Assert.assertEquals(bucket, mockStore.getLocalBucket());
+        Assert.assertEquals(expectedVersion, mockStore.getLocalBucket().getVersion());
+    }
+
+    /**
+     * Create BucketStore actor and returns the underlying instance of BucketStore class.
+     *
+     * @return instance of BucketStore class
+     */
+    private static BucketStore createStore(){
+        TestProbe mockActor = new TestProbe(system);
+        ActorRef mockGossiper = mockActor.ref();
+        final Props props = Props.create(BucketStore.class, mockGossiper);
+        final TestActorRef<BucketStore> testRef = TestActorRef.create(system, props, "testStore");
+
+        return testRef.underlyingActor();
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/gossip/GossiperTest.java b/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/gossip/GossiperTest.java
new file mode 100644 (file)
index 0000000..d862dcb
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.remote.rpc.registry.gossip;
+
+import akka.actor.ActorSystem;
+import akka.actor.Address;
+import akka.actor.Props;
+import akka.testkit.TestActorRef;
+import com.typesafe.config.ConfigFactory;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.remote.rpc.TerminationMonitor;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyMap;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.GossiperMessages.GossipEnvelope;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.GossiperMessages.GossipStatus;
+
+
+public class GossiperTest {
+
+    private static ActorSystem system;
+    private static Gossiper gossiper;
+
+    private Gossiper mockGossiper;
+
+    @BeforeClass
+    public static void setup() throws InterruptedException {
+        Thread.sleep(1000);//give some time for previous test to stop the system. Netty port conflict arises otherwise.
+        system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("unit-test"));
+        system.actorOf(Props.create(TerminationMonitor.class), "termination-monitor");
+
+        gossiper = createGossiper();
+    }
+
+    @AfterClass
+    public static void teardown() {
+        if (system != null)
+            system.shutdown();
+    }
+
+    @Before
+    public void createMocks(){
+        mockGossiper = spy(gossiper);
+    }
+
+    @After
+    public void resetMocks(){
+        reset(mockGossiper);
+
+    }
+
+    @Test
+    public void testReceiveGossipTick_WhenNoRemoteMemberShouldIgnore(){
+
+        mockGossiper.setClusterMembers(Collections.EMPTY_LIST);
+        doNothing().when(mockGossiper).getLocalStatusAndSendTo(any(Address.class));
+        mockGossiper.receiveGossipTick();
+        verify(mockGossiper, times(0)).getLocalStatusAndSendTo(any(Address.class));
+    }
+
+    @Test
+    public void testReceiveGossipTick_WhenRemoteMemberExistsShouldSendStatus(){
+        List<Address> members = new ArrayList<>();
+        Address remote = new Address("tcp", "member");
+        members.add(remote);
+
+        mockGossiper.setClusterMembers(members);
+        doNothing().when(mockGossiper).getLocalStatusAndSendTo(any(Address.class));
+        mockGossiper.receiveGossipTick();
+        verify(mockGossiper, times(1)).getLocalStatusAndSendTo(any(Address.class));
+    }
+
+    @Test
+    public void testReceiveGossipStatus_WhenSenderIsNonMemberShouldIgnore(){
+
+        Address nonMember = new Address("tcp", "non-member");
+        GossipStatus remoteStatus = new GossipStatus(nonMember, mock(Map.class));
+
+        //add a member
+        List<Address> members = new ArrayList<>();
+        members.add(new Address("tcp", "member"));
+
+        mockGossiper.setClusterMembers(members);
+        mockGossiper.receiveGossipStatus(remoteStatus);
+        verify(mockGossiper, times(0)).getSender();
+    }
+
+    @Test
+    public void testReceiveGossip_WhenNotAddressedToSelfShouldIgnore(){
+        Address notSelf = new Address("tcp", "not-self");
+
+        GossipEnvelope envelope = new GossipEnvelope(notSelf, notSelf, mock(Map.class));
+        doNothing().when(mockGossiper).updateRemoteBuckets(anyMap());
+        mockGossiper.receiveGossip(envelope);
+        verify(mockGossiper, times(0)).updateRemoteBuckets(anyMap());
+    }
+
+    @Test
+    public void testUpdateRemoteBuckets_WhenNoBucketShouldIgnore(){
+
+        mockGossiper.updateRemoteBuckets(null);
+        verify(mockGossiper, times(0)).getContext();
+
+        Map<Address, Bucket> empty = Collections.emptyMap();
+        mockGossiper.updateRemoteBuckets(empty);
+        verify(mockGossiper, times(0)).getContext();
+    }
+
+    /**
+     * Create Gossiper actor and return the underlying instance of Gossiper class.
+     *
+     * @return instance of Gossiper class
+     */
+    private static Gossiper createGossiper(){
+
+        final Props props = Props.create(Gossiper.class, false);
+        final TestActorRef<Gossiper> testRef = TestActorRef.create(system, props, "testGossiper");
+
+        return testRef.underlyingActor();
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/test/resources/application.conf b/opendaylight/md-sal/sal-remoterpc-connector/src/test/resources/application.conf
new file mode 100644 (file)
index 0000000..874d3fc
--- /dev/null
@@ -0,0 +1,116 @@
+odl-cluster{
+  akka {
+    loglevel = "INFO"
+    #log-config-on-start = on
+
+    actor {
+      provider = "akka.cluster.ClusterActorRefProvider"
+      debug{
+        #autoreceive = on
+        #lifecycle = on
+
+      }
+    }
+    remote {
+      log-received-messages = on
+      log-sent-messages = on
+
+      log-remote-lifecycle-events = off
+      netty.tcp {
+        hostname = "localhost"
+        port = 2551
+      }
+    }
+
+    cluster {
+      seed-nodes = ["akka.tcp://opendaylight-rpc@localhost:2551"]
+
+      auto-down-unreachable-after = 10s
+    }
+  }
+}
+unit-test{
+  akka {
+    loglevel = "INFO"
+    loggers = ["akka.event.slf4j.Slf4jLogger"]
+    actor {
+      provider = "akka.cluster.ClusterActorRefProvider"
+    }
+  }
+}
+
+memberA{
+  akka {
+    loglevel = "INFO"
+    loggers = ["akka.event.slf4j.Slf4jLogger"]
+    actor {
+      provider = "akka.cluster.ClusterActorRefProvider"
+    }
+    remote {
+      log-received-messages = off
+      log-sent-messages = off
+
+      log-remote-lifecycle-events = off
+      netty.tcp {
+        hostname = "localhost"
+        port = 2551
+      }
+    }
+
+    cluster {
+      seed-nodes = ["akka.tcp://opendaylight-rpc@localhost:2551"]
+
+      auto-down-unreachable-after = 10s
+    }
+  }
+}
+memberB{
+  akka {
+    loglevel = "INFO"
+    loggers = ["akka.event.slf4j.Slf4jLogger"]
+    actor {
+      provider = "akka.cluster.ClusterActorRefProvider"
+    }
+    remote {
+      log-received-messages = off
+      log-sent-messages = off
+
+      log-remote-lifecycle-events = off
+      netty.tcp {
+        hostname = "localhost"
+        port = 2552
+      }
+    }
+
+    cluster {
+      seed-nodes = ["akka.tcp://opendaylight-rpc@localhost:2551"]
+
+      auto-down-unreachable-after = 10s
+    }
+  }
+}
+memberC{
+  akka {
+    loglevel = "INFO"
+    loggers = ["akka.event.slf4j.Slf4jLogger"]
+    actor {
+      provider = "akka.cluster.ClusterActorRefProvider"
+    }
+    remote {
+      log-received-messages = off
+      log-sent-messages = off
+
+      log-remote-lifecycle-events = off
+      netty.tcp {
+        hostname = "localhost"
+        port = 2553
+      }
+    }
+
+    cluster {
+      seed-nodes = ["akka.tcp://opendaylight-rpc@localhost:2551"]
+
+      auto-down-unreachable-after = 10s
+    }
+  }
+}
\ No newline at end of file
index ae8e1b05af95f68f29bad798cded1a701e946c80..93e6a2c0e98504e169703423837177078992c2a4 100644 (file)
@@ -14,8 +14,6 @@ import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
 import com.google.common.base.Splitter;
 import com.google.common.base.Strings;
-import com.google.common.collect.BiMap;
-import com.google.common.collect.HashBiMap;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import java.io.UnsupportedEncodingException;
@@ -86,10 +84,6 @@ public class ControllerContext implements SchemaContextListener {
 
     private static final Splitter SLASH_SPLITTER = Splitter.on('/');
 
-    private final BiMap<URI, String> uriToModuleName = HashBiMap.<URI, String> create();
-
-    private final Map<String, URI> moduleNameToUri = uriToModuleName.inverse();
-
     private final AtomicReference<Map<QName, RpcDefinition>> qnameToRpc =
             new AtomicReference<>(Collections.<QName, RpcDefinition>emptyMap());
 
@@ -279,16 +273,8 @@ public class ControllerContext implements SchemaContextListener {
     public String findModuleNameByNamespace(final URI namespace) {
         this.checkPreconditions();
 
-        String moduleName = this.uriToModuleName.get(namespace);
-        if (moduleName == null) {
-            final Module module = this.findModuleByNamespace(namespace);
-            if (module != null) {
-                moduleName = module.getName();
-                this.uriToModuleName.put(namespace, moduleName);
-            }
-        }
-
-        return moduleName;
+        final Module module = this.findModuleByNamespace(namespace);
+        return module == null ? null : module.getName();
     }
 
     public String findModuleNameByNamespace(final DOMMountPoint mountPoint, final URI namespace) {
@@ -297,16 +283,8 @@ public class ControllerContext implements SchemaContextListener {
     }
 
     public URI findNamespaceByModuleName(final String moduleName) {
-        URI namespace = this.moduleNameToUri.get(moduleName);
-        if (namespace == null) {
-            Module module = this.findModuleByName(moduleName);
-            if (module != null) {
-                URI _namespace = module.getNamespace();
-                namespace = _namespace;
-                this.uriToModuleName.put(namespace, moduleName);
-            }
-        }
-        return namespace;
+        final Module module = this.findModuleByName(moduleName);
+        return module == null ? null : module.getNamespace();
     }
 
     public URI findNamespaceByModuleName(final DOMMountPoint mountPoint, final String moduleName) {
@@ -326,26 +304,15 @@ public class ControllerContext implements SchemaContextListener {
         return globalSchema.getModules();
     }
 
+    private static final CharSequence toRestconfIdentifier(final SchemaContext context, final QName qname) {
+        final Module schema = context.findModuleByNamespaceAndRevision(qname.getNamespace(), qname.getRevision());
+        return schema == null ? null : schema.getName() + ':' + qname.getLocalName();
+    }
+
     public CharSequence toRestconfIdentifier(final QName qname) {
         this.checkPreconditions();
 
-        String module = this.uriToModuleName.get(qname.getNamespace());
-        if (module == null) {
-            final Module moduleSchema = globalSchema.findModuleByNamespaceAndRevision(qname.getNamespace(),
-                    qname.getRevision());
-            if (moduleSchema == null) {
-                return null;
-            }
-
-            this.uriToModuleName.put(qname.getNamespace(), moduleSchema.getName());
-            module = moduleSchema.getName();
-        }
-
-        StringBuilder builder = new StringBuilder();
-        builder.append(module);
-        builder.append(":");
-        builder.append(qname.getLocalName());
-        return builder.toString();
+        return toRestconfIdentifier(globalSchema, qname);
     }
 
     public CharSequence toRestconfIdentifier(final DOMMountPoint mountPoint, final QName qname) {
@@ -353,19 +320,7 @@ public class ControllerContext implements SchemaContextListener {
             return null;
         }
 
-        SchemaContext schemaContext = mountPoint.getSchemaContext();
-
-        final Module moduleSchema = schemaContext.findModuleByNamespaceAndRevision(qname.getNamespace(),
-                qname.getRevision());
-        if (moduleSchema == null) {
-            return null;
-        }
-
-        StringBuilder builder = new StringBuilder();
-        builder.append(moduleSchema.getName());
-        builder.append(":");
-        builder.append(qname.getLocalName());
-        return builder.toString();
+        return toRestconfIdentifier(mountPoint.getSchemaContext(), qname);
     }
 
     public Module getRestconfModule() {
@@ -391,7 +346,7 @@ public class ControllerContext implements SchemaContextListener {
 
         final GroupingDefinition restconfGrouping = Iterables.getFirst(filteredGroups, null);
 
-        List<DataSchemaNode> instanceDataChildrenByName = this.findInstanceDataChildrenByName(restconfGrouping,
+        List<DataSchemaNode> instanceDataChildrenByName = findInstanceDataChildrenByName(restconfGrouping,
                 Draft02.RestConfModule.ERRORS_CONTAINER_SCHEMA_NODE);
         return Iterables.getFirst(instanceDataChildrenByName, null);
     }
@@ -417,38 +372,38 @@ public class ControllerContext implements SchemaContextListener {
         Iterable<GroupingDefinition> filteredGroups = Iterables.filter(groupings, GROUPING_FILTER);
         final GroupingDefinition restconfGrouping = Iterables.getFirst(filteredGroups, null);
 
-        List<DataSchemaNode> instanceDataChildrenByName = this.findInstanceDataChildrenByName(restconfGrouping,
+        List<DataSchemaNode> instanceDataChildrenByName = findInstanceDataChildrenByName(restconfGrouping,
                 Draft02.RestConfModule.RESTCONF_CONTAINER_SCHEMA_NODE);
         final DataSchemaNode restconfContainer = Iterables.getFirst(instanceDataChildrenByName, null);
 
         if (Objects.equal(schemaNodeName, Draft02.RestConfModule.OPERATIONS_CONTAINER_SCHEMA_NODE)) {
-            List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+            List<DataSchemaNode> instances = findInstanceDataChildrenByName(
                     ((DataNodeContainer) restconfContainer), Draft02.RestConfModule.OPERATIONS_CONTAINER_SCHEMA_NODE);
             return Iterables.getFirst(instances, null);
         } else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE)) {
-            List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+            List<DataSchemaNode> instances = findInstanceDataChildrenByName(
                     ((DataNodeContainer) restconfContainer), Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
             return Iterables.getFirst(instances, null);
         } else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.STREAM_LIST_SCHEMA_NODE)) {
-            List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+            List<DataSchemaNode> instances = findInstanceDataChildrenByName(
                     ((DataNodeContainer) restconfContainer), Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
             final DataSchemaNode modules = Iterables.getFirst(instances, null);
-            instances = this.findInstanceDataChildrenByName(((DataNodeContainer) modules),
+            instances = findInstanceDataChildrenByName(((DataNodeContainer) modules),
                     Draft02.RestConfModule.STREAM_LIST_SCHEMA_NODE);
             return Iterables.getFirst(instances, null);
         } else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE)) {
-            List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+            List<DataSchemaNode> instances = findInstanceDataChildrenByName(
                     ((DataNodeContainer) restconfContainer), Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
             return Iterables.getFirst(instances, null);
         } else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE)) {
-            List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+            List<DataSchemaNode> instances = findInstanceDataChildrenByName(
                     ((DataNodeContainer) restconfContainer), Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
             final DataSchemaNode modules = Iterables.getFirst(instances, null);
-            instances = this.findInstanceDataChildrenByName(((DataNodeContainer) modules),
+            instances = findInstanceDataChildrenByName(((DataNodeContainer) modules),
                     Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
             return Iterables.getFirst(instances, null);
         } else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE)) {
-            List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+            List<DataSchemaNode> instances = findInstanceDataChildrenByName(
                     ((DataNodeContainer) restconfContainer), Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
             return Iterables.getFirst(instances, null);
         }
@@ -602,7 +557,7 @@ public class ControllerContext implements SchemaContextListener {
                 }
             }
 
-            targetNode = this.findInstanceDataChildByNameAndNamespace(parentNode, nodeName, module.getNamespace());
+            targetNode = findInstanceDataChildByNameAndNamespace(parentNode, nodeName, module.getNamespace());
             if (targetNode == null) {
                 throw new RestconfDocumentedException("URI has bad format. Possible reasons:\n" + " 1. \"" + head
                         + "\" was not found in parent data node.\n" + " 2. \"" + head
@@ -610,7 +565,7 @@ public class ControllerContext implements SchemaContextListener {
                         ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
             }
         } else {
-            final List<DataSchemaNode> potentialSchemaNodes = this.findInstanceDataChildrenByName(parentNode, nodeName);
+            final List<DataSchemaNode> potentialSchemaNodes = findInstanceDataChildrenByName(parentNode, nodeName);
             if (potentialSchemaNodes.size() > 1) {
                 final StringBuilder strBuilder = new StringBuilder();
                 for (final DataSchemaNode potentialNodeSchema : potentialSchemaNodes) {
@@ -680,11 +635,11 @@ public class ControllerContext implements SchemaContextListener {
         return new InstanceIdWithSchemaNode(builder.toInstance(), targetNode, mountPoint);
     }
 
-    public DataSchemaNode findInstanceDataChildByNameAndNamespace(final DataNodeContainer container, final String name,
+    public static DataSchemaNode findInstanceDataChildByNameAndNamespace(final DataNodeContainer container, final String name,
             final URI namespace) {
         Preconditions.<URI> checkNotNull(namespace);
 
-        final List<DataSchemaNode> potentialSchemaNodes = this.findInstanceDataChildrenByName(container, name);
+        final List<DataSchemaNode> potentialSchemaNodes = findInstanceDataChildrenByName(container, name);
 
         Predicate<DataSchemaNode> filter = new Predicate<DataSchemaNode>() {
             @Override
@@ -697,12 +652,12 @@ public class ControllerContext implements SchemaContextListener {
         return Iterables.getFirst(result, null);
     }
 
-    public List<DataSchemaNode> findInstanceDataChildrenByName(final DataNodeContainer container, final String name) {
+    public static List<DataSchemaNode> findInstanceDataChildrenByName(final DataNodeContainer container, final String name) {
         Preconditions.<DataNodeContainer> checkNotNull(container);
         Preconditions.<String> checkNotNull(name);
 
         List<DataSchemaNode> instantiatedDataNodeContainers = new ArrayList<DataSchemaNode>();
-        this.collectInstanceDataNodeContainers(instantiatedDataNodeContainers, container, name);
+        collectInstanceDataNodeContainers(instantiatedDataNodeContainers, container, name);
         return instantiatedDataNodeContainers;
     }
 
@@ -713,7 +668,7 @@ public class ControllerContext implements SchemaContextListener {
         }
     };
 
-    private void collectInstanceDataNodeContainers(final List<DataSchemaNode> potentialSchemaNodes,
+    private static void collectInstanceDataNodeContainers(final List<DataSchemaNode> potentialSchemaNodes,
             final DataNodeContainer container, final String name) {
 
         Predicate<DataSchemaNode> filter = new Predicate<DataSchemaNode>() {
@@ -728,7 +683,7 @@ public class ControllerContext implements SchemaContextListener {
         // Can't combine this loop with the filter above because the filter is
         // lazily-applied by Iterables.filter.
         for (final DataSchemaNode potentialNode : nodes) {
-            if (this.isInstantiatedDataSchema(potentialNode)) {
+            if (isInstantiatedDataSchema(potentialNode)) {
                 potentialSchemaNodes.add(potentialNode);
             }
         }
@@ -738,11 +693,11 @@ public class ControllerContext implements SchemaContextListener {
 
         final Iterable<ChoiceCaseNode> allCases = Iterables.<ChoiceCaseNode> concat(map);
         for (final ChoiceCaseNode caze : allCases) {
-            this.collectInstanceDataNodeContainers(potentialSchemaNodes, caze, name);
+            collectInstanceDataNodeContainers(potentialSchemaNodes, caze, name);
         }
     }
 
-    public boolean isInstantiatedDataSchema(final DataSchemaNode node) {
+    public static boolean isInstantiatedDataSchema(final DataSchemaNode node) {
         return node instanceof LeafSchemaNode || node instanceof LeafListSchemaNode
                 || node instanceof ContainerSchemaNode || node instanceof ListSchemaNode
                 || node instanceof AnyXmlSchemaNode;
@@ -876,11 +831,7 @@ public class ControllerContext implements SchemaContextListener {
     }
 
     private CharSequence convertToRestconfIdentifier(final NodeIdentifier argument, final ContainerSchemaNode node) {
-        StringBuilder builder = new StringBuilder();
-        builder.append("/");
-        QName nodeType = argument.getNodeType();
-        builder.append(this.toRestconfIdentifier(nodeType));
-        return builder.toString();
+        return "/" + this.toRestconfIdentifier(argument.getNodeType());
     }
 
     private CharSequence convertToRestconfIdentifier(final NodeIdentifierWithPredicates argument,
@@ -890,9 +841,9 @@ public class ControllerContext implements SchemaContextListener {
         final Map<QName, Object> keyValues = argument.getKeyValues();
 
         StringBuilder builder = new StringBuilder();
-        builder.append("/");
+        builder.append('/');
         builder.append(nodeIdentifier);
-        builder.append("/");
+        builder.append('/');
 
         List<QName> keyDefinition = node.getKeyDefinition();
         boolean hasElements = false;
@@ -900,7 +851,7 @@ public class ControllerContext implements SchemaContextListener {
             if (!hasElements) {
                 hasElements = true;
             } else {
-                builder.append("/");
+                builder.append('/');
             }
 
             try {
index d61ccfdacf0e387fdd71e28a69b4b1bde6e99a0d..665fafacc893b7b05235daaa34f8e709d6f2702f 100644 (file)
@@ -244,7 +244,7 @@ public class RestCodec {
             for (int i = 0; i < identities.size(); i++) {
                 IdentityValue identityValue = identities.get(i);
                 URI validNamespace = resolveValidNamespace(identityValue.getNamespace(), mountPoint);
-                DataSchemaNode node = ControllerContext.getInstance().findInstanceDataChildByNameAndNamespace(
+                DataSchemaNode node = ControllerContext.findInstanceDataChildByNameAndNamespace(
                         parentContainer, identityValue.getValue(), validNamespace);
                 if (node == null) {
                     logger.info("'{}' node was not found in {}", identityValue, parentContainer.getChildNodes());
@@ -271,7 +271,7 @@ public class RestCodec {
                         Map<QName, Object> predicatesMap = new HashMap<>();
                         for (Predicate predicate : identityValue.getPredicates()) {
                             validNamespace = resolveValidNamespace(predicate.getName().getNamespace(), mountPoint);
-                            DataSchemaNode listKey = ControllerContext.getInstance()
+                            DataSchemaNode listKey = ControllerContext
                                     .findInstanceDataChildByNameAndNamespace(listNode, predicate.getName().getValue(),
                                             validNamespace);
                             predicatesMap.put(listKey.getQName(), predicate.getValue());
@@ -286,7 +286,7 @@ public class RestCodec {
                 }
                 result.add(pathArgument);
                 if (i < identities.size() - 1) { // last element in instance-identifier can be other than
-                                                 // DataNodeContainer
+                    // DataNodeContainer
                     if (node instanceof DataNodeContainer) {
                         parentContainer = (DataNodeContainer) node;
                     } else {
index 5cb3cc2bae495724c4133a57c7feb929f682ebf2..73ca02c505f47741ca4e38c071a780a0f32e1cdf 100644 (file)
@@ -15,6 +15,7 @@ import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
+
 import java.net.URI;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
@@ -32,6 +33,7 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
+
 import org.apache.commons.lang3.StringUtils;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -60,12 +62,8 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.InstanceIdentifierBuilder;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.composite.node.schema.cnsn.parser.CnSnToNormalizedNodeParserFactory;
-import org.opendaylight.yangtools.yang.data.composite.node.schema.cnsn.serializer.CnSnFromNormalizedNodeSerializerFactory;
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
@@ -358,31 +356,31 @@ public class RestconfImpl implements RestconfService {
 
     private CompositeNode toStreamCompositeNode(final String streamName, final DataSchemaNode streamSchemaNode) {
         final List<Node<?>> streamNodeValues = new ArrayList<Node<?>>();
-        List<DataSchemaNode> instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+        List<DataSchemaNode> instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) streamSchemaNode), "name");
         final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         streamNodeValues
-                .add(NodeFactory.<String> createImmutableSimpleNode(nameSchemaNode.getQName(), null, streamName));
+        .add(NodeFactory.<String> createImmutableSimpleNode(nameSchemaNode.getQName(), null, streamName));
 
-        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) streamSchemaNode), "description");
         final DataSchemaNode descriptionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         streamNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(descriptionSchemaNode.getQName(), null,
                 "DESCRIPTION_PLACEHOLDER"));
 
-        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) streamSchemaNode), "replay-support");
         final DataSchemaNode replaySupportSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         streamNodeValues.add(NodeFactory.<Boolean> createImmutableSimpleNode(replaySupportSchemaNode.getQName(), null,
                 Boolean.valueOf(true)));
 
-        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) streamSchemaNode), "replay-log-creation-time");
         final DataSchemaNode replayLogCreationTimeSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         streamNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(replayLogCreationTimeSchemaNode.getQName(),
                 null, ""));
 
-        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) streamSchemaNode), "events");
         final DataSchemaNode eventsSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         streamNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(eventsSchemaNode.getQName(), null, ""));
@@ -392,26 +390,26 @@ public class RestconfImpl implements RestconfService {
 
     private CompositeNode toModuleCompositeNode(final Module module, final DataSchemaNode moduleSchemaNode) {
         final List<Node<?>> moduleNodeValues = new ArrayList<Node<?>>();
-        List<DataSchemaNode> instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+        List<DataSchemaNode> instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) moduleSchemaNode), "name");
         final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         moduleNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(nameSchemaNode.getQName(), null,
                 module.getName()));
 
-        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) moduleSchemaNode), "revision");
         final DataSchemaNode revisionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         Date _revision = module.getRevision();
         moduleNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(revisionSchemaNode.getQName(), null,
                 REVISION_FORMAT.format(_revision)));
 
-        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) moduleSchemaNode), "namespace");
         final DataSchemaNode namespaceSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         moduleNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(namespaceSchemaNode.getQName(), null,
                 module.getNamespace().toString()));
 
-        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) moduleSchemaNode), "feature");
         final DataSchemaNode featureSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         for (final FeatureDefinition feature : module.getFeatures()) {
@@ -830,7 +828,7 @@ public class RestconfImpl implements RestconfService {
             }
 
             String payloadName = this.getName(payload);
-            final DataSchemaNode schemaNode = this.controllerContext.findInstanceDataChildByNameAndNamespace(
+            final DataSchemaNode schemaNode = ControllerContext.findInstanceDataChildByNameAndNamespace(
                     parentSchema, payloadName, module.getNamespace());
             value = this.normalizeNode(payload, schemaNode, mountPoint);
 
@@ -878,7 +876,7 @@ public class RestconfImpl implements RestconfService {
         }
 
         String payloadName = this.getName(payload);
-        final DataSchemaNode schemaNode = this.controllerContext.findInstanceDataChildByNameAndNamespace(module,
+        final DataSchemaNode schemaNode = ControllerContext.findInstanceDataChildByNameAndNamespace(module,
                 payloadName, module.getNamespace());
         final CompositeNode value = this.normalizeNode(payload, schemaNode, null);
         final InstanceIdWithSchemaNode iiWithData = this.addLastIdentifierFromData(null, value, schemaNode);
@@ -1102,10 +1100,10 @@ public class RestconfImpl implements RestconfService {
     private boolean representsMountPointRootData(final Node<?> data) {
         URI namespace = this.namespace(data);
         return (SchemaContext.NAME.getNamespace().equals(namespace) /*
-                                                                     * || MOUNT_POINT_MODULE_NAME .equals( namespace .
-                                                                     * toString( ) )
-                                                                     */)
-                && SchemaContext.NAME.getLocalName().equals(this.localName(data));
+         * || MOUNT_POINT_MODULE_NAME .equals( namespace .
+         * toString( ) )
+         */)
+         && SchemaContext.NAME.getLocalName().equals(this.localName(data));
     }
 
     private String addMountPointIdentifier(final String identifier) {
@@ -1239,7 +1237,7 @@ public class RestconfImpl implements RestconfService {
         final List<NodeWrapper<?>> children = compositeNodeBuilder.getValues();
         checkNodeMultiplicityAccordingToSchema(schema, children);
         for (final NodeWrapper<? extends Object> child : children) {
-            final List<DataSchemaNode> potentialSchemaNodes = this.controllerContext.findInstanceDataChildrenByName(
+            final List<DataSchemaNode> potentialSchemaNodes = ControllerContext.findInstanceDataChildrenByName(
                     schema, child.getLocalName());
 
             if (potentialSchemaNodes.size() > 1 && child.getNamespace() == null) {
@@ -1334,15 +1332,16 @@ public class RestconfImpl implements RestconfService {
         }
 
         if (nodeBuilder.getNamespace() == null || Objects.equal(nodeBuilder.getNamespace(), validQName.getNamespace())
-                || Objects.equal(nodeBuilder.getNamespace().toString(), moduleName) /*
-                                                                                     * || Note : this check is wrong -
-                                                                                     * can never be true as it compares
-                                                                                     * a URI with a String not sure what
-                                                                                     * the intention is so commented out
-                                                                                     * ... Objects . equal ( nodeBuilder
-                                                                                     * . getNamespace ( ) ,
-                                                                                     * MOUNT_POINT_MODULE_NAME )
-                                                                                     */) {
+                || Objects.equal(nodeBuilder.getNamespace().toString(), moduleName)) {
+            /*
+             * || Note : this check is wrong -
+             * can never be true as it compares
+             * a URI with a String not sure what
+             * the intention is so commented out
+             * ... Objects . equal ( nodeBuilder
+             * . getNamespace ( ) ,
+             * MOUNT_POINT_MODULE_NAME )
+             */
 
             nodeBuilder.setQname(validQName);
         }
@@ -1411,25 +1410,15 @@ public class RestconfImpl implements RestconfService {
     }
 
     private CompositeNode datastoreNormalizedNodeToCompositeNode(final NormalizedNode<?, ?> dataNode, final DataSchemaNode schema) {
-        Iterable<Node<?>> nodes = null;
+        Node<?> nodes = null;
         if (dataNode == null) {
             throw new RestconfDocumentedException(new RestconfError(ErrorType.APPLICATION, ErrorTag.DATA_MISSING,
                     "No data was found."));
         }
-        if (schema instanceof ContainerSchemaNode && dataNode instanceof ContainerNode) {
-            nodes = CnSnFromNormalizedNodeSerializerFactory.getInstance().getContainerNodeSerializer()
-                    .serialize((ContainerSchemaNode) schema, (ContainerNode) dataNode);
-        } else if (schema instanceof ListSchemaNode && dataNode instanceof MapNode) {
-            nodes = CnSnFromNormalizedNodeSerializerFactory.getInstance().getMapNodeSerializer()
-                    .serialize((ListSchemaNode) schema, (MapNode) dataNode);
-        } else if (schema instanceof ListSchemaNode && dataNode instanceof MapEntryNode) {
-            nodes = CnSnFromNormalizedNodeSerializerFactory.getInstance().getMapEntryNodeSerializer()
-                    .serialize((ListSchemaNode) schema, (MapEntryNode) dataNode);
-        }
+        nodes = DataNormalizer.toLegacy(dataNode);
         if (nodes != null) {
-            if (nodes.iterator().hasNext()) {
-                Node<?> nodeOldStruct = nodes.iterator().next();
-                return (CompositeNode) nodeOldStruct;
+            if (nodes instanceof CompositeNode) {
+                return (CompositeNode) nodes;
             } else {
                 LOG.error("The node " + dataNode.getNodeType() + " couldn't be transformed to compositenode.");
             }
index d4f69090819c152895eeb53b71bbfc9107fda511..539248a147cd4eea16dca9f4725cf26e9b185496 100644 (file)
@@ -61,17 +61,14 @@ import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
@@ -674,9 +671,7 @@ public class RestGetOperationTest extends JerseyTest {
     }
 
     private NormalizedNode prepareCnDataForSlashesBehindMountPointTest() throws ParseException {
-        CollectionNodeBuilder<MapEntryNode, MapNode> lst1 = ImmutableMapNodeBuilder.create();
-        lst1.withNodeIdentifier(TestUtils.getNodeIdentifier("lst1", "test:module", "2014-01-09"));
-        lst1.withChild(ImmutableMapEntryNodeBuilder
+        return ImmutableMapEntryNodeBuilder
                 .create()
                 .withNodeIdentifier(
                         TestUtils.getNodeIdentifierPredicate("lst1", "test:module", "2014-01-09", "lf11",
@@ -684,9 +679,8 @@ public class RestGetOperationTest extends JerseyTest {
                 .withChild(
                         ImmutableLeafNodeBuilder.create()
                                 .withNodeIdentifier(TestUtils.getNodeIdentifier("lf11", "test:module", "2014-01-09"))
-                                .withValue("GigabitEthernet0/0/0/0").build()).build());
+                                .withValue("GigabitEthernet0/0/0/0").build()).build();
 
-        return lst1.build();
     }
 
     /**
@@ -905,6 +899,9 @@ public class RestGetOperationTest extends JerseyTest {
                         expectLeaf("depth3-leaf1", "depth3-leaf1-value")));
     }
 
+    /**
+     * Tests behavior when invalid value of depth URI parameter
+     */
     @Test
     public void getDataWithInvalidDepthParameterTest() {
 
@@ -931,6 +928,10 @@ public class RestGetOperationTest extends JerseyTest {
 
     private void getDataWithInvalidDepthParameterTest(final UriInfo uriInfo) {
         try {
+            QName qNameDepth1Cont = QName.create("urn:nested:module", "2014-06-3", "depth1-cont");
+            YangInstanceIdentifier ii = YangInstanceIdentifier.builder().node(qNameDepth1Cont).build();
+            NormalizedNode value = (NormalizedNode<?,?>)(Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(qNameDepth1Cont)).build());
+            when(brokerFacade.readConfigurationData(eq(ii))).thenReturn(value);
             restconfImpl.readConfigurationData("nested-module:depth1-cont", uriInfo);
             fail("Expected RestconfDocumentedException");
         } catch (RestconfDocumentedException e) {
index 562cac0bcf523a74a62163116105a9fff7d47c8d..c2b153f02bd27b6729dbba2a89a201a306763a99 100644 (file)
@@ -62,15 +62,12 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.composite.node.schema.cnsn.parser.CnSnToNormalizedNodeParserFactory;
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
@@ -407,9 +404,7 @@ public final class TestUtils {
 
     static NormalizedNode prepareNormalizedNodeWithIetfInterfacesInterfacesData() throws ParseException {
         String ietfInterfacesDate = "2013-07-04";
-        CollectionNodeBuilder<MapEntryNode, MapNode> intface = ImmutableMapNodeBuilder.create();
         String namespace = "urn:ietf:params:xml:ns:yang:ietf-interfaces";
-        intface.withNodeIdentifier(getNodeIdentifier("interface", namespace, ietfInterfacesDate));
         DataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> mapEntryNode = ImmutableMapEntryNodeBuilder.create();
 
         Map<String, Object> predicates = new HashMap<>();
@@ -431,8 +426,6 @@ public final class TestUtils {
                 .withNodeIdentifier(getNodeIdentifier("description", namespace, ietfInterfacesDate))
                 .withValue("some interface").build());
 
-        intface.withChild(mapEntryNode.build());
-
-        return intface.build();
+        return mapEntryNode.build();
     }
 }
index 9995a8f1271ea348b835fb8b296937797f944f6d..a1d5ab0a129fa92d362b4faa7d1e416fd367b7ab 100644 (file)
@@ -3,7 +3,7 @@
     yang-version 1;
 
     namespace
-      "http://netconfcentral.org/ns/toaster";
+      "http://netconfcentral.org/ns/toaster2";
 
     prefix toast;
 
index a0c23aecb4627c4aec4ab1a828d6d97fe695fc60..af7a32924b783ebfafa1f43a2726b9a635387270 100644 (file)
@@ -7,10 +7,11 @@
  */
 package org.opendaylight.controller.md.sal.test.model.util;
 
-import java.util.Arrays;
-
+import com.google.common.collect.ImmutableList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyUsesAugmentBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUses;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesKey;
@@ -25,7 +26,7 @@ import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-import com.google.common.collect.ImmutableList;
+import java.util.Arrays;
 
 public class ListsBindingUtils {
 
@@ -79,4 +80,9 @@ public class ListsBindingUtils {
         return new TreeComplexUsesAugmentBuilder().setListViaUses(listViaUses.build()).build();
     }
 
+    public static TreeLeafOnlyUsesAugment leafOnlyUsesAugment(String leafFromGroupingValue) {
+
+        return new TreeLeafOnlyUsesAugmentBuilder().setLeafFromGrouping(leafFromGroupingValue).build();
+    }
+
 }
index 2c8571ca64369c80748ee5d1b157a39017c1db86..e01a0d5dcba4956f790d2274462455911970742c 100644 (file)
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-flow-base</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.model</groupId>
-      <artifactId>model-flow-management</artifactId>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-flow-service</artifactId>
index eddad8b4c7c1df593c45a5f829c3c56828339e18..fff8d611b7975b34dce89ce603f164603ea2b582 100644 (file)
@@ -65,9 +65,11 @@ public class ConfigPusher {
         LinkedHashMap<ConfigSnapshotHolder, EditAndCommitResponse> result = new LinkedHashMap<>();
         // start pushing snapshots:
         for (ConfigSnapshotHolder configSnapshotHolder : configs) {
-            EditAndCommitResponse editAndCommitResponseWithRetries = pushConfigWithConflictingVersionRetries(configSnapshotHolder);
-            logger.debug("Config snapshot pushed successfully: {}, result: {}", configSnapshotHolder, result);
-            result.put(configSnapshotHolder, editAndCommitResponseWithRetries);
+            if(configSnapshotHolder != null) {
+                EditAndCommitResponse editAndCommitResponseWithRetries = pushConfigWithConflictingVersionRetries(configSnapshotHolder);
+                logger.debug("Config snapshot pushed successfully: {}, result: {}", configSnapshotHolder, result);
+                result.put(configSnapshotHolder, editAndCommitResponseWithRetries);
+            }
         }
         logger.debug("All configuration snapshots have been pushed successfully.");
         return result;
index cd7a1aacf2dbfbf47dc0e6a00003abde2f09b3d7..55a87150008ab51f0a96cc163ed218e629e31201 100644 (file)
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-data-impl</artifactId>
-      <!--        <version>0.6.2-SNAPSHOT</version>-->
     </dependency>
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
-      <artifactId>yang-data-json</artifactId>
-      <version>0.6.2-SNAPSHOT</version>
+      <artifactId>yang-data-composite-node</artifactId>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
index c101db9ef8406342c502fe2e276e203791970662..ef29a76fff342c5c5e0fc87d89b1a56639aa04f6 100644 (file)
@@ -18,7 +18,7 @@ import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
 import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
-import org.opendaylight.yangtools.yang.data.json.schema.cnsn.parser.CnSnToNormalizedNodeParserFactory;
+import org.opendaylight.yangtools.yang.data.composite.node.schema.cnsn.parser.CnSnToNormalizedNodeParserFactory;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
index 0e9589d2d21b0bde118440a1a0c683e1bedf3fd5..272b686fc034ff33fbbe247b706ec536040660cb 100644 (file)
 
   <build>
     <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <configuration>
-          <forkCount>1</forkCount>
-          <reuseForks>false</reuseForks>
-          <perCoreThreadCount>false</perCoreThreadCount>
-        </configuration>
-        <executions>
-          <execution>
-            <id>default-test</id>
-            <configuration>
-              <skip>true</skip>
-            </configuration>
-          </execution>
-          <execution>
-            <id>integration-tests</id>
-            <goals>
-              <goal>test</goal>
-            </goals>
-            <phase>integration-test</phase>
-            <configuration>
-              <skip>false</skip>
-              <argLine>-Dlogback.configurationFile=${maven.test.dest}/logback.xml</argLine>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
       <plugin>
         <groupId>org.ops4j.pax.exam</groupId>
         <artifactId>maven-paxexam-plugin</artifactId>