Merge "Be sure to shutdown instance when destroyed"
authorTony Tkacik <ttkacik@cisco.com>
Thu, 4 Sep 2014 12:49:58 +0000 (12:49 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 4 Sep 2014 12:49:58 +0000 (12:49 +0000)
369 files changed:
features/adsal-compatibility/pom.xml [new file with mode: 0644]
features/adsal-compatibility/src/main/resources/features.xml [new file with mode: 0644]
features/adsal/pom.xml
features/adsal/src/main/resources/features.xml
features/base/pom.xml
features/base/src/main/resources/features.xml
features/config-netty/src/main/resources/features.xml
features/config-persister/src/main/resources/features.xml
features/config/src/main/resources/features.xml
features/flow/src/main/resources/features.xml
features/mdsal/pom.xml
features/mdsal/src/main/resources/features.xml
features/netconf/pom.xml
features/netconf/src/main/resources/features.xml
features/nsf/pom.xml
features/nsf/src/main/resources/features.xml
features/pom.xml
features/protocol-framework/src/main/resources/features.xml
opendaylight/archetypes/opendaylight-configfile-archetype/pom.xml [new file with mode: 0644]
opendaylight/archetypes/opendaylight-configfile-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml [new file with mode: 0644]
opendaylight/archetypes/opendaylight-configfile-archetype/src/main/resources/archetype-resources/pom.xml [new file with mode: 0644]
opendaylight/archetypes/opendaylight-configfile-archetype/src/main/resources/archetype-resources/src/main/resources/80-__repoName__.xml [new file with mode: 0644]
opendaylight/archetypes/opendaylight-configfile-archetype/src/test/resources/projects/basic/archetype.properties [new file with mode: 0644]
opendaylight/archetypes/opendaylight-configfile-archetype/src/test/resources/projects/basic/goal.txt [new file with mode: 0644]
opendaylight/archetypes/opendaylight-karaf-distro-archetype/pom.xml [new file with mode: 0644]
opendaylight/archetypes/opendaylight-karaf-distro-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml [new file with mode: 0644]
opendaylight/archetypes/opendaylight-karaf-distro-archetype/src/main/resources/archetype-resources/pom.xml [new file with mode: 0644]
opendaylight/archetypes/opendaylight-karaf-distro-archetype/src/test/resources/projects/basic/archetype.properties [new file with mode: 0644]
opendaylight/archetypes/opendaylight-karaf-distro-archetype/src/test/resources/projects/basic/goal.txt [new file with mode: 0644]
opendaylight/archetypes/opendaylight-karaf-features/pom.xml [new file with mode: 0644]
opendaylight/archetypes/opendaylight-karaf-features/src/main/resources/META-INF/maven/archetype-metadata.xml [new file with mode: 0644]
opendaylight/archetypes/opendaylight-karaf-features/src/main/resources/archetype-resources/pom.xml [new file with mode: 0644]
opendaylight/archetypes/opendaylight-karaf-features/src/main/resources/archetype-resources/src/main/resources/features.xml [new file with mode: 0644]
opendaylight/archetypes/opendaylight-karaf-features/src/test/resources/projects/basic/archetype.properties [new file with mode: 0644]
opendaylight/archetypes/opendaylight-karaf-features/src/test/resources/projects/basic/goal.txt [new file with mode: 0644]
opendaylight/archetypes/pom.xml
opendaylight/commons/opendaylight/pom.xml
opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectPromise.java
opendaylight/config/config-api/pom.xml
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/JmxAttribute.java
opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/IdentityAttributeRefTest.java [new file with mode: 0644]
opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/JmxAttributeTest.java [new file with mode: 0644]
opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/JmxAttributeValidationExceptionTest.java
opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/ModuleIdentifierTest.java [new file with mode: 0644]
opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/ValidationExceptionTest.java
opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/jmx/CommitStatusTest.java [new file with mode: 0644]
opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/jmx/ConfigRegistryConstantsTest.java [new file with mode: 0644]
opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtilTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/RefreshingSCPModuleInfoRegistryTest.java [new file with mode: 0644]
opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationService.java
opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ContainerConfigurationService.java
opendaylight/distribution/opendaylight-karaf-resources/src/main/resources/configuration/tomcat-server.xml
opendaylight/distribution/opendaylight-karaf-resources/src/main/resources/etc/custom.properties
opendaylight/distribution/opendaylight-karaf/pom.xml
opendaylight/distribution/opendaylight/pom.xml
opendaylight/karaf-tomcat-security/pom.xml [new file with mode: 0644]
opendaylight/karaf-tomcat-security/src/main/java/org/opendaylight/controller/karafsecurity/ControllerCustomRealm.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractChangeListener.java [deleted file]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FRMActivator.java
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FlowCookieProducer.java [deleted file]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FlowNodeReconciliation.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/ForwardingRulesCommiter.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/ForwardingRulesManager.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowChangeListener.java [deleted file]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowProvider.java [deleted file]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupChangeListener.java [deleted file]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupProvider.java [deleted file]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/AbstractListeningCommiter.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/FlowForwarder.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/FlowNodeReconciliationImpl.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/ForwardingRulesManagerImpl.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/GroupForwarder.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/MeterForwarder.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterChangeListener.java [deleted file]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterProvider.java [deleted file]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/reconil/FlowNodeReconcilListener.java [deleted file]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/reconil/FlowNodeReconcilProvider.java [deleted file]
opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/FlowListenerTest.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/GroupListenerTest.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/MeterListenerTest.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/NodeListenerTest.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/AbstractDataBrokerTest.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/AbstractSchemaAwareTest.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/DataBrokerTestCustomizer.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/FRMTest.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/MockSchemaService.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/RpcProviderRegistryMock.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalFlowServiceMock.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalGroupServiceMock.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalMeterServiceMock.java [new file with mode: 0644]
opendaylight/md-sal/md-sal-config/src/main/resources/initial/01-md-sal.xml
opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-node-inventory.yang
opendaylight/md-sal/pom.xml
opendaylight/md-sal/sal-akka-raft/pom.xml
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/KeyValue.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/client/messages/FindLeader.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/client/messages/FindLeaderReply.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntries.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/protobuff/client/messages/Payload.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/protobuff/messages/VotingMessages.java [deleted file]
opendaylight/md-sal/sal-akka-raft/src/main/resources/VotingMessages.proto [deleted file]
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/AbstractActorTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/MockRaftActorContext.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-akka-raft/src/test/resources/application.conf
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/BindingTransactionChain.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataBroker.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/BindingToNormalizedNodeCodec.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DomToBindingRpcForwarder.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/ForwardedBackwardsCompatibleDataBrokerTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/DataBrokerTestCustomizer.java
opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java
opendaylight/md-sal/sal-clustering-commons/pom.xml
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/NormalizedNodeToNodeCodec.java
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodeGetter.java
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/PathUtils.java
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/QNameFactory.java
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/NormalizedNodeDeSerializationContext.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/NormalizedNodeSerializationContext.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/NormalizedNodeSerializer.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/NormalizedNodeType.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/PathArgumentSerializer.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/PathArgumentType.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/ValueSerializer.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/ValueType.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/util/InstanceIdentifierUtils.java
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/common/actor/MeteredBoundedMailbox.java
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/cluster/example/KeyValueMessages.java [moved from opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/protobuff/messages/KeyValueMessages.java with 78% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/cluster/raft/AppendEntriesMessages.java [moved from opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/protobuff/messages/AppendEntriesMessages.java with 79% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/cluster/raft/test/MockPayloadMessages.java [moved from opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/protobuff/messages/MockPayloadMessages.java with 66% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/common/NormalizedNodeMessages.java
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/persistent/PersistentMessages.java
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/shard/CompositeModificationPayload.java
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessages.java
opendaylight/md-sal/sal-clustering-commons/src/main/resources/AppendEntriesMessages.proto [moved from opendaylight/md-sal/sal-akka-raft/src/main/resources/AppendEntriesMessages.proto with 88% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/Common.proto
opendaylight/md-sal/sal-clustering-commons/src/main/resources/KeyValueMessages.proto [moved from opendaylight/md-sal/sal-akka-raft/src/main/resources/KeyValueMessages.proto with 79% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/MockPayload.proto [moved from opendaylight/md-sal/sal-akka-raft/src/test/resources/MockPayload.proto with 54% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/NormalizedNodeToNodeCodecTest.java
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/PathUtilsTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/QNameFactoryTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/NormalizedNodeSerializerTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/PathArgumentSerializerTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/ValueSerializerTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/TestModel.java
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/common/actor/MeteredBoundedMailboxTest.java
opendaylight/md-sal/sal-clustering-commons/src/test/resources/odl-datastore-test.yang
opendaylight/md-sal/sal-clustering-config/pom.xml
opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/akka.conf
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionChain.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionChainFactory.java
opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/AbstractMXBean.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/QueuedNotificationManagerMXBean.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/QueuedNotificationManagerMXBeanImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/QueuedNotificationManagerStats.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/ThreadExecutorStats.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/ThreadExecutorStatsMXBean.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/ThreadExecutorStatsMXBeanImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/pom.xml
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/CompositeModificationPayload.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/DataChangeListenerRegistration.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DatastoreContext.java [new file with mode: 0644]
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/DistributedDataStoreFactory.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreProperties.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadTransaction.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadWriteTransaction.java
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
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohort.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohortProxy.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionChainProxy.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/AbstractBaseMBean.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardMBeanFactory.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/FindPrimary.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PrimaryFound.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PrimaryNotFound.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/ActorContext.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/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/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/CompositeModificationPayloadTest.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/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/ShardTransactionFailureTest.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/ThreePhaseCommitCohortFailureTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohortProxyTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/TransactionChainProxyTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/TransactionProxyTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStatsTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/resources/application.conf
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataReadTransaction.java
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/DOMDataBrokerImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMDataCommitCoordinatorImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/TranslatingListenerInvoker.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/jmx/CommitStatsMXBean.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/jmx/CommitStatsMXBeanImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/jmx/CommitStatsMXBeanImplTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/DOMStoreReadTransaction.java
opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/DOMStoreTransactionChain.java
opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/statistics/DOMStoreStatsTracker.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-xsql-config/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-dom-xsql-config/src/main/resources/04-xsql.xml [new file with mode: 0644]
opendaylight/md-sal/sal-dom-xsql/src/main/java/org/opendaylight/controller/md/sal/dom/xsql/XSQLAdapter.java
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryConfigDataStoreProviderModule.java
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryOperationalDataStoreProviderModule.java
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ChangeListenerNotifyTask.java [deleted file]
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStoreConfigProperties.java
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStoreFactory.java
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ResolveDataChangeEventsTask.java
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ResolveDataChangeState.java
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedReadTransaction.java
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/jmx/InMemoryDataStoreStats.java [new file with mode: 0644]
opendaylight/md-sal/sal-inmemory-datastore/src/main/yang/opendaylight-inmemory-datastore-provider.yang
opendaylight/md-sal/sal-karaf-xsql/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-karaf-xsql/src/main/java/org/opendaylight/controller/xsql/xsql.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfStateSchemas.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/NetconfDeviceSalFacade.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/schema/NetconfRemoteSchemaYangSourceProvider.java
opendaylight/md-sal/sal-remoterpc-connector/pom.xml
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/RpcRegistry.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/BucketStore.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/gossip/Gossiper.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/ActorUtil.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/RemoteRpcProviderTest.java
opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/RouteRpcListenerTest.java
opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/RpcListenerTest.java
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/utils/LatestEntryRoutingLogicTest.java
opendaylight/md-sal/sal-remoterpc-connector/src/test/resources/application.conf
opendaylight/md-sal/sal-rest-connector/pom.xml
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfConstants.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/AbstractIdentifierAwareJaxRsProvider.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonNormalizedNodeBodyReader.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/NormalizedNodeJsonBodyWriter.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/NormalizedNodeXmlBodyWriter.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfApplication.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToJsonProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlNormalizedNodeBodyReader.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlToCompositeNodeReader.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlToNormalizedNodeReaderWithSchema.java [deleted file]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java
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/InstanceIdentifierContext.java [moved from opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/InstanceIdWithSchemaNode.java with 71% similarity]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/NormalizedDataPrunner.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/NormalizedNodeContext.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java
opendaylight/md-sal/sal-rest-connector/src/main/resources/WEB-INF/web.xml
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestGetAugmentedElementWhenEqualNamesTest.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/RestconfDocumentedExceptionMapperTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/URITest.java
opendaylight/md-sal/sal-rest-docgen/src/main/resources/WEB-INF/web.xml
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/index.html
opendaylight/md-sal/samples/toaster-provider/pom.xml
opendaylight/md-sal/samples/toaster-provider/src/test/java/org/opendaylight/controller/sample/toaster/provider/OpenDaylightToasterTest.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/AbstractStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowComparator.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowStatsEntry.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowTableStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/GroupDescStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/GroupStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MeterConfigStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MeterStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeConnectorStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/QueueStatsTracker.java
opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiterTest.java
opendaylight/md-sal/topology-manager/src/main/java/org/opendaylight/md/controller/topology/manager/FlowCapableTopologyExporter.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AttributeConfigElement.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/CompositeAttributeReadingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectXmlReader.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectMapper.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java
opendaylight/netconf/netconf-auth/pom.xml [new file with mode: 0644]
opendaylight/netconf/netconf-auth/src/main/java/org/opendaylight/controller/netconf/auth/AuthConstants.java [new file with mode: 0644]
opendaylight/netconf/netconf-auth/src/main/java/org/opendaylight/controller/netconf/auth/AuthProvider.java [moved from opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProvider.java with 56% similarity]
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/SshClientChannelInitializer.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/HardcodedYangStoreService.java [deleted file]
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITMonitoringTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITSecureTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java [deleted file]
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/SSLUtil.java
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/Get.java
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringActivator.java
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringServiceTracker.java
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/xml/JaxBSerializer.java
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/xml/model/NetconfState.java
opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/GetTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/xml/JaxBSerializerTest.java
opendaylight/netconf/netconf-netty-util/pom.xml
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfHelloMessageToXMLEncoder.java
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfXMLToMessageDecoder.java
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/authentication/AuthenticationHandler.java
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/authentication/LoginPassword.java
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/AsyncSshHandler.java [new file with mode: 0644]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/Invoker.java [deleted file]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshClient.java [deleted file]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshClientAdapter.java [deleted file]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshHandler.java [deleted file]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshSession.java [deleted file]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/virtualsocket/ChannelInputStream.java [deleted file]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/virtualsocket/ChannelOutputStream.java [deleted file]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/virtualsocket/VirtualSocket.java [deleted file]
opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/ChunkedFramingMechanismEncoderTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/EOMFramingMechanismEncoderTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/FramingMechanismHandlerFactoryTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfChunkAggregatorTest.java
opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfHelloMessageToXMLEncoderTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfXMLToHelloMessageDecoderTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfXMLToMessageDecoderTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/authentication/LoginPasswordTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-ssh/pom.xml
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/osgi/NetconfSSHActivator.java
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/Handshaker.java
opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/StubUserManager.java [deleted file]
opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/netty/SSHTest.java
opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/ssh/authentication/SSHServerTest.java
opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/AcceptingAuthProvider.java
opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java
opendaylight/netconf/netconf-usermanager/pom.xml [new file with mode: 0644]
opendaylight/netconf/netconf-usermanager/src/main/java/org/opendaylight/controller/netconf/auth/usermanager/AuthProviderActivator.java [new file with mode: 0644]
opendaylight/netconf/netconf-usermanager/src/main/java/org/opendaylight/controller/netconf/auth/usermanager/AuthProviderImpl.java [moved from opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProviderImpl.java with 65% similarity]
opendaylight/netconf/pom.xml
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronLoadBalancerPoolMemberAware.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronRouter_Interface.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/Neutron_IPs.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/Activator.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/ActionType.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/GlobalConstants.java
opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/action/ActionTest.java
opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/DataPacketService.java
opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java
opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/ProtocolService.java [new file with mode: 0644]
opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/ReadService.java
opendaylight/sal/implementation/src/test/java/org/opendaylight/controller/sal/implementation/ProtocolServiceTest.java [new file with mode: 0644]
opendaylight/samples/northbound/loadbalancer/pom.xml
opendaylight/web/flows/src/main/resources/js/page.js
pom.xml

diff --git a/features/adsal-compatibility/pom.xml b/features/adsal-compatibility/pom.xml
new file mode 100644 (file)
index 0000000..44b9b09
--- /dev/null
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+ Necessary TODO: Put your copyright here.\r
+\r
+ This program and the accompanying materials are made available under the\r
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ and is available at http://www.eclipse.org/legal/epl-v10.html\r
+--><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">\r
+   <modelVersion>4.0.0</modelVersion>\r
+   <parent>\r
+     <groupId>org.opendaylight.controller</groupId>\r
+     <artifactId>commons.opendaylight</artifactId>\r
+     <version>1.4.2-SNAPSHOT</version>\r
+     <relativePath>../../opendaylight/commons/opendaylight</relativePath>\r
+   </parent>\r
+   <artifactId>features-adsal-compatibility</artifactId>\r
+   <packaging>jar</packaging>\r
+   <properties>\r
+      <features.file>features.xml</features.file>\r
+      <feature.test.version>0.6.2-SNAPSHOT</feature.test.version>\r
+   </properties>\r
+   <dependencies>\r
+    <!--\r
+      Necessary TODO: Put dependencies on any feature repos\r
+      you use in your features.xml file.\r
+\r
+      Note: they will need to be <type>xml</xml>\r
+      and <classifier>features</classifier>.\r
+      One other thing to watch for is to make sure they are\r
+      <scope>compile</compile>, which they should be by default,\r
+      but be cautious lest they be at a different scope in a parent pom.\r
+\r
+      Examples:\r
+        <dependency>\r
+          <groupId>org.opendaylight.yangtools</groupId>\r
+          <artifactId>features-yangtools</artifactId>\r
+          <version>0.6.2-SNAPSHOT</version>\r
+          <classifier>features</classifier>\r
+          <type>xml</type>\r
+        </dependency>\r
+        <dependency>\r
+          <groupId>org.opendaylight.controller</groupId>\r
+          <artifactId>features-mdsal</artifactId>\r
+          <version>1.1-SNAPSHOT</version>\r
+          <classifier>features</classifier>\r
+          <type>xml</type>\r
+        </dependency>\r
+        <dependency>\r
+          <groupId>org.opendaylight.openflowplugin</groupId>\r
+          <artifactId>features-openflowplugin</artifactId>\r
+          <version>0.0.3-SNAPSHOT</version>\r
+          <classifier>features</classifier>\r
+          <type>xml</type>\r
+        </dependency>\r
+    -->\r
+      <dependency>\r
+        <groupId>org.opendaylight.controller</groupId>\r
+        <artifactId>features-mdsal</artifactId>\r
+        <version>${mdsal.version}</version>\r
+        <classifier>features</classifier>\r
+        <type>xml</type>\r
+      </dependency>\r
+      <dependency>\r
+        <groupId>org.opendaylight.controller</groupId>\r
+        <artifactId>features-flow</artifactId>\r
+        <version>${mdsal.version}</version>\r
+        <classifier>features</classifier>\r
+        <type>xml</type>\r
+      </dependency>\r
+      <dependency>\r
+        <groupId>org.opendaylight.controller</groupId>\r
+        <artifactId>features-adsal</artifactId>\r
+        <version>${sal.version}</version>\r
+        <classifier>features</classifier>\r
+        <type>xml</type>\r
+      </dependency>\r
+\r
+    <!--\r
+      Necessary TODO: Put dependencies for bundles directly referenced\r
+      in your features.xml file.  For every <bundle> reference in your\r
+      features.xml file, you need a corresponding dependency here.\r
+\r
+      Examples:\r
+      <dependency>\r
+        <groupId>org.opendaylight.controller</groupId>\r
+        <artifactId>controller-provider</artifactId>\r
+        <version>${project.version}</version>\r
+      </dependency>\r
+      <dependency>\r
+        <groupId>org.opendaylight.controller</groupId>\r
+        <artifactId>controller-model</artifactId>\r
+        <version>${project.version}</version>\r
+      </dependency>\r
+    -->\r
+      <dependency>\r
+        <groupId>org.opendaylight.controller</groupId>\r
+        <artifactId>sal-compatibility</artifactId>\r
+        <version>${mdsal.version}</version>\r
+      </dependency>\r
+\r
+    <!--\r
+      Necessary TODO: Put dependencies for configfiles directly referenced\r
+      in your features.xml file.  For every <configfile> reference in your\r
+      features.xml file, you need a corresponding dependency here.\r
+\r
+      Example (presuming here version is coming from the parent pom):\r
+      <dependency>\r
+        <groupId>org.opendaylight.controller</groupId>\r
+        <artifactId>controller-config</artifactId>\r
+        <version>${project.version}</version>\r
+        <type>xml</type>\r
+        <classifier>config</classifier>\r
+      </dependency>\r
+    -->\r
+\r
+    <!--\r
+      Optional TODO: Remove TODO comments.\r
+    -->\r
+    <!-- test to validate features.xml -->\r
+    <dependency>\r
+      <groupId>org.opendaylight.yangtools</groupId>\r
+      <artifactId>features-test</artifactId>\r
+      <version>${feature.test.version}</version>\r
+      <scope>test</scope>\r
+    </dependency>\r
+    <!-- dependency for opendaylight-karaf-empty for use by testing -->\r
+    <dependency>\r
+      <groupId>org.opendaylight.controller</groupId>\r
+      <artifactId>opendaylight-karaf-empty</artifactId>\r
+      <version>${commons.opendaylight.version}</version>\r
+      <type>zip</type>\r
+    </dependency>\r
+    <!-- Uncomment this if you get an error : java.lang.NoSuchMethodError: org.slf4j.helpers.MessageFormatter.format(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Lorg/slf4j/helpers/FormattingTuple;\r
+    <dependency>\r
+      <groupId>org.slf4j</groupId>\r
+      <artifactId>slf4j-simple</artifactId>\r
+      <version>1.7.2</version>\r
+    </dependency>\r
+    -->\r
+\r
+   </dependencies>\r
+   <build>\r
+      <resources>\r
+         <resource>\r
+            <directory>src/main/resources</directory>\r
+            <filtering>true</filtering>\r
+         </resource>\r
+      </resources>\r
+      <plugins>\r
+         <plugin>\r
+            <groupId>org.apache.maven.plugins</groupId>\r
+            <artifactId>maven-resources-plugin</artifactId>\r
+            <executions>\r
+               <execution>\r
+                  <id>filter</id>\r
+                  <phase>generate-resources</phase>\r
+                  <goals>\r
+                     <goal>resources</goal>\r
+                  </goals>\r
+               </execution>\r
+            </executions>\r
+         </plugin>\r
+         <plugin>\r
+            <groupId>org.codehaus.mojo</groupId>\r
+            <artifactId>build-helper-maven-plugin</artifactId>\r
+            <executions>\r
+               <execution>\r
+                  <id>attach-artifacts</id>\r
+                  <phase>package</phase>\r
+                  <goals>\r
+                     <goal>attach-artifact</goal>\r
+                  </goals>\r
+                  <configuration>\r
+                     <artifacts>\r
+                        <artifact>\r
+                           <file>${project.build.directory}/classes/${features.file}</file>\r
+                           <type>xml</type>\r
+                           <classifier>features</classifier>\r
+                        </artifact>\r
+                     </artifacts>\r
+                  </configuration>\r
+               </execution>\r
+            </executions>\r
+         </plugin>\r
+         <plugin>\r
+            <groupId>org.apache.maven.plugins</groupId>\r
+            <artifactId>maven-surefire-plugin</artifactId>\r
+            <version>${surefire.version}</version>\r
+            <configuration>\r
+              <systemPropertyVariables>\r
+                <karaf.distro.groupId>org.opendaylight.controller</karaf.distro.groupId>\r
+                <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId>\r
+                <karaf.distro.version>${commons.opendaylight.version}</karaf.distro.version>\r
+              </systemPropertyVariables>\r
+              <dependenciesToScan>\r
+               <dependency>org.opendaylight.yangtools:features-test</dependency>\r
+              </dependenciesToScan>\r
+            </configuration>\r
+          </plugin>\r
+      </plugins>\r
+   </build>\r
+   <scm>\r
+      <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>\r
+      <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>\r
+      <tag>HEAD</tag>\r
+      <url>https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=summary</url>\r
+   </scm>\r
+</project>\r
diff --git a/features/adsal-compatibility/src/main/resources/features.xml b/features/adsal-compatibility/src/main/resources/features.xml
new file mode 100644 (file)
index 0000000..de939f2
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Necessary TODO: Put your copyright statement here
+
+ 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
+-->
+<features name="odl-adsal-compatibility-${sal.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+    <repository>mvn:org.opendaylight.controller/features-mdsal/${mdsal.version}/xml/features</repository>
+    <repository>mvn:org.opendaylight.controller/features-adsal/${sal.version}/xml/features</repository>
+    <repository>mvn:org.opendaylight.controller/features-flow/${mdsal.version}/xml/features</repository>
+    <feature name='odl-adsal-compatibility-all' version='${project.version}' description='OpenDaylight :: controller :: All'>
+        <feature version='${sal.version}'>odl-adsal-compatibility</feature>
+    </feature>
+    <feature name='odl-adsal-compatibility' description="OpenDaylight :: AD-SAL :: Compatibility" version="${sal.version}">
+      <feature version="${mdsal.version}">odl-mdsal-broker</feature>
+      <feature version="${mdsal.version}">odl-flow-model</feature>
+      <feature version="${sal.version}">odl-adsal-all</feature>
+      <bundle>mvn:org.opendaylight.controller/sal-compatibility/${mdsal.version}</bundle>
+   </feature>
+</features>
index 0ccb17a664ef203a88aa01e263811d998f09222f..0ce976e2ef3beed38a8019cfc63074d04989a674 100644 (file)
@@ -9,7 +9,7 @@
   </parent>
   <artifactId>features-adsal</artifactId>
   <version>${sal.version}</version>
-  <packaging>pom</packaging>
+  <packaging>jar</packaging>
   <name>Features :: AD-SAL Features</name>
   <description>AD-SAL Features POM</description>
   <properties>
   <dependencies>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
-      <artifactId>base-features</artifactId>
-      <version>${project.parent.version}</version>
+      <artifactId>features-base</artifactId>
       <classifier>features</classifier>
       <type>xml</type>
-      <scope>runtime</scope>
+    </dependency>
+    <!-- test to validate features.xml -->
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>features-test</artifactId>
+    </dependency>
+    <!-- dependency for opendaylight-karaf-empty for use by testing -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>opendaylight-karaf-empty</artifactId>
+      <version>1.4.2-SNAPSHOT</version>
+      <type>zip</type>
+    </dependency>
+    <!-- Bundle dependencies -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>dummy-console</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal.connection</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal.connection.implementation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal.implementation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal.networkconfiguration</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal.networkconfiguration.implementation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>clustering.services</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>clustering.services-implementation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>clustering.stub</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>configuration</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>configuration.implementation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>logging.bridge</artifactId>
     </dependency>
   </dependencies>
   <build>
           </execution>
         </executions>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <systemPropertyVariables>
+            <karaf.distro.groupId>org.opendaylight.controller</karaf.distro.groupId>
+            <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId>
+            <karaf.distro.version>${commons.opendaylight.version}</karaf.distro.version>
+          </systemPropertyVariables>
+          <dependenciesToScan>
+           <dependency>org.opendaylight.yangtools:features-test</dependency>
+          </dependenciesToScan>
+        </configuration>
+      </plugin>
     </plugins>
   </build>
 </project>
index f955315164ced774198c742c5c8f55171abe58b3..e12ca8e5e990acc860dc9e56e4eed57ed9c2a0e0 100644 (file)
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <features name="adsal-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+   <repository>mvn:org.opendaylight.controller/features-base/${commons.opendaylight.version}/xml/features</repository>
    <feature name="odl-adsal-all" description="OpenDaylight AD-SAL All Features" version="${sal.version}">
       <feature version="${sal.version}">odl-adsal-core</feature>
       <feature version="${sal.networkconfiguration.version}">odl-adsal-networkconfiguration</feature>
       <feature version="${configuration.version}">odl-adsal-configuration</feature>
    </feature>
    <feature name="odl-adsal-core" description="OpenDaylight :: AD-SAL :: Core" version="${sal.version}">
-      <feature>base-felix-dm</feature>
-      <feature>base-dummy-console</feature>
+      <feature>odl-base-felix-dm</feature>
+      <feature>odl-base-dummy-console</feature>
       <feature version="${project.version}">odl-adsal-thirdparty</feature>
-      <bundle start="true" start-level="35">mvn:org.apache.commons/commons-lang3/${commons.lang3.version}</bundle>
+      <bundle start="true">mvn:org.apache.commons/commons-lang3/${commons.lang3.version}</bundle>
   <!--    <bundle>mvn:org.osgi/org.osgi.compendium/${osgi.compendium.version}</bundle> -->
       <bundle>mvn:org.opendaylight.controller/sal/${sal.version}</bundle>
       <bundle>mvn:org.opendaylight.controller/sal.implementation/${sal.implementation.version}</bundle>
    </feature>
    <feature name="odl-adsal-networkconfiguration" description="OpenDaylight :: AD-SAL :: Network Configuration" version="${sal.networkconfiguration.version}">
+      <feature>odl-adsal-core</feature>
       <bundle>mvn:org.opendaylight.controller/sal.networkconfiguration/${sal.networkconfiguration.version}</bundle>
       <bundle>mvn:org.opendaylight.controller/sal.networkconfiguration.implementation/${sal.networkconfiguration.version}</bundle>
    </feature>
@@ -28,8 +30,8 @@
    </feature>
    <feature name="odl-adsal-clustering" description="OpenDaylight :: AD-SAL :: Clustering" version="${clustering.services.version}">
       <feature>transaction</feature>
-      <feature>base-felix-dm</feature>
-      <feature>base-eclipselink-persistence</feature>
+      <feature>odl-base-felix-dm</feature>
+      <feature>odl-base-eclipselink-persistence</feature>
       <feature version="${sal.version}">odl-adsal-core</feature>
       <bundle>mvn:org.opendaylight.controller/clustering.services/${clustering.services.version}</bundle>
       <bundle>mvn:org.opendaylight.controller/clustering.services-implementation/${clustering.services_implementation.version}</bundle>
index d925f51b948cfe444a77a5875546e6986ec5ca26..ed8e2a8c20d2765ade8cbe42856f8b94460eeb40 100644 (file)
     <version>1.4.2-SNAPSHOT</version>
     <relativePath>../../opendaylight/commons/opendaylight</relativePath>
   </parent>
-  <artifactId>base-features</artifactId>
-  <packaging>pom</packaging>
+  <artifactId>features-base</artifactId>
+  <packaging>jar</packaging>
   <name>${project.artifactId}</name>
   <description>Base Features POM</description>
   <properties>
     <features.file>features.xml</features.file>
   </properties>
+  <dependencies>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>dummy-console</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>karaf-tomcat-security</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.thirdparty</groupId>
+      <artifactId>ganymed</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-annotations</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.datatype</groupId>
+      <artifactId>jackson-datatype-json-org</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.jaxrs</groupId>
+      <artifactId>jackson-jaxrs-base</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.jaxrs</groupId>
+      <artifactId>jackson-jaxrs-json-provider</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.module</groupId>
+      <artifactId>jackson-module-jaxb-annotations</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.google.code.gson</groupId>
+      <artifactId>gson</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.sun.jersey</groupId>
+      <artifactId>jersey-client</artifactId>
+    </dependency>
+    <!-- Jersey for JAXRS -->
+    <dependency>
+      <groupId>com.sun.jersey</groupId>
+      <artifactId>jersey-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.sun.jersey</groupId>
+      <artifactId>jersey-server</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-fileupload</groupId>
+      <artifactId>commons-fileupload</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-net</groupId>
+      <artifactId>commons-net</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>eclipselink</groupId>
+      <artifactId>javax.persistence</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>eclipselink</groupId>
+      <artifactId>javax.resource</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>equinoxSDK381</groupId>
+      <artifactId>javax.servlet</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>equinoxSDK381</groupId>
+      <artifactId>javax.servlet.jsp</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>equinoxSDK381</groupId>
+      <artifactId>org.apache.felix.gogo.command</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>equinoxSDK381</groupId>
+      <artifactId>org.apache.felix.gogo.runtime</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>equinoxSDK381</groupId>
+      <artifactId>org.apache.felix.gogo.shell</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>equinoxSDK381</groupId>
+      <artifactId>org.eclipse.equinox.cm</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>equinoxSDK381</groupId>
+      <artifactId>org.eclipse.equinox.console</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>equinoxSDK381</groupId>
+      <artifactId>org.eclipse.equinox.ds</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>equinoxSDK381</groupId>
+      <artifactId>org.eclipse.equinox.launcher</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>equinoxSDK381</groupId>
+      <artifactId>org.eclipse.equinox.util</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>equinoxSDK381</groupId>
+      <artifactId>org.eclipse.osgi</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>equinoxSDK381</groupId>
+      <artifactId>org.eclipse.osgi.services</artifactId>
+    </dependency>
+    <!-- Gemini Web -->
+    <dependency>
+      <groupId>geminiweb</groupId>
+      <artifactId>org.eclipse.gemini.web.core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>geminiweb</groupId>
+      <artifactId>org.eclipse.gemini.web.extender</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>geminiweb</groupId>
+      <artifactId>org.eclipse.gemini.web.tomcat</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>geminiweb</groupId>
+      <artifactId>org.eclipse.virgo.kernel.equinox.extensions</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>geminiweb</groupId>
+      <artifactId>org.eclipse.virgo.util.common</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>geminiweb</groupId>
+      <artifactId>org.eclipse.virgo.util.io</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>geminiweb</groupId>
+      <artifactId>org.eclipse.virgo.util.math</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>geminiweb</groupId>
+      <artifactId>org.eclipse.virgo.util.osgi</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>geminiweb</groupId>
+      <artifactId>org.eclipse.virgo.util.osgi.manifest</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>geminiweb</groupId>
+      <artifactId>org.eclipse.virgo.util.parser.manifest</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-buffer</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-codec</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-codec-http</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-common</artifactId>
+    </dependency>
+
+    <!--Netty-->
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-handler</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-transport</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>javax.activation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>javax.annotation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>javax.ejb</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>javax.el</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>javax.mail.glassfish</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>javax.servlet.jsp.jstl</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>javax.servlet.jsp.jstl.impl</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>javax.xml.rpc</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>org.apache.catalina</artifactId>
+      <version>7.0.53.v201406061610</version>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>org.apache.catalina.ha</artifactId>
+      <version>7.0.53.v201406070630</version>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>org.apache.catalina.tribes</artifactId>
+      <version>7.0.53.v201406070630</version>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>org.apache.coyote</artifactId>
+      <version>7.0.53.v201406070630</version>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>org.apache.el</artifactId>
+      <version>7.0.53.v201406060720</version>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>org.apache.jasper</artifactId>
+      <version>7.0.53.v201406070630</version>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>org.apache.juli.extras</artifactId>
+      <version>7.0.53.v201406060720</version>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>org.apache.tomcat.api</artifactId>
+      <version>7.0.53.v201406060720</version>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>org.apache.tomcat.util</artifactId>
+      <version>7.0.53.v201406070630</version>
+    </dependency>
+    <dependency>
+      <groupId>org.aopalliance</groupId>
+      <artifactId>com.springsource.org.aopalliance</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.dependencymanager</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.dependencymanager.shell</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.fileinstall</artifactId>
+    </dependency>
+    <!-- felix webconsole -->
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.webconsole</artifactId>
+      <classifier>all</classifier>
+    </dependency>
+
+    <dependency>
+      <groupId>org.codehaus.jettison</groupId>
+      <artifactId>jettison</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.eclipse.equinox.http</groupId>
+      <artifactId>servlet</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.persistence</groupId>
+      <artifactId>org.eclipse.persistence.antlr</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.persistence</groupId>
+      <artifactId>org.eclipse.persistence.core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.persistence</groupId>
+      <artifactId>org.eclipse.persistence.moxy</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.javassist</groupId>
+      <artifactId>javassist</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.spec.javax.transaction</groupId>
+      <artifactId>jboss-transaction-api_1.1_spec</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.jolokia</groupId>
+      <artifactId>jolokia-osgi</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.json</groupId>
+      <artifactId>json</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.ow2.asm</groupId>
+      <artifactId>asm-all</artifactId>
+    </dependency>
+    <!-- Visual VM hook -->
+    <dependency>
+      <groupId>org.ow2.chameleon.management</groupId>
+      <artifactId>chameleon-mbeans</artifactId>
+    </dependency>
+
+    <!-- Third party depedencies -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jcl-over-slf4j</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>log4j-over-slf4j</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>org.springframework.aop</artifactId>
+    </dependency>
+    <!-- Add Pax Exam -->
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>org.springframework.asm</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>org.springframework.beans</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>org.springframework.context</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>org.springframework.context.support</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>org.springframework.core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>org.springframework.expression</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>org.springframework.transaction</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>org.springframework.web</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>org.springframework.web.servlet</artifactId>
+    </dependency>
+    <!-- Spring security -->
+    <dependency>
+      <groupId>org.springframework.security</groupId>
+      <artifactId>spring-security-config</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.security</groupId>
+      <artifactId>spring-security-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.security</groupId>
+      <artifactId>spring-security-taglibs</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.security</groupId>
+      <artifactId>spring-security-web</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>virgomirror</groupId>
+      <artifactId>org.eclipse.jdt.core.compiler.batch</artifactId>
+    </dependency>
+
+    <!-- test to validate features.xml -->
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>features-test</artifactId>
+      <version>0.6.2-SNAPSHOT</version>
+    </dependency>
+    <!-- dependency for opendaylight-karaf-empty for use by testing -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>opendaylight-karaf-empty</artifactId>
+      <version>1.4.2-SNAPSHOT</version>
+      <type>zip</type>
+    </dependency>
+  </dependencies>
   <build>
     <resources>
       <resource>
           </execution>
         </executions>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <systemPropertyVariables>
+            <karaf.distro.groupId>org.opendaylight.controller</karaf.distro.groupId>
+            <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId>
+            <karaf.distro.version>${commons.opendaylight.version}</karaf.distro.version>
+          </systemPropertyVariables>
+          <dependenciesToScan>
+           <dependency>org.opendaylight.yangtools:features-test</dependency>
+          </dependenciesToScan>
+        </configuration>
+      </plugin>
     </plugins>
   </build>
 </project>
index b9107b9f62881d1fc2799ddbecc238559add943a..999cf704d2bedf212a283864e6d8e4d74f10fd68 100644 (file)
@@ -1,34 +1,35 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<features name="base-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+<features name="odl-base-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
 
-   <feature name="base-all" description="OpenDaylight Controller" version="${project.version}">
+   <feature name="odl-base-all" description="OpenDaylight Controller" version="${project.version}">
       <feature>http</feature>
       <feature>transaction</feature>
-      <feature>base-felix-dm</feature>
-      <feature>base-aries-spi-fly</feature>
-      <feature>base-dummy-console</feature>
-      <feature>base-apache-commons</feature>
-      <feature>base-eclipselink-persistence</feature>
-      <feature>base-gemini-web</feature>
-      <feature>base-tomcat</feature>
-      <feature>base-netty</feature>
-      <feature>base-jersey</feature>
-      <feature>base-spring-security</feature>
+      <feature>odl-base-felix-dm</feature>
+      <feature>odl-base-aries-spi-fly</feature>
+      <feature>odl-base-dummy-console</feature>
+      <feature>odl-base-apache-commons</feature>
+      <feature>odl-base-eclipselink-persistence</feature>
+      <feature>odl-base-gemini-web</feature>
+      <feature>odl-base-tomcat</feature>
+      <feature>odl-base-netty</feature>
+      <feature>odl-base-jersey</feature>
+      <feature>odl-base-jackson</feature>
+      <feature>odl-base-spring-security</feature>
    </feature>
-   <feature name="base-dummy-console" description="Temporary Dummy Console" version="1.1.0-SNAPSHOT">
+   <feature name="odl-base-dummy-console" description="Temporary Dummy Console" version="1.1.0-SNAPSHOT">
       <bundle>mvn:org.opendaylight.controller/dummy-console/1.1.0-SNAPSHOT</bundle>
    </feature>
-   <feature name="base-felix-dm" description="Felix Dependency Manager" version="${felix.dependencymanager.version}">
-      <bundle start-level="35">mvn:org.osgi/org.osgi.compendium/${osgi.compendium.version}</bundle>
-      <bundle start-level="35">mvn:org.apache.felix/org.apache.felix.dependencymanager/${felix.dependencymanager.version}</bundle>
-      <bundle start-level="35">mvn:org.apache.felix/org.apache.felix.dependencymanager.shell/${felix.dependencymanager.shell.version}</bundle>
+   <feature name="odl-base-felix-dm" description="Felix Dependency Manager" version="${felix.dependencymanager.version}">
+      <bundle>mvn:org.osgi/org.osgi.compendium/${osgi.compendium.version}</bundle>
+      <bundle>mvn:org.apache.felix/org.apache.felix.dependencymanager/${felix.dependencymanager.version}</bundle>
+      <bundle>mvn:org.apache.felix/org.apache.felix.dependencymanager.shell/${felix.dependencymanager.shell.version}</bundle>
    </feature>
-   <feature name="base-aries-spi-fly" description="Aries SPI Fly" version="${spifly.version}">
-      <bundle start-level="35">mvn:org.apache.aries/org.apache.aries.util/1.1.0</bundle>
-      <bundle start-level="35">mvn:org.apache.aries.spifly/org.apache.aries.spifly.dynamic.bundle/${spifly.version}</bundle>
-      <bundle start-level="35">mvn:org.ow2.asm/asm-all/4.0</bundle>
+   <feature name="odl-base-aries-spi-fly" description="Aries SPI Fly" version="${spifly.version}">
+      <bundle>mvn:org.apache.aries/org.apache.aries.util/1.1.0</bundle>
+      <bundle>mvn:org.apache.aries.spifly/org.apache.aries.spifly.dynamic.bundle/${spifly.version}</bundle>
+      <bundle>mvn:org.ow2.asm/asm-all/4.0</bundle>
    </feature>
-   <feature name='base-netty' version='${netty.version}'>
+   <feature name='odl-base-netty' version='${netty.version}'>
       <bundle>wrap:mvn:io.netty/netty-buffer/${netty.version}</bundle>
       <bundle>wrap:mvn:io.netty/netty-codec/${netty.version}</bundle>
       <bundle>wrap:mvn:io.netty/netty-transport/${netty.version}</bundle>
       <bundle>wrap:mvn:io.netty/netty-codec-http/${netty.version}</bundle>
       <bundle>mvn:org.opendaylight.controller.thirdparty/ganymed/1.1-SNAPSHOT</bundle>
    </feature>
-   <feature name="base-jersey" description="Jersey" version="${jersey.version}">
-      <feature>base-gemini-web</feature>
-      <bundle>mvn:org.opendaylight.controller.thirdparty/com.sun.jersey.jersey-servlet/${jersey.version}</bundle>
+   <feature name="odl-base-jersey" description="Jersey" version="${jersey.version}">
+      <feature>odl-base-gemini-web</feature>
       <bundle>mvn:com.sun.jersey/jersey-server/${jersey.version}</bundle>
       <bundle>mvn:com.sun.jersey/jersey-core/${jersey.version}</bundle>
       <bundle>mvn:com.sun.jersey/jersey-client/${jersey.version}</bundle>
       <bundle>mvn:com.sun.jersey/jersey-servlet/${jersey.version}</bundle>
-      <bundle start="true" start-level="35">mvn:javax.ws.rs/javax.ws.rs-api/2.0</bundle>
    </feature>
-   <feature name="base-jersey2-osgi" description="OSGi friendly Jersey" version="${jersey2.publisher.version}">
+   <feature name="odl-base-jersey2-osgi" description="OSGi friendly Jersey" version="${jersey2.publisher.version}">
       <feature>http</feature>
       <bundle>mvn:com.eclipsesource.jaxrs/jersey-all/${jersey2.version}</bundle>
       <bundle>mvn:com.eclipsesource.jaxrs/publisher/${jersey2.publisher.version}</bundle>
-      <bundle start="true" start-level="35">mvn:javax.ws.rs/javax.ws.rs-api/${jsr311.v2.api.version}</bundle>
+      <bundle start="true">mvn:javax.ws.rs/javax.ws.rs-api/${jsr311.v2.api.version}</bundle>
       <bundle>mvn:javax.annotation/javax.annotation-api/${javax.annotation.version}</bundle>
     </feature>
-   <feature name="base-jackson" description="Jackson JAX-RS" version="${jackson.version}">
-      <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.core/jackson-annotations/${jackson.version}</bundle>
-      <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.core/jackson-core/${jackson.version}</bundle>
-      <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.core/jackson-databind/${jackson.version}</bundle>
-      <bundle start="true" start-level="35">mvn:org.codehaus.jettison/jettison/${jettison.version}</bundle>
-      <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.module/jackson-module-jaxb-annotations/${jackson.version}</bundle>
-      <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-base/${jackson.version}</bundle>
-      <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider/${jackson.version}</bundle>
+   <feature name="odl-base-jackson" description="Jackson JAX-RS" version="${jackson.version}">
+      <bundle>mvn:com.sun.jersey/jersey-core/${jersey.version}</bundle>
+      <bundle>mvn:com.sun.jersey/jersey-client/${jersey.version}</bundle>
+      <bundle start="true">mvn:com.fasterxml.jackson.core/jackson-annotations/${jackson.version}</bundle>
+      <bundle start="true">mvn:com.fasterxml.jackson.core/jackson-core/${jackson.version}</bundle>
+      <bundle start="true">mvn:com.fasterxml.jackson.core/jackson-databind/${jackson.version}</bundle>
+      <bundle start="true">mvn:org.codehaus.jettison/jettison/${jettison.version}</bundle>
+      <bundle start="true">mvn:com.fasterxml.jackson.module/jackson-module-jaxb-annotations/${jackson.version}</bundle>
+      <bundle start="true">mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-base/${jackson.version}</bundle>
+      <bundle start="true">mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider/${jackson.version}</bundle>
    </feature>
-   <feature name="base-slf4j" description="SLF4J Logging" version="${slf4j.version}">
-      <bundle start-level="35">mvn:org.slf4j/slf4j-jdk14/1.7.2</bundle>
-      <bundle start-level="35">mvn:org.slf4j/slf4j-nop/1.7.2</bundle>
-      <bundle start-level="35">mvn:org.slf4j/slf4j-simple/1.7.2</bundle>
-      <bundle start="true" start-level="35">mvn:org.slf4j/slf4j-api/1.7.2</bundle>
+   <feature name="odl-base-slf4j" description="SLF4J Logging" version="${slf4j.version}">
+      <bundle>mvn:org.slf4j/slf4j-jdk14/1.7.2</bundle>
+      <bundle>mvn:org.slf4j/slf4j-nop/1.7.2</bundle>
+      <bundle>mvn:org.slf4j/slf4j-simple/1.7.2</bundle>
+      <bundle start="true">mvn:org.slf4j/slf4j-api/1.7.2</bundle>
    </feature>
-   <feature name="base-apache-commons" description="Apache Commons Libraries" version="${project.version}">
-      <bundle start="true" start-level="35">mvn:com.google.guava/guava/${guava.version}</bundle>
-      <bundle start="true" start-level="35">mvn:org.javassist/javassist/${javassist.version}</bundle>
-      <bundle start="true" start-level="35">mvn:commons-io/commons-io/${commons.io.version}</bundle>
-      <bundle start="true" start-level="35">mvn:commons-codec/commons-codec/${commons.codec.version}</bundle>
-      <bundle start="true" start-level="35">mvn:org.apache.commons/commons-lang3/${commons.lang3.version}</bundle>
-      <bundle start="true" start-level="35">mvn:commons-net/commons-net/${commons.net.version}</bundle>
+   <feature name="odl-base-apache-commons" description="Apache Commons Libraries" version="${project.version}">
+      <bundle start="true">mvn:com.google.guava/guava/${guava.version}</bundle>
+      <bundle start="true">mvn:org.javassist/javassist/${javassist.version}</bundle>
+      <bundle start="true">mvn:commons-io/commons-io/${commons.io.version}</bundle>
+      <bundle start="true">mvn:commons-codec/commons-codec/${commons.codec.version}</bundle>
+      <bundle start="true">mvn:org.apache.commons/commons-lang3/${commons.lang3.version}</bundle>
+      <bundle start="true">mvn:commons-net/commons-net/${commons.net.version}</bundle>
    </feature>
-   <feature name="base-eclipselink-persistence" description="EclipseLink Persistence API" version="2.0.4.v201112161009">
-      <bundle start="true" start-level="35">mvn:eclipselink/javax.persistence/2.0.4.v201112161009</bundle>
-      <bundle start="true" start-level="35">mvn:eclipselink/javax.resource/1.5.0.v200906010428</bundle>
-      <bundle start="true" start-level="35">mvn:org.eclipse.persistence/org.eclipse.persistence.moxy/2.5.0</bundle>
-      <bundle start="true" start-level="35">mvn:org.eclipse.persistence/org.eclipse.persistence.core/2.5.0</bundle>
+   <feature name="odl-base-eclipselink-persistence" description="EclipseLink Persistence API" version="2.0.4.v201112161009">
+      <bundle start="true">mvn:eclipselink/javax.persistence/2.0.4.v201112161009</bundle>
+      <bundle start="true">mvn:eclipselink/javax.resource/1.5.0.v200906010428</bundle>
+      <bundle start="true">mvn:org.eclipse.persistence/org.eclipse.persistence.moxy/2.5.0</bundle>
+      <bundle start="true">mvn:org.eclipse.persistence/org.eclipse.persistence.core/2.5.0</bundle>
    </feature>
-   <feature name="base-gemini-web" description="Gemini Web" version="${geminiweb.version}">
+   <feature name="odl-base-gemini-web" description="Gemini Web" version="${geminiweb.version}">
       <feature>http</feature>
       <feature>transaction</feature>
-      <feature>base-slf4j</feature>
-      <feature>base-felix-dm</feature>
-      <feature>base-jackson</feature>
-      <feature>base-apache-commons</feature>
-      <bundle start="true" start-level="35">mvn:com.google.code.gson/gson/${gson.version}</bundle>
-      <bundle start="true" start-level="35">mvn:commons-fileupload/commons-fileupload/${commons.fileupload.version}</bundle>
-      <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.gemini.web.core/${geminiweb.version}</bundle>
-      <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.gemini.web.extender/${geminiweb.version}</bundle>
-      <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.common/${virgo.version}</bundle>
-      <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.io/${virgo.version}</bundle>
-      <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.math/${virgo.version}</bundle>
-      <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.osgi/${virgo.version}</bundle>
-      <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.osgi.manifest/${virgo.version}</bundle>
-      <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.parser.manifest/${virgo.version}</bundle>
-      <bundle start="true" start-level="35">mvn:org.apache.felix/org.apache.felix.fileinstall/3.1.6</bundle>
-      <bundle start="true" start-level="35">mvn:orbit/javax.activation/1.1.0.v201211130549</bundle>
-      <bundle start="true" start-level="35">mvn:orbit/javax.annotation/1.1.0.v201209060031</bundle>
-      <bundle start="true" start-level="35">mvn:orbit/javax.ejb/3.1.1.v201204261316</bundle>
-      <bundle start="true" start-level="35">mvn:orbit/javax.el/2.2.0.v201108011116</bundle>
-      <bundle start="true" start-level="35">mvn:orbit/javax.mail.glassfish/1.4.1.v201108011116</bundle>
-      <bundle start="true" start-level="35">mvn:orbit/javax.xml.rpc/1.1.0.v201005080400</bundle>
-      <bundle start="true" start-level="35">mvn:org.eclipse.jetty.orbit/javax.servlet.jsp/2.2.0.v201112011158</bundle>
-      <bundle start="true" start-level="35">mvn:orbit/javax.servlet.jsp.jstl/1.2.0.v201105211821</bundle>
-      <bundle start="true" start-level="35">mvn:orbit/javax.servlet.jsp.jstl.impl/1.2.0.v201210211230</bundle>
+      <feature>odl-base-slf4j</feature>
+      <feature>odl-base-felix-dm</feature>
+      <feature>odl-base-jackson</feature>
+      <feature>odl-base-apache-commons</feature>
+      <bundle start="true">mvn:com.google.code.gson/gson/${gson.version}</bundle>
+      <bundle start="true">mvn:commons-fileupload/commons-fileupload/${commons.fileupload.version}</bundle>
+      <bundle start="true">mvn:geminiweb/org.eclipse.gemini.web.core/${geminiweb.version}</bundle>
+      <bundle start="true">mvn:geminiweb/org.eclipse.gemini.web.extender/${geminiweb.version}</bundle>
+      <bundle start="true">mvn:geminiweb/org.eclipse.virgo.util.common/${virgo.version}</bundle>
+      <bundle start="true">mvn:geminiweb/org.eclipse.virgo.util.io/${virgo.version}</bundle>
+      <bundle start="true">mvn:geminiweb/org.eclipse.virgo.util.math/${virgo.version}</bundle>
+      <bundle start="true">mvn:geminiweb/org.eclipse.virgo.util.osgi/${virgo.version}</bundle>
+      <bundle start="true">mvn:geminiweb/org.eclipse.virgo.util.osgi.manifest/${virgo.version}</bundle>
+      <bundle start="true">mvn:geminiweb/org.eclipse.virgo.util.parser.manifest/${virgo.version}</bundle>
+      <bundle start="true">mvn:org.apache.felix/org.apache.felix.fileinstall/3.1.6</bundle>
+      <bundle start="true">mvn:orbit/javax.activation/1.1.0.v201211130549</bundle>
+      <bundle start="true">mvn:orbit/javax.annotation/1.1.0.v201209060031</bundle>
+      <bundle start="true">mvn:orbit/javax.ejb/3.1.1.v201204261316</bundle>
+      <bundle start="true">mvn:orbit/javax.el/2.2.0.v201108011116</bundle>
+      <bundle start="true">mvn:orbit/javax.mail.glassfish/1.4.1.v201108011116</bundle>
+      <bundle start="true">mvn:orbit/javax.xml.rpc/1.1.0.v201005080400</bundle>
+      <bundle start="true">mvn:org.eclipse.jetty.orbit/javax.servlet.jsp/2.2.0.v201112011158</bundle>
+      <bundle start="true">mvn:orbit/javax.servlet.jsp.jstl/1.2.0.v201105211821</bundle>
+      <bundle start="true">mvn:orbit/javax.servlet.jsp.jstl.impl/1.2.0.v201210211230</bundle>
    </feature>
-   <feature name="base-tomcat" description="OpenDaylight Tomcat" version="7.0.32">
-      <feature>base-gemini-web</feature>
-      <feature>base-eclipselink-persistence</feature>
-      <bundle start="true" start-level="35">mvn:orbit/org.apache.catalina/7.0.32.v201211201336</bundle>
-      <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.gemini.web.tomcat/${geminiweb.version}</bundle>
-      <bundle start="true" start-level="35">mvn:orbit/org.apache.catalina.ha/7.0.32.v201211201952</bundle>
-      <bundle start="true" start-level="35">mvn:orbit/org.apache.catalina.tribes/7.0.32.v201211201952</bundle>
-      <bundle start="true" start-level="35">mvn:orbit/org.apache.coyote/7.0.32.v201211201952</bundle>
-      <bundle start="true" start-level="35">mvn:orbit/org.apache.el/7.0.32.v201211081135</bundle>
-      <bundle start="true" start-level="35">mvn:orbit/org.apache.jasper/7.0.32.v201211201952</bundle>
-      <bundle start="true" start-level="35">mvn:orbit/org.apache.juli.extras/7.0.32.v201211081135</bundle>
-      <bundle start="true" start-level="35">mvn:orbit/org.apache.tomcat.api/7.0.32.v201211081135</bundle>
-      <bundle start="true" start-level="35">mvn:orbit/org.apache.tomcat.util/7.0.32.v201211201952</bundle>
-      <bundle start="true" start-level="35">wrap:mvn:virgomirror/org.eclipse.jdt.core.compiler.batch/3.8.0.I20120518-2145</bundle>
+   <feature name="odl-base-tomcat" description="OpenDaylight Tomcat" version="7.0.53">
+      <feature>odl-base-gemini-web</feature>
+      <feature>odl-base-eclipselink-persistence</feature>
+      <bundle start="true">mvn:orbit/org.apache.catalina/${commons.karaf.catalina}</bundle>
+      <bundle start="true">mvn:geminiweb/org.eclipse.gemini.web.tomcat/${geminiweb.version}</bundle>
+      <bundle start="true">mvn:orbit/org.apache.catalina.ha/${commons.karaf.catalina.ha}</bundle>
+      <bundle start="true">mvn:orbit/org.apache.catalina.tribes/${commons.karaf.catalina.tribes}</bundle>
+      <bundle start="true">mvn:orbit/org.apache.coyote/${commons.karaf.coyote}</bundle>
+      <bundle start="true">mvn:orbit/org.apache.el/${commons.karaf.el}</bundle>
+      <bundle start="true">mvn:orbit/org.apache.jasper/${commons.karaf.jasper}</bundle>
+      <bundle start="true">mvn:orbit/org.apache.juli.extras/${commons.karaf.juli.version}</bundle>
+      <bundle start="true">mvn:orbit/org.apache.tomcat.api/${commons.karaf.tomcat.api}</bundle>
+      <bundle start="true">mvn:orbit/org.apache.tomcat.util/${commons.karaf.tomcat.util}</bundle>
+      <bundle start="true" >mvn:org.opendaylight.controller/karaf-tomcat-security/${karaf.security.version}</bundle>
+      <bundle start="true">wrap:mvn:virgomirror/org.eclipse.jdt.core.compiler.batch/${eclipse.jdt.core.compiler.batch.version}</bundle>
    </feature>
-   <feature name="base-spring" description="Opendaylight Spring Support" version="${spring.version}">
+   <feature name="odl-base-spring" description="Opendaylight Spring Support" version="${spring.version}">
       <bundle>mvn:org.ow2.asm/asm-all/${asm.version}</bundle>
       <bundle>mvn:org.aopalliance/com.springsource.org.aopalliance/${aopalliance.version}</bundle>
       <bundle>mvn:org.springframework/org.springframework.aop/${spring.version}</bundle>
       <bundle>mvn:org.springframework/org.springframework.expression/${spring.version}</bundle>
       <bundle>mvn:org.springframework/org.springframework.transaction/${spring.version}</bundle>
    </feature>
-   <feature name="base-spring-web" description="OpenDaylight Spring Web" version="${spring.version}">
-      <feature>base-spring</feature>
-      <feature>base-gemini-web</feature>
+   <feature name="odl-base-spring-web" description="OpenDaylight Spring Web" version="${spring.version}">
+      <feature>odl-base-spring</feature>
+      <feature>odl-base-gemini-web</feature>
       <bundle>mvn:org.springframework/org.springframework.web/${spring.version}</bundle>
       <bundle>mvn:org.springframework/org.springframework.web.servlet/${spring.version}</bundle>
    </feature>
-   <feature name="base-spring-security" description="OpenDaylight Spring Security" version="${spring-security.version}">
-      <feature>base-spring-web</feature>
+   <feature name="odl-base-spring-security" description="OpenDaylight Spring Security" version="${spring-security.version}">
+      <feature>odl-base-spring-web</feature>
       <bundle>mvn:org.springframework.security/spring-security-config/${spring-security.version}</bundle>
       <bundle>mvn:org.springframework.security/spring-security-core/${spring-security.version}</bundle>
       <bundle>mvn:org.springframework.security/spring-security-taglibs/${spring-security.version}</bundle>
index 7f57d8cb84cbb3b5d103799646c8ea787f8e0d88..f8df1aa58c979d5f5b5b1cfb4cc7e8f928754852 100644 (file)
@@ -4,7 +4,7 @@
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
   <repository>mvn:org.opendaylight.controller/features-config-persister/${config.version}/xml/features</repository>
-  <feature name='odl-config-netty' version='${project.version}'>
+  <feature name='odl-config-netty' version='${project.version}' description="OpenDaylight :: Config-Netty">
     <feature version='${project.version}'>odl-config-netty-config-api</feature>
     <bundle>mvn:org.opendaylight.controller/netty-event-executor-config/${project.version}</bundle>
     <bundle>mvn:org.opendaylight.controller/netty-threadgroup-config/${project.version}</bundle>
index a3c005b3bd8937425420c1eff652e89262657225..20fb19f5ff6a1218975f9703f6ad5310be601cdf 100644 (file)
@@ -6,11 +6,11 @@
   <repository>mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features</repository>
   <repository>mvn:org.opendaylight.controller/features-netconf/${netconf.version}/xml/features</repository>
   <repository>mvn:org.opendaylight.controller/features-config/${config.version}/xml/features</repository>
-  <feature name='odl-config-all' version='${project.version}'>
+  <feature name='odl-config-persister-all' version='${project.version}' description="OpenDaylight :: Config Persister:: All">
     <feature version='${project.version}'>odl-config-persister</feature>
     <feature version='${project.version}'>odl-config-startup</feature>
   </feature>
-  <feature name='odl-config-persister' version='${project.version}'>
+  <feature name='odl-config-persister' version='${project.version}' description="OpenDaylight :: Config Persister ">
     <feature version='${netconf.version}'>odl-netconf-api</feature>
     <feature version='${project.version}'>odl-config-api</feature>
     <feature version='${yangtools.version}'>odl-yangtools-binding-generator</feature>
@@ -27,7 +27,7 @@
     <bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.core/${eclipse.persistence.version}</bundle>
     <bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.moxy/${eclipse.persistence.version}</bundle>
   </feature>
-  <feature name='odl-config-startup' version='${project.version}'>
+  <feature name='odl-config-startup' version='${project.version}' description="OpenDaylight :: Config Persister:: Config Startup">
     <feature version='${project.version}'>odl-config-netconf-connector</feature>
     <feature version='${project.version}'>odl-config-persister</feature>
     <feature version='${project.version}'>odl-netconf-impl</feature>
index 5027588acb2e9fce758cffffff77388400c21c68..b4dd03f4910d6761e7415c7d657851e15de356f5 100644 (file)
@@ -5,7 +5,7 @@
           xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
   <repository>mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features</repository>
 
-  <feature name='odl-config-all' version='${project.version}'>
+  <feature name='odl-config-all' version='${project.version}' description="OpenDaylight :: Config :: All">
       <feature version='${mdsal.version}'>odl-mdsal-common</feature>
       <feature version='${project.version}'>odl-config-api</feature>
       <feature version='${project.version}'>odl-config-netty-config-api</feature>
@@ -13,7 +13,7 @@
       <feature version='${project.version}'>odl-config-manager</feature>
   </feature>
 
-  <feature name='odl-mdsal-common' version='${mdsal.version}'>
+  <feature name='odl-mdsal-common' version='${mdsal.version}' description="OpenDaylight :: Config :: All">
       <feature version='${yangtools.version}'>odl-yangtools-data-binding</feature>
       <bundle>mvn:org.opendaylight.controller/sal-common/${mdsal.version}</bundle>
       <bundle>mvn:org.opendaylight.controller/sal-common-api/${mdsal.version}</bundle>
       <bundle>mvn:org.opendaylight.controller/sal-common-util/${mdsal.version}</bundle>
   </feature>
 
-  <feature name='odl-config-api' version='${project.version}'>
+  <feature name='odl-config-api' version='${project.version}' description="OpenDaylight :: Config :: API">
     <bundle>mvn:org.opendaylight.controller/config-api/${project.version}</bundle>
     <feature version='${yangtools.version}'>odl-yangtools-common</feature>
     <feature version='${yangtools.version}'>odl-yangtools-binding</feature>
   </feature>
 
-  <feature name='odl-config-netty-config-api' version='${project.version}'>
+  <feature name='odl-config-netty-config-api' version='${project.version}' description="OpenDaylight :: Config :: Netty Config API">
     <feature version='${project.version}'>odl-config-api</feature>
     <bundle>mvn:org.opendaylight.controller/netty-config-api/${project.version}</bundle>
     <bundle>mvn:io.netty/netty-transport/${netty.version}</bundle>
@@ -35,7 +35,7 @@
     <bundle>mvn:io.netty/netty-buffer/${netty.version}</bundle>
   </feature>
 
-  <feature name='odl-config-core' version='${project.version}'>
+  <feature name='odl-config-core' version='${project.version}' description="OpenDaylight :: Config :: Core">
     <feature version='${yangtools.version}'>odl-yangtools-common</feature>
     <feature version='${yangtools.version}'>odl-yangtools-binding</feature>
     <feature version='${yangtools.version}'>odl-yangtools-binding-generator</feature>
@@ -49,7 +49,7 @@
     <bundle>mvn:com.google.guava/guava/${guava.version}</bundle>
     <bundle>mvn:org.javassist/javassist/${javassist.version}</bundle>
   </feature>
-  <feature name='odl-config-manager' version='${project.version}'>
+  <feature name='odl-config-manager' version='${project.version}' description="OpenDaylight :: Config :: Manager">
     <feature version='${project.version}'>odl-config-core</feature>
     <bundle>mvn:org.opendaylight.controller/config-manager/${project.version}</bundle>
   </feature>
index 3f914be4aeabacfef427189543a1a9f91fe7325f..05404586309e24af131236d14b83c4c2d6bcb1b0 100644 (file)
@@ -4,7 +4,7 @@
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
     <repository>mvn:org.opendaylight.controller/features-mdsal/${mdsal.version}/xml/features</repository>
-    <feature name='odl-flow-model' version='${project.version}'>
+    <feature name='odl-flow-model' version='${project.version}' description="OpenDaylight :: Flow :: Model">
         <feature version='${yangtools.version}'>odl-yangtools-models</feature>
         <bundle>mvn:org.opendaylight.controller.model/model-flow-base/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.controller.model/model-flow-service/${project.version}</bundle>
@@ -12,7 +12,7 @@
         <bundle>mvn:org.opendaylight.controller.model/model-inventory/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.controller.model/model-topology/${project.version}</bundle>
     </feature>
-    <feature name='odl-flow-services' version='${project.version}'>
+    <feature name='odl-flow-services' version='${project.version}' description="OpenDaylight :: Flow :: Services">
         <feature version='${project.version}'>odl-mdsal-broker</feature>
         <feature version='${project.version}'>odl-flow-model</feature>
         <bundle>mvn:org.opendaylight.controller.md/topology-manager/${project.version}</bundle>
index ac6b82b26fb355036ba92f4b2f26bc49df21e0c9..c6856c89fb4776718a7ea13cc1074cf71f403e12 100644 (file)
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-broker-impl</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-dom-xsql</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-dom-xsql-config</artifactId>
+      <classifier>config</classifier>
+      <type>xml</type>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-binding-api</artifactId>
       <artifactId>jersey-server</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.opendaylight.controller.thirdparty</groupId>
-      <artifactId>com.sun.jersey.jersey-servlet</artifactId>
+      <groupId>com.sun.jersey</groupId>
+      <artifactId>jersey-servlet</artifactId>
     </dependency>
     <dependency>
       <groupId>io.netty</groupId>
       <type>xml</type>
       <classifier>config</classifier>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-rest-docgen</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-annotations</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.datatype</groupId>
+      <artifactId>jackson-datatype-json-org</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.module</groupId>
+      <artifactId>jackson-module-jaxb-annotations</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.jaxrs</groupId>
+      <artifactId>jackson-jaxrs-base</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.jaxrs</groupId>
+      <artifactId>jackson-jaxrs-json-provider</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.json</groupId>
+      <artifactId>json</artifactId>
+    </dependency>
     <!-- test to validate features.xml -->
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
index a3d7ed0f83df6455006a4c94dbb52283d1438461..408be621f514b279a681bc7cdf6d53158f69fbc7 100644 (file)
@@ -7,13 +7,14 @@
     <repository>mvn:org.opendaylight.controller/features-config/${config.version}/xml/features</repository>
     <repository>mvn:org.opendaylight.controller/features-config-persister/${config.version}/xml/features</repository>
     <repository>mvn:org.opendaylight.controller/features-config-netty/${config.version}/xml/features</repository>
-    <feature name='odl-mdsal-all' version='${project.version}'>
+    <feature name='odl-mdsal-all' version='${project.version}' description="OpenDaylight :: MDSAL :: All">
         <feature version='${project.version}'>odl-mdsal-broker</feature>
         <feature version='${project.version}'>odl-mdsal-netconf-connector</feature>
         <feature version='${project.version}'>odl-restconf</feature>
+        <feature version='${project.version}'>odl-mdsal-xsql</feature>
         <feature version='${project.version}'>odl-toaster</feature>
     </feature>
-    <feature name='odl-mdsal-broker' version='${project.version}'>
+    <feature name='odl-mdsal-broker' version='${project.version}' description="OpenDaylight :: MDSAL :: Broker">
         <feature version='${yangtools.version}'>odl-yangtools-common</feature>
         <feature version='${yangtools.version}'>odl-yangtools-binding</feature>
         <feature version='${mdsal.version}'>odl-mdsal-common</feature>
@@ -30,7 +31,7 @@
         <bundle>mvn:org.opendaylight.controller/sal-inmemory-datastore/${project.version}</bundle>
         <configfile finalname="${config.configfile.directory}/${config.mdsal.configfile}">mvn:org.opendaylight.controller/md-sal-config/${mdsal.version}/xml/config</configfile>
     </feature>
-    <feature name='odl-mdsal-netconf-connector' version='${project.version}'>
+    <feature name='odl-mdsal-netconf-connector' version='${project.version}' description="OpenDaylight :: MDSAL :: Netconf Connector">
         <feature version='${project.version}'>odl-mdsal-broker</feature>
         <feature version='${netconf.version}'>odl-netconf-client</feature>
         <feature version='${yangtools.version}'>odl-yangtools-models</feature>
         <bundle>mvn:org.opendaylight.controller/netconf-config-dispatcher/${config.version}</bundle>
         <configfile finalname="${config.configfile.directory}/${config.netconf.connector.configfile}">mvn:org.opendaylight.controller/netconf-connector-config/${netconf.version}/xml/config</configfile>
     </feature>
-    <feature name='odl-restconf' version='${project.version}'>
+    <feature name='odl-restconf' version='${project.version}' description="OpenDaylight :: Restconf">
         <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
         <feature>war</feature>
         <bundle>mvn:org.opendaylight.controller/sal-rest-connector/${project.version}</bundle>
         <bundle>mvn:com.google.code.gson/gson/${gson.version}</bundle>
+        <bundle>mvn:org.opendaylight.yangtools/yang-data-codec-gson/${yangtools.version}</bundle>
         <bundle>mvn:com.sun.jersey/jersey-core/${jersey.version}</bundle>
         <bundle>mvn:com.sun.jersey/jersey-server/${jersey.version}</bundle>
-        <bundle>mvn:org.opendaylight.controller.thirdparty/com.sun.jersey.jersey-servlet/${jersey.version}</bundle>
+        <bundle>mvn:com.sun.jersey/jersey-servlet/${jersey.version}</bundle>
         <bundle>mvn:io.netty/netty-buffer/${netty.version}</bundle>
         <bundle>mvn:io.netty/netty-codec/${netty.version}</bundle>
         <bundle>mvn:io.netty/netty-codec-http/${netty.version}</bundle>
@@ -56,7 +58,7 @@
         <bundle>mvn:org.opendaylight.controller/sal-remote/${project.version}</bundle>
         <configfile finalname="${config.configfile.directory}/${config.restconf.configfile}">mvn:org.opendaylight.controller/sal-rest-connector-config/${mdsal.version}/xml/config</configfile>
     </feature>
-    <feature name='odl-toaster' version='${project.version}'>
+    <feature name='odl-toaster' version='${project.version}' description="OpenDaylight :: Toaster">
         <feature version='${yangtools.version}'>odl-yangtools-common</feature>
         <feature version='${yangtools.version}'>odl-yangtools-binding</feature>
         <feature version='${project.version}'>odl-mdsal-broker</feature>
         <bundle>mvn:org.opendaylight.controller.samples/sample-toaster-provider/${project.version}</bundle>
         <configfile finalname="${config.configfile.directory}/${config.toaster.configfile}">mvn:org.opendaylight.controller.samples/toaster-config/${project.version}/xml/config</configfile>
     </feature>
+    <feature name ='odl-mdsal-xsql' version='${project.version}'>
+        <feature version='${project.version}'>odl-mdsal-broker</feature>
+        <bundle>mvn:org.opendaylight.controller/sal-dom-xsql/${project.version}</bundle>
+        <configfile finalname="${config.configfile.directory}/${config.xsql.configfile}">mvn:org.opendaylight.controller/sal-dom-xsql-config/${project.version}/xml/config</configfile>
+    </feature>
+    <feature name ='odl-mdsal-apidocs' version='${project.version}'>
+        <feature version='${project.version}'>odl-restconf</feature>
+        <bundle>mvn:org.opendaylight.controller/sal-rest-docgen/${project.version}</bundle>
+        <bundle>mvn:com.fasterxml.jackson.core/jackson-annotations/${jackson.version}</bundle>
+        <bundle>mvn:com.fasterxml.jackson.core/jackson-core/${jackson.version}</bundle>
+        <bundle>mvn:com.fasterxml.jackson.core/jackson-databind/${jackson.version}</bundle>
+        <bundle>mvn:com.fasterxml.jackson.datatype/jackson-datatype-json-org/${jackson.version}</bundle>
+        <bundle>mvn:com.fasterxml.jackson.module/jackson-module-jaxb-annotations/${jackson.version}</bundle>
+        <bundle>mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-base/${jackson.version}</bundle>
+        <bundle>mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider/${jackson.version}</bundle>
+        <bundle>mvn:com.sun.jersey/jersey-core/${jersey.version}</bundle>
+        <bundle>mvn:com.sun.jersey/jersey-server/${jersey.version}</bundle>
+        <bundle>mvn:com.sun.jersey/jersey-servlet/${jersey.version}</bundle>
+        <bundle>wrap:mvn:org.json/json/${org.json.version}</bundle>
+    </feature>
 </features>
index 106e54a338203453fca414f06b89bce81232a3bc..d18d227f0013d1e861d56759840403dee0c06ada 100644 (file)
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>netconf-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>netconf-auth</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>ietf-netconf-monitoring</artifactId>
       <groupId>org.opendaylight.controller.thirdparty</groupId>
       <artifactId>ganymed</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.sshd</groupId>
+      <artifactId>sshd-core</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.openexi</groupId>
       <artifactId>nagasena</artifactId>
index 0033b0d83c7e4bf02aea300b62cf0ee69be350ba..0a6356231a84d1c671fa07e48212200a61451490 100644 (file)
@@ -5,7 +5,7 @@
           xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
   <repository>mvn:org.opendaylight.controller/features-protocol-framework/${protocol-framework.version}/xml/features</repository>
   <repository>mvn:org.opendaylight.controller/features-config/${config.version}/xml/features</repository>
-  <feature name='odl-netconf-all' version='${project.version}'>
+  <feature name='odl-netconf-all' version='${project.version}' description="OpenDaylight :: Netconf :: All">
     <feature version='${project.version}'>odl-netconf-api</feature>
     <feature version='${project.version}'>odl-netconf-mapping-api</feature>
     <feature version='${project.version}'>odl-netconf-util</feature>
     <feature version='${project.version}'>odl-netconf-monitoring</feature>
   </feature>
 
-  <feature name='odl-netconf-api' version='${project.version}'>
+  <feature name='odl-netconf-api' version='${project.version}' description="OpenDaylight :: Netconf :: API">
     <feature version='${protocol-framework.version}'>odl-protocol-framework</feature>
     <bundle>mvn:org.opendaylight.controller/netconf-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/netconf-auth/${project.version}</bundle>
     <bundle>mvn:org.opendaylight.controller/ietf-netconf-monitoring/${project.version}</bundle>
     <bundle>mvn:org.opendaylight.controller/ietf-netconf-monitoring-extension/${project.version}</bundle>
     <bundle>mvn:org.opendaylight.yangtools.model/ietf-inet-types/${ietf-inet-types.version}</bundle>
     <bundle>mvn:org.opendaylight.yangtools.model/ietf-yang-types/${ietf-yang-types.version}</bundle>
   </feature>
-  <feature name='odl-netconf-mapping-api' version='${project.version}'>
+  <feature name='odl-netconf-mapping-api' version='${project.version}' description="OpenDaylight :: Netconf :: Mapping API">
     <feature version='${project.version}'>odl-netconf-api</feature>
     <bundle>mvn:org.opendaylight.controller/netconf-mapping-api/${project.version}</bundle>
   </feature>
     <feature version='${project.version}'>odl-netconf-mapping-api</feature>
     <bundle>mvn:org.opendaylight.controller/netconf-util/${project.version}</bundle>
   </feature>
-    <feature name='odl-netconf-impl' version='${project.version}'>
+    <feature name='odl-netconf-impl' version='${project.version}' description="OpenDaylight :: Netconf :: Impl">
     <feature version='${project.version}'>odl-netconf-api</feature>
     <feature version='${project.version}'>odl-netconf-mapping-api</feature>
     <feature version='${project.version}'>odl-netconf-util</feature>
     <feature version='${project.version}'>odl-netconf-netty-util</feature>
     <bundle>mvn:org.opendaylight.controller/netconf-impl/${project.version}</bundle>
   </feature>
-  <feature name='odl-config-netconf-connector' version='${project.version}'>
+  <feature name='odl-config-netconf-connector' version='${project.version}' description="OpenDaylight :: Netconf :: Connector">
     <feature version='${config.version}'>odl-config-manager</feature>
     <feature version='${project.version}'>odl-netconf-api</feature>
     <feature version='${project.version}'>odl-netconf-mapping-api</feature>
     <feature version='${project.version}'>odl-netconf-util</feature>
     <bundle>mvn:org.opendaylight.controller/config-netconf-connector/${project.version}</bundle>
   </feature>
-  <feature name='odl-netconf-netty-util' version='${project.version}'>
+  <feature name='odl-netconf-netty-util' version='${project.version}' description="OpenDaylight :: Netconf :: Netty Util">
     <feature version='${project.version}'>odl-netconf-api</feature>
     <feature version='${project.version}'>odl-netconf-mapping-api</feature>
     <feature version='${project.version}'>odl-netconf-util</feature>
     <bundle>mvn:org.opendaylight.controller/netconf-netty-util/${project.version}</bundle>
     <bundle>mvn:org.opendaylight.controller.thirdparty/ganymed/${ganymed.version}</bundle>
+    <bundle>mvn:org.apache.sshd/sshd-core/${sshd-core.version}</bundle>
     <bundle>mvn:org.openexi/nagasena/${exi.nagasena.version}</bundle>
     <bundle>mvn:io.netty/netty-codec/${netty.version}</bundle>
     <bundle>mvn:io.netty/netty-handler/${netty.version}</bundle>
     <bundle>mvn:io.netty/netty-buffer/${netty.version}</bundle>
     <bundle>mvn:io.netty/netty-transport/${netty.version}</bundle>
   </feature>
-  <feature name='odl-netconf-client' version="${project.version}">
+  <feature name='odl-netconf-client' version='${project.version}' description="OpenDaylight :: Netconf :: Client">
     <feature version='${project.version}'>odl-netconf-netty-util</feature>
     <bundle>mvn:org.opendaylight.controller/netconf-client/${project.version}</bundle>
-    <configfile finalname="${config.configfile.directory}/${config.netconf.client.configfile}">mvn:org.opendaylight.controller/netconf-config/${netconf.version}/xml/config</configfile>
+    <configfile finalname='${config.configfile.directory}/${config.netconf.client.configfile}'>mvn:org.opendaylight.controller/netconf-config/${netconf.version}/xml/config</configfile>
   </feature>
-  <feature name='odl-netconf-monitoring' version='${project.version}'>
+  <feature name='odl-netconf-monitoring' version='${project.version}' description="OpenDaylight :: Netconf :: Monitoring">
     <feature version='${project.version}'>odl-netconf-util</feature>
     <bundle>mvn:org.opendaylight.controller/netconf-monitoring/${project.version}</bundle>
   </feature>
 
-</features>
\ No newline at end of file
+</features>
index 224aef1dacb040b33f3ef88872d86384fb436b96..875ca2ca617d26b9246f6eda27914daa9c87d358 100644 (file)
     <relativePath>../../opendaylight/commons/opendaylight</relativePath>
   </parent>
   <artifactId>features-nsf</artifactId>
-  <packaging>pom</packaging>
+  <version>${nsf.version}</version>
+  <packaging>jar</packaging>
   <name>OpenDaylight :: Features :: Network Service Functions</name>
   <description>Feature for Network Service Functions</description>
   <properties>
     <features.file>features.xml</features.file>
   </properties>
+  <dependencies>
+    <!-- test to validate features.xml -->
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>features-test</artifactId>
+    </dependency>
+    <!-- dependency for opendaylight-karaf-empty for use by testing -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>opendaylight-karaf-empty</artifactId>
+      <version>1.4.2-SNAPSHOT</version>
+      <type>zip</type>
+    </dependency>
+    <!-- Feature Dependencies -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>features-adsal</artifactId>
+      <version>${sal.version}</version>
+      <classifier>features</classifier>
+      <type>xml</type>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>features-base</artifactId>
+      <classifier>features</classifier>
+      <version>${commons.opendaylight.version}</version>
+      <type>xml</type>
+    </dependency>
+    <!-- Bundle Dependencies -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>appauth</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>arphandler</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>bundlescanner</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>bundlescanner.implementation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>commons.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>configuration</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>configuration.implementation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>connectionmanager</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>connectionmanager.implementation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>connectionmanager.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>containermanager</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>containermanager.implementation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>containermanager.shell</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>containermanager.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>controllermanager.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>devices.web</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>flowprogrammer.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>flows.web</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>routing.dijkstra_implementation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>forwarding.staticrouting</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>forwarding.staticrouting.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>forwardingrulesmanager</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>forwardingrulesmanager.implementation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>hosttracker</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>hosttracker.shell</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>hosttracker.implementation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>hosttracker.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>httpservice-bridge</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>jolokia-bridge</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>logging.bridge</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>networkconfig.bridgedomain.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>networkconfig.neutron</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>networkconfig.neutron.implementation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>networkconfig.neutron.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>osgi-brandfragment.web</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>samples.loadbalancer</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>samples.loadbalancer.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>samples.simpleforwarding</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>security</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>statistics.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>statisticsmanager</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>statisticsmanager.implementation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>subnets.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>switchmanager</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>switchmanager.implementation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>switchmanager.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>topology.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>topology.web</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>topologymanager</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>topologymanager.shell</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>troubleshoot.web</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>usermanager</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>usermanager.implementation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>usermanager.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.thirdparty</groupId>
+      <artifactId>net.sf.jung2</artifactId>
+    </dependency>
+  </dependencies>
   <build>
     <resources>
       <resource>
           </execution>
         </executions>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <systemPropertyVariables>
+            <karaf.distro.groupId>org.opendaylight.controller</karaf.distro.groupId>
+            <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId>
+            <karaf.distro.version>${commons.opendaylight.version}</karaf.distro.version>
+          </systemPropertyVariables>
+          <dependenciesToScan>
+           <dependency>org.opendaylight.yangtools:features-test</dependency>
+          </dependenciesToScan>
+        </configuration>
+      </plugin>
     </plugins>
   </build>
 </project>
index 130d72e01ae588780ccaa8d7840be0727874e2da..8dc51f1644c48dd31e9bf911681ea6819d7dc32b 100644 (file)
@@ -1,5 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <features name="nsf-${project.version}"  xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+    <repository>mvn:org.opendaylight.controller/features-base/${commons.opendaylight.version}/xml/features</repository>
+    <repository>mvn:org.opendaylight.controller/features-adsal/${sal.version}/xml/features</repository>
     <feature name="odl-nsf-all" description="OpenDaylight :: NSF :: All Network Service Functions" version="${project.version}">
         <feature version="${sal.version}">odl-adsal-all</feature>
         <feature version="${project.version}">odl-nsf-managers</feature>
@@ -11,7 +13,7 @@
     </feature>
 
     <feature name="odl-nsf-managers" description="OpenDaylight :: AD-SAL :: Network Service Functions" version="${project.version}">
-        <feature version="${project.version}">base-all</feature>
+        <feature version="${commons.opendaylight.version}">odl-base-all</feature>
         <feature version="${sal.version}">odl-adsal-all</feature>
         <bundle>mvn:org.opendaylight.controller/usermanager/${usermanager.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/usermanager.implementation/${usermanager.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/hosttracker.implementation/${hosttracker.implementation.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/hosttracker.shell/${hosttracker.shell.version}</bundle>
 
-        <bundle>mvn:org.opendaylight.controller/forwarding.staticrouting</bundle>
+        <bundle>mvn:org.opendaylight.controller/forwarding.staticrouting/${forwarding.staticrouting}</bundle>
 
         <bundle>mvn:org.opendaylight.controller.thirdparty/net.sf.jung2/2.0.1</bundle>
-        <bundle>mvn:org.opendaylight.controller/routing.dijkstra_implementation</bundle>
+        <bundle>mvn:org.opendaylight.controller/routing.dijkstra_implementation/${routing.dijkstra_implementation.version}</bundle>
     </feature>
 
     <feature name="odl-adsal-northbound" description="OpenDaylight :: AD-SAL :: Northbound APIs" version="${project.version}">
-        <feature version="${project.version}">base-all</feature>
+        <feature version="${commons.opendaylight.version}">odl-base-all</feature>
         <feature version="${project.version}">odl-nsf-managers</feature>
-        <bundle start-level="35">mvn:org.ow2.asm/asm-all/${asm.version}</bundle>
+        <bundle>mvn:org.ow2.asm/asm-all/${asm.version}</bundle>
         <!--
             TODO : Resolve these in a follow-up commit
             <bundle>mvn:org.opendaylight.controller/httpservice-bridge/${httpservice-bridge.northbound.version}</bundle>
@@ -61,6 +63,7 @@
         <bundle>mvn:org.opendaylight.controller/bundlescanner/${bundlescanner.api.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/bundlescanner.implementation/${bundlescanner.implementation.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/commons.northbound/${northbound.commons.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller/connectionmanager.northbound/${connectionmanager.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/flowprogrammer.northbound/${flowprogrammer.northbound.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/hosttracker.northbound/${hosttracker.northbound.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/networkconfig.bridgedomain.northbound/${networkconfig.bridgedomain.northbound.version}</bundle>
index 88ed7491a75d922646dcdfcf6f43cad77392be00..039060b4aeb7bec891d74ccb5ea018ef19855bad 100644 (file)
@@ -25,5 +25,6 @@
     <module>flow</module>
     <module>netconf</module>
     <module>protocol-framework</module>
+    <module>adsal-compatibility</module>
   </modules>
-</project>
+</project>
\ No newline at end of file
index 6daa3432c14285d8746bcd7385b08e520213f330..46510bca469805cd190222787693fe50d9492e33 100644 (file)
@@ -4,7 +4,7 @@
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
   <repository>mvn:org.opendaylight.controller/features-config/${config.version}/xml/features</repository>
-  <feature name='odl-protocol-framework' version='${project.version}'>
+  <feature name='odl-protocol-framework' version='${project.version}' description="OpenDaylight :: Protocol Framework">
     <feature version='${config.version}'>odl-config-api</feature>
     <feature version='${config.version}'>odl-config-netty-config-api</feature>
     <bundle>mvn:org.opendaylight.controller/protocol-framework/${protocol-framework.version}</bundle>
diff --git a/opendaylight/archetypes/opendaylight-configfile-archetype/pom.xml b/opendaylight/archetypes/opendaylight-configfile-archetype/pom.xml
new file mode 100644 (file)
index 0000000..38c8616
--- /dev/null
@@ -0,0 +1,52 @@
+<?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>
+
+  <groupId>org.opendaylight.controller</groupId>
+  <artifactId>opendaylight-configfile-archetype</artifactId>
+  <version>1.1-SNAPSHOT</version>
+  <packaging>maven-archetype</packaging>
+
+
+  <build>
+    <extensions>
+      <extension>
+        <groupId>org.apache.maven.archetype</groupId>
+        <artifactId>archetype-packaging</artifactId>
+        <version>2.2</version>
+      </extension>
+    </extensions>
+
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <artifactId>maven-archetype-plugin</artifactId>
+          <version>2.2</version>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+
+  <description>Configuration files for md-sal</description>
+
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git/md-sal-config</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git/md-sal-config</developerConnection>
+    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL/md-sal-config</url>
+  </scm>
+
+  <distributionManagement>
+    <repository>
+      <id>opendaylight-release</id>
+      <url>http://nexus.opendaylight.org/content/repositories/opendaylight.release/</url>
+    </repository>
+    <snapshotRepository>
+      <id>opendaylight-snapshot</id>
+      <url>http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/</url>
+    </snapshotRepository>
+    <site>
+      <id>website</id>
+      <url>dav:http://nexus.opendaylight.org/content/sites/site/sal-parent</url>
+    </site>
+  </distributionManagement>
+</project>
diff --git a/opendaylight/archetypes/opendaylight-configfile-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml b/opendaylight/archetypes/opendaylight-configfile-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml
new file mode 100644 (file)
index 0000000..d404f99
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archetype-descriptor xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd" name="md-sal-config"
+    xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <requiredProperties>
+    <requiredProperty key="repoName"/>
+  </requiredProperties>
+  <fileSets>
+    <fileSet filtered="true" encoding="UTF-8">
+      <directory>src/main/resources</directory>
+      <includes>
+        <include>**/*.xml</include>
+      </includes>
+    </fileSet>
+  </fileSets>
+</archetype-descriptor>
diff --git a/opendaylight/archetypes/opendaylight-configfile-archetype/src/main/resources/archetype-resources/pom.xml b/opendaylight/archetypes/opendaylight-configfile-archetype/src/main/resources/archetype-resources/pom.xml
new file mode 100644 (file)
index 0000000..3c778e2
--- /dev/null
@@ -0,0 +1,76 @@
+<?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>
+  <!--
+    Necessary TODO: Hookup your parent pom here, else you will not get necessary versions,
+    maven repos etc.  If you run this archetype in a subdirectory of your project, it
+    will pick the pom.xml from the parent directory as the parent pom, which may or may
+    not be correct.
+  -->
+  <!--
+    Necessary TODO: Replace the contents of src/main/resources/80-${repoName}.xml with
+    the proper config subsystem contents for your module
+  -->
+  <artifactId>${artifactId}</artifactId>
+  <groupId>${groupId}</groupId>
+  <description>Configuration files for md-sal</description>
+  <!-- Optional TODO: Uncomment version if you are not using a parent pom.xml
+   <version>${version}</version>
+   -->
+  <packaging>jar</packaging>
+  <properties>
+      <!-- Optional TODO: Rename your configfile to taste -->
+      <configfile>80-${repoName}.xml</configfile>
+  </properties>
+  <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/${configfile}</file>
+                  <type>xml</type>
+                  <classifier>config</classifier>
+                </artifact>
+                <!--
+                  Optional TODO: Add additional config files
+                    You may need to add more than one config file
+                    if so, you just need to add additional <artifact> entries
+                    here WITH DIFFERENT CLASSIFIERS
+                    Example:
+                    <artifact>
+                      <file>${project.build.directory}/classes/<another-configfile></file>
+                      <type>xml</type>
+                      <classifier>config-<meaningful suffix to describe your other configfile></classifier>
+                    </artifact>
+                -->
+              </artifacts>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <scm>
+      <connection>scm:git:ssh://git.opendaylight.org:29418/${repoName}.git</connection>
+      <developerConnection>scm:git:ssh://git.opendaylight.org:29418/${repoName}.git</developerConnection>
+      <tag>HEAD</tag>
+      <url>https://git.opendaylight.org/gerrit/gitweb?p=${repoName}.git;a=summary</url>
+   </scm>
+</project>
diff --git a/opendaylight/archetypes/opendaylight-configfile-archetype/src/main/resources/archetype-resources/src/main/resources/80-__repoName__.xml b/opendaylight/archetypes/opendaylight-configfile-archetype/src/main/resources/archetype-resources/src/main/resources/80-__repoName__.xml
new file mode 100644 (file)
index 0000000..432b947
--- /dev/null
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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>
+    <required-capabilities>
+        <!-- Necessary TODO put your required capabilities here
+
+        Examples:
+        <capability>urn:opendaylight:params:xml:ns:yang:controller:netty?module=netty&amp;revision=2013-11-19</capability>
+        <capability>urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor?module=netty-event-executor&amp;revision=2013-11-12</capability>
+        <capability>urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup?module=threadgroup&amp;revision=2013-11-07</capability>
+        <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">
+                <!-- Optional TODO: Add your modules definitions here
+                Examples:
+                <module>
+                    <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup">netty:netty-threadgroup-fixed</type>
+                    <name>global-boss-group</name>
+                </module>
+                <module>
+                    <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup">netty:netty-threadgroup-fixed</type>
+                    <name>global-worker-group</name>
+                </module>
+                <module>
+                    <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty:timer">netty:netty-hashed-wheel-timer</type>
+                    <name>global-timer</name>
+                </module>
+                <module>
+                    <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor">netty:netty-global-event-executor</type>
+                    <name>singleton</name>
+                </module>
+                -->
+            </modules>
+
+            <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+                <!-- Optional TODO: Put your service instance definitions here
+                Examples:
+                <service>
+                    <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-threadgroup</type>
+                    <instance>
+                        <name>global-boss-group</name>
+                        <provider>/modules/module[type='netty-threadgroup-fixed'][name='global-boss-group']</provider>
+                    </instance>
+                    <instance>
+                        <name>global-worker-group</name>
+                        <provider>/modules/module[type='netty-threadgroup-fixed'][name='global-worker-group']</provider>
+                    </instance>
+                </service>
+                <service>
+                    <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-event-executor</type>
+                    <instance>
+                        <name>global-event-executor</name>
+                        <provider>/modules/module[type='netty-global-event-executor'][name='singleton']</provider>
+                    </instance>
+                </service>
+                <service>
+                    <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-timer</type>
+                    <instance>
+                        <name>global-timer</name>
+                        <provider>/modules/module[type='netty-hashed-wheel-timer'][name='global-timer']</provider>
+                    </instance>
+                </service>
+                -->
+            </services>
+        </data>
+
+    </configuration>
+</snapshot>
diff --git a/opendaylight/archetypes/opendaylight-configfile-archetype/src/test/resources/projects/basic/archetype.properties b/opendaylight/archetypes/opendaylight-configfile-archetype/src/test/resources/projects/basic/archetype.properties
new file mode 100644 (file)
index 0000000..7a940e7
--- /dev/null
@@ -0,0 +1,6 @@
+#Mon Aug 25 05:45:18 CDT 2014
+package=it.pkg
+version=0.1-SNAPSHOT
+groupId=archetype.it
+artifactId=basic
+repoName=foo
diff --git a/opendaylight/archetypes/opendaylight-configfile-archetype/src/test/resources/projects/basic/goal.txt b/opendaylight/archetypes/opendaylight-configfile-archetype/src/test/resources/projects/basic/goal.txt
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/opendaylight/archetypes/opendaylight-karaf-distro-archetype/pom.xml b/opendaylight/archetypes/opendaylight-karaf-distro-archetype/pom.xml
new file mode 100644 (file)
index 0000000..8883c64
--- /dev/null
@@ -0,0 +1,38 @@
+<?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>
+
+  <groupId>org.opendaylight.controller</groupId>
+  <artifactId>opendaylight-karaf-distro-archetype</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>maven-archetype</packaging>
+
+  <name>distribution-karaf-archetype</name>
+
+  <build>
+    <extensions>
+      <extension>
+        <groupId>org.apache.maven.archetype</groupId>
+        <artifactId>archetype-packaging</artifactId>
+        <version>2.2</version>
+      </extension>
+    </extensions>
+
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <artifactId>maven-archetype-plugin</artifactId>
+          <version>2.2</version>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+
+  <url>https://wiki.opendaylight.org/view/CrossProject:Integration_Group/distribution-karaf</url>
+
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+  </scm>
+</project>
diff --git a/opendaylight/archetypes/opendaylight-karaf-distro-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml b/opendaylight/archetypes/opendaylight-karaf-distro-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml
new file mode 100644 (file)
index 0000000..4c4f510
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archetype-descriptor xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd"
+    xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <requiredProperties>
+    <requiredProperty key="repoName"/>
+  </requiredProperties>
+</archetype-descriptor>
diff --git a/opendaylight/archetypes/opendaylight-karaf-distro-archetype/src/main/resources/archetype-resources/pom.xml b/opendaylight/archetypes/opendaylight-karaf-distro-archetype/src/main/resources/archetype-resources/pom.xml
new file mode 100644 (file)
index 0000000..965c619
--- /dev/null
@@ -0,0 +1,285 @@
+<?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>
+  <!--
+    Necessary TODO: Hookup your parent pom here, else you will not get necessary versions,
+    maven repos etc.  If you run this archetype in a subdirectory of your project, it
+    will pick the pom.xml from the parent directory as the parent pom, which may or may
+    not be correct.
+  -->
+  <artifactId>${artifactId}</artifactId>
+  <groupId>${groupId}</groupId>
+  <!-- Optional TODO: Uncomment version if you are not using a parent pom.xml
+  <version>${version}</version>
+  -->
+  <packaging>pom</packaging>
+  <prerequisites>
+    <maven>3.0</maven>
+  </prerequisites>
+  <properties>
+    <!-- Optional TODO: Move these properties to your parent pom and possibly
+            DependencyManagement section of your parent pom -->
+    <branding.version>1.0.0-SNAPSHOT</branding.version>
+    <karaf.resources.version>1.4.2-SNAPSHOT</karaf.resources.version>
+    <karaf.version>3.0.1</karaf.version>
+  </properties>
+
+  <dependencies>
+    <!-- Basic Karaf dependencies -->
+    <dependency>
+      <groupId>org.apache.karaf.features</groupId>
+      <artifactId>framework</artifactId>
+      <version>${karaf.version}</version>
+      <type>kar</type>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.karaf.features</groupId>
+      <artifactId>standard</artifactId>
+      <version>${karaf.version}</version>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+
+    <!-- ODL Branding -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>karaf.branding</artifactId>
+      <version>${branding.version}</version>
+      <scope>compile</scope>
+    </dependency>
+
+    <!-- ODL Resources needed for karaf -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>opendaylight-karaf-resources</artifactId>
+      <version>${karaf.resources.version}</version>
+    </dependency>
+
+    <!-- Project local feautures -->
+    <!--
+      Necessary TODO put your features here.
+
+      Note: they will need to be <type>xml</xml>
+      and <classifier>features</classifier>.
+
+      Note: they must be <scope>runtime</scope>
+
+      Note: usually you would only need to depend
+      on your own feature file here for your local distro,
+      and possible the features-mdsal for odl-restconf
+      (although, strange situations do exist :) )
+
+      Example:
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>features-mdsal</artifactId>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.openflowplugin</groupId>
+        <artifactId>features-openflowplugin</artifactId>
+        <version>0.0.3-SNAPSHOT</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
+    -->
+  </dependencies>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.eclipse.m2e</groupId>
+          <artifactId>lifecycle-mapping</artifactId>
+          <version>1.0.0</version>
+          <configuration>
+            <lifecycleMappingMetadata>
+              <pluginExecutions>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.apache.felix</groupId>
+                    <artifactId>maven-bundle-plugin</artifactId>
+                    <versionRange>[0,)</versionRange>
+                    <goals>
+                      <goal>cleanVersions</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore></ignore>
+                  </action>
+                </pluginExecution>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-dependency-plugin</artifactId>
+                    <versionRange>[0,)</versionRange>
+                    <goals>
+                      <goal>copy</goal>
+                      <goal>unpack</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore></ignore>
+                  </action>
+                </pluginExecution>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.apache.karaf.tooling</groupId>
+                    <artifactId>karaf-maven-plugin</artifactId>
+                    <versionRange>[0,)</versionRange>
+                    <goals>
+                      <goal>commands-generate-help</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore></ignore>
+                  </action>
+                </pluginExecution>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.fusesource.scalate</groupId>
+                    <artifactId>maven-scalate-plugin</artifactId>
+                    <versionRange>[0,)</versionRange>
+                    <goals>
+                      <goal>sitegen</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore></ignore>
+                  </action>
+                </pluginExecution>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.apache.servicemix.tooling</groupId>
+                    <artifactId>depends-maven-plugin</artifactId>
+                    <versionRange>[0,)</versionRange>
+                    <goals>
+                      <goal>generate-depends-file</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore></ignore>
+                  </action>
+                </pluginExecution>
+              </pluginExecutions>
+            </lifecycleMappingMetadata>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.karaf.tooling</groupId>
+        <artifactId>karaf-maven-plugin</artifactId>
+        <version>${karaf.version}</version>
+        <extensions>true</extensions>
+        <configuration>
+          <bootFeatures>
+            <feature>standard</feature>
+            <!--
+              Optional TODO: Add entries here for the features you want in your local distro
+              Note: odl-restconf is a separate feature from odl-mdsal-broker.  If you want
+              restconf, you need to list it here explicitely.
+              Examples:
+              <feature>odl-openflowplugin-flow-services</feature>
+              <feature>odl-restconf</feature>
+            -->
+            <!-- Final TODO: Remove TODO Comments ;) -->
+          </bootFeatures>
+        </configuration>
+        <executions>
+          <execution>
+            <id>process-resources</id>
+            <goals>
+              <goal>install-kars</goal>
+            </goals>
+            <phase>process-resources</phase>
+          </execution>
+          <execution>
+            <id>package</id>
+            <goals>
+              <goal>instance-create-archive</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <version>2.6</version>
+        <executions>
+          <execution>
+            <id>copy</id>
+            <goals>
+              <goal>copy</goal>
+            </goals>
+            <phase>generate-resources</phase>
+            <configuration>
+              <artifactItems>
+                <artifactItem>
+                  <groupId>org.opendaylight.controller</groupId>
+                  <artifactId>karaf.branding</artifactId>
+                  <version>${karaf.branding.version}</version>
+                  <outputDirectory>target/assembly/lib</outputDirectory>
+                  <destFileName>karaf.branding-${branding.version}.jar</destFileName>
+                </artifactItem>
+              </artifactItems>
+            </configuration>
+          </execution>
+          <execution>
+            <id>unpack-karaf-resources</id>
+            <goals>
+              <goal>unpack-dependencies</goal>
+            </goals>
+            <phase>prepare-package</phase>
+            <configuration>
+             <outputDirectory>${project.build.directory}/assembly</outputDirectory>
+             <groupId>org.opendaylight.controller</groupId>
+             <includeArtifactIds>opendaylight-karaf-resources</includeArtifactIds>
+             <excludes>META-INF\/**</excludes>
+             <excludeTransitive>true</excludeTransitive>
+             <ignorePermissions>false</ignorePermissions>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+            <execution>
+                <phase>prepare-package</phase>
+                <goals>
+                    <goal>run</goal>
+                </goals>
+                <configuration>
+                  <tasks>
+                    <chmod perm="755">
+                        <fileset dir="${project.build.directory}/assembly/bin">
+                          <include name="karaf" />
+                          <include name="instance" />
+                          <include name="start"/>
+                          <include name="stop"/>
+                          <include name="status"/>
+                          <include name="client"/>
+                          <include name="shell"/>
+                        </fileset>
+                    </chmod>
+                  </tasks>
+                </configuration>
+            </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/${repoName}.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/${repoName}.git</developerConnection>
+    <tag>HEAD</tag>
+    <url>https://git.opendaylight.org/gerrit/gitweb?p=${repoName}.git;a=summary</url>
+  </scm>
+</project>
diff --git a/opendaylight/archetypes/opendaylight-karaf-distro-archetype/src/test/resources/projects/basic/archetype.properties b/opendaylight/archetypes/opendaylight-karaf-distro-archetype/src/test/resources/projects/basic/archetype.properties
new file mode 100644 (file)
index 0000000..dd29db6
--- /dev/null
@@ -0,0 +1,6 @@
+#Thu Aug 21 14:44:29 CDT 2014
+package=it.pkg
+version=0.1-SNAPSHOT
+groupId=archetype.it
+artifactId=basic
+repoName=foo
diff --git a/opendaylight/archetypes/opendaylight-karaf-distro-archetype/src/test/resources/projects/basic/goal.txt b/opendaylight/archetypes/opendaylight-karaf-distro-archetype/src/test/resources/projects/basic/goal.txt
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/opendaylight/archetypes/opendaylight-karaf-features/pom.xml b/opendaylight/archetypes/opendaylight-karaf-features/pom.xml
new file mode 100644 (file)
index 0000000..4973a69
--- /dev/null
@@ -0,0 +1,36 @@
+<?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>
+
+  <groupId>org.opendaylight.controller</groupId>
+  <artifactId>opendaylight-karaf-features-archetype</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>maven-archetype</packaging>
+
+  <name>opendaylight-karaf-features-archetype</name>
+
+  <build>
+    <extensions>
+      <extension>
+        <groupId>org.apache.maven.archetype</groupId>
+        <artifactId>archetype-packaging</artifactId>
+        <version>2.2</version>
+      </extension>
+    </extensions>
+
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <artifactId>maven-archetype-plugin</artifactId>
+          <version>2.2</version>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git/</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git/</developerConnection>
+    <url>https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=summary</url>
+  </scm>
+</project>
diff --git a/opendaylight/archetypes/opendaylight-karaf-features/src/main/resources/META-INF/maven/archetype-metadata.xml b/opendaylight/archetypes/opendaylight-karaf-features/src/main/resources/META-INF/maven/archetype-metadata.xml
new file mode 100644 (file)
index 0000000..158e448
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archetype-descriptor xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd" name="features-integration"
+    xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <requiredProperties>
+    <requiredProperty key="repoName"/>
+  </requiredProperties>
+  <fileSets>
+    <fileSet filtered="true" encoding="UTF-8">
+    <directory>src/main/resources</directory>
+    <include>**/*.xml</include>
+    </fileSet>
+  </fileSets>
+</archetype-descriptor>
diff --git a/opendaylight/archetypes/opendaylight-karaf-features/src/main/resources/archetype-resources/pom.xml b/opendaylight/archetypes/opendaylight-karaf-features/src/main/resources/archetype-resources/pom.xml
new file mode 100644 (file)
index 0000000..e135e6b
--- /dev/null
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Necessary TODO: Put your copyright here.
+
+ 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>
+   <!--
+    Necessary TODO: Hookup your parent pom here, else you will not get necessary versions,
+    maven repos etc.  If you run this archetype in a subdirectory of your project, it
+    will pick the pom.xml from the parent directory as the parent pom, which may or may
+    not be correct.
+  -->
+   <artifactId>features-${repoName}</artifactId>
+   <groupId>${groupId}</groupId>
+   <!-- Optional TODO: Uncomment version if you are not using a parent pom.xml
+   <version>${version}</version>
+   -->
+   <packaging>jar</packaging>
+   <properties>
+      <features.file>features.xml</features.file>
+      <!-- Optional TODO: Move these properties to your parent pom and possibly
+            DependencyManagement section of your parent pom -->
+      <branding.version>1.0.0-SNAPSHOT</branding.version>
+      <karaf.resources.version>1.4.2-SNAPSHOT</karaf.resources.version>
+      <karaf.version>3.0.1</karaf.version>
+      <feature.test.version>0.6.2-SNAPSHOT</feature.test.version>
+      <karaf.empty.version>1.4.2-SNAPSHOT</karaf.empty.version>
+      <surefire.version>2.16</surefire.version>
+   </properties>
+   <dependencies>
+    <!--
+      Necessary TODO: Put dependencies on any feature repos
+      you use in your features.xml file.
+
+      Note: they will need to be <type>xml</xml>
+      and <classifier>features</classifier>.
+      One other thing to watch for is to make sure they are
+      <scope>compile</compile>, which they should be by default,
+      but be cautious lest they be at a different scope in a parent pom.
+
+      Examples:
+        <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>features-yangtools</artifactId>
+          <version>0.6.2-SNAPSHOT</version>
+          <classifier>features</classifier>
+          <type>xml</type>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>features-mdsal</artifactId>
+          <version>1.1-SNAPSHOT</version>
+          <classifier>features</classifier>
+          <type>xml</type>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.openflowplugin</groupId>
+          <artifactId>features-openflowplugin</artifactId>
+          <version>0.0.3-SNAPSHOT</version>
+          <classifier>features</classifier>
+          <type>xml</type>
+        </dependency>
+    -->
+
+    <!--
+      Necessary TODO: Put dependencies for bundles directly referenced
+      in your features.xml file.  For every <bundle> reference in your
+      features.xml file, you need a corresponding dependency here.
+
+      Examples:
+      <dependency>
+        <groupId>${groupId}</groupId>
+        <artifactId>${repoName}-provider</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>${groupId}</groupId>
+        <artifactId>${repoName}-model</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+    -->
+
+    <!--
+      Necessary TODO: Put dependencies for configfiles directly referenced
+      in your features.xml file.  For every <configfile> reference in your
+      features.xml file, you need a corresponding dependency here.
+
+      Example (presuming here version is coming from the parent pom):
+      <dependency>
+        <groupId>${groupId}</groupId>
+        <artifactId>${repoName}-config</artifactId>
+        <version>${project.version}</version>
+        <type>xml</type>
+        <classifier>config</classifier>
+      </dependency>
+    -->
+
+    <!--
+      Optional TODO: Remove TODO comments.
+    -->
+    <!-- test to validate features.xml -->
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>features-test</artifactId>
+      <version>${feature.test.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <!-- dependency for opendaylight-karaf-empty for use by testing -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>opendaylight-karaf-empty</artifactId>
+      <version>${karaf.empty.version}</version>
+      <type>zip</type>
+    </dependency>
+    <!-- Uncomment this if you get an error : java.lang.NoSuchMethodError: org.slf4j.helpers.MessageFormatter.format(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Lorg/slf4j/helpers/FormattingTuple;
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <version>1.7.2</version>
+    </dependency>
+    -->
+
+   </dependencies>
+   <build>
+      <resources>
+         <resource>
+            <directory>src/main/resources</directory>
+            <filtering>true</filtering>
+         </resource>
+      </resources>
+      <plugins>
+         <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-resources-plugin</artifactId>
+            <executions>
+               <execution>
+                  <id>filter</id>
+                  <phase>generate-resources</phase>
+                  <goals>
+                     <goal>resources</goal>
+                  </goals>
+               </execution>
+            </executions>
+         </plugin>
+         <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>build-helper-maven-plugin</artifactId>
+            <executions>
+               <execution>
+                  <id>attach-artifacts</id>
+                  <phase>package</phase>
+                  <goals>
+                     <goal>attach-artifact</goal>
+                  </goals>
+                  <configuration>
+                     <artifacts>
+                        <artifact>
+                           <file>${project.build.directory}/classes/${features.file}</file>
+                           <type>xml</type>
+                           <classifier>features</classifier>
+                        </artifact>
+                     </artifacts>
+                  </configuration>
+               </execution>
+            </executions>
+         </plugin>
+         <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <version>${surefire.version}</version>
+            <configuration>
+              <systemPropertyVariables>
+                <karaf.distro.groupId>org.opendaylight.controller</karaf.distro.groupId>
+                <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId>
+                <karaf.distro.version>${karaf.empty.version}</karaf.distro.version>
+              </systemPropertyVariables>
+              <dependenciesToScan>
+               <dependency>org.opendaylight.yangtools:features-test</dependency>
+              </dependenciesToScan>
+            </configuration>
+          </plugin>
+      </plugins>
+   </build>
+   <scm>
+      <connection>scm:git:ssh://git.opendaylight.org:29418/${repoName}.git</connection>
+      <developerConnection>scm:git:ssh://git.opendaylight.org:29418/${repoName}.git</developerConnection>
+      <tag>HEAD</tag>
+      <url>https://git.opendaylight.org/gerrit/gitweb?p=${repoName}.git;a=summary</url>
+   </scm>
+</project>
diff --git a/opendaylight/archetypes/opendaylight-karaf-features/src/main/resources/archetype-resources/src/main/resources/features.xml b/opendaylight/archetypes/opendaylight-karaf-features/src/main/resources/archetype-resources/src/main/resources/features.xml
new file mode 100644 (file)
index 0000000..4a59657
--- /dev/null
@@ -0,0 +1,86 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Necessary TODO: Put your copyright statement here
+
+ 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
+-->
+<features name="odl-${repoName}-${symbol_dollar}{project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+    <!--
+        Necessary TODO: Please read the features guidelines:
+        https://wiki.opendaylight.org/view/Runtime:Karaf_Features_Guidelines#Feature_Best_Practices
+    -->
+    <!--
+    Necessary TODO: Add repo entries for the repositories of features you refer to
+        in this feature file but do not define here.
+        Examples:
+            <repository>mvn:org.opendaylight.yangtools/features-yangtools/0.6.2-SNAPSHOT/xml/features</repository>
+            <repository>mvn:org.opendaylight.controller/features-mdsal/1.1-SNAPSHOT/xml/features</repository>
+            <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin/0.0.3-SNAPSHOT/xml/features</repository>
+    -->
+    <feature name='odl-${repoName}-all' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${repoName} :: All'>
+        <!--
+            Necessary TODO:
+            List all of the user consumable features you define in this feature file here.
+            Generally you would *not* list individual bundles here, but only features defined in *this* file.
+            It is useful to list them in the same order they occur in the file.
+
+            Examples:
+            <feature version='${symbol_dollar}{project.version}'>odl-${repoName}-provider</feature>
+            <feature version='${symbol_dollar}{project.version}'>odl-${repoName}-model</feature>
+        -->
+    </feature>
+    <!--
+        Necessary TODO: Define your features.  It is useful to list then in order of dependency.  So if A depends on B, list A first.
+        When naming your features please be mindful of the guidelines:
+            https://wiki.opendaylight.org/view/Runtime:Karaf_Features_Guidelines
+        Particularly:
+            a) Prefixing names with 'odl-': https://wiki.opendaylight.org/view/Runtime:Karaf_Features_Guidelines#Feature_Naming
+            b) Descriptions: https://wiki.opendaylight.org/view/Runtime:Karaf_Features_Guidelines#Description
+            c) Avoid start-levels: https://wiki.opendaylight.org/view/Runtime:Karaf_Features_Guidelines#Avoid_start-levels
+
+        It's also nice to list inside a feature, first the features it needs, then the bundles it needs, then the configfiles.
+        Examples:
+
+        * Basic MD-SAL Provider
+        <feature name='odl-${repoName}-provider' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${repoName} :: Provider '>
+            <feature version='1.1-SNAPSHOT'>odl-mdsal-broker</feature>
+            <feature version='${symbol_dollar}{project.version}'>odl-${repoName}-model</feature>
+            <bundle>mvn:${groupId}/${repoName}-provider/${symbol_dollar}{project.version}</bundle>
+            ... whatever other bundles you need
+        </feature>
+
+        * Basic MD-SAL Model feature
+        <feature name='odl-${repoName}-model' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${repoName} :: Model'>
+            <feature version='0.6.2-SNAPSHOT'>odl-yangtools-binding</feature>
+            <feature version='0.6.2-SNAPSHOT'>odl-yangtools-models</feature>
+            <bundle>mvn:${groupId}/${repoName}-model/${symbol_dollar}{project.version}</bundle>
+            ... whatever other bundles you need
+        </feature>
+
+        * Config Subsystem example - the config file is your config subsystem configuration
+        <feature name='odl-${repoName}-provider' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${repoName} :: Provider'>
+            <feature version='1.1-SNAPSHOT'>odl-mdsal-broker</feature>
+            <bundle>mvn:${groupId}/${repoName}-provider/${symbol_dollar}{project.version}</bundle>
+            <configfile finalname="etc/opendaylight/karaf/80-${repoName}.xml">mvn:${groupId}/${repoName}-config/${symbol_dollar}{project.version}/xml/config</configfile>
+            ... whatever other bundles you need
+        </feature>
+
+        * Basic MD-SAL Provider that uses openflowplugin-flow-services (which brings along odl-mdsal-broker)
+        <feature name='odl-${repoName}-provider' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${repoName} :: Provider'>
+            <feature version='0.0.3-SNAPSHOT'>odl-openflowplugin-flow-services</feature>
+            <bundle>mvn:${groupId}/${repoName}-provider/${symbol_dollar}{project.version}</bundle>
+            ... whatever other bundles you need
+        </feature>
+
+    -->
+    <!-- Optional TODO: Remove TODO Comments -->
+
+</features>
diff --git a/opendaylight/archetypes/opendaylight-karaf-features/src/test/resources/projects/basic/archetype.properties b/opendaylight/archetypes/opendaylight-karaf-features/src/test/resources/projects/basic/archetype.properties
new file mode 100644 (file)
index 0000000..bab8cd2
--- /dev/null
@@ -0,0 +1,6 @@
+#Thu Aug 21 23:46:25 CDT 2014
+package=it.pkg
+version=0.1-SNAPSHOT
+groupId=archetype.it
+artifactId=basic
+repoName=foo
diff --git a/opendaylight/archetypes/opendaylight-karaf-features/src/test/resources/projects/basic/goal.txt b/opendaylight/archetypes/opendaylight-karaf-features/src/test/resources/projects/basic/goal.txt
new file mode 100644 (file)
index 0000000..e69de29
index 36af861e84826e109ed53e97fadee123b6056c18..cb597c10bd09fe4375053ced97449e25a3b68dc0 100644 (file)
@@ -6,9 +6,9 @@
   </prerequisites>
   <parent>
     <groupId>org.opendaylight.controller</groupId>
-    <artifactId>commons.parent</artifactId>
-    <version>1.0.1-SNAPSHOT</version>
-    <relativePath>../commons/parent</relativePath>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.2-SNAPSHOT</version>
+    <relativePath>../commons/opendaylight</relativePath>
   </parent>
   <scm>
     <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
@@ -39,5 +39,8 @@
   </distributionManagement>
   <modules>
     <module>odl-model-project</module>
+    <module>opendaylight-configfile-archetype</module>
+    <module>opendaylight-karaf-distro-archetype</module>
+    <module>opendaylight-karaf-features</module>
   </modules>
 </project>
index 1064afd82d53fcdcdf6714421b5702535a2d6180..2e953072681704e6d4b9b3d1251658d59da4f7f7 100644 (file)
     <clustering.test.version>0.4.2-SNAPSHOT</clustering.test.version>
     <commmons.northbound.version>0.4.2-SNAPSHOT</commmons.northbound.version>
     <!-- Third Party Versions -->
+    <codahale.metrics.version>3.0.1</codahale.metrics.version>
     <commons.catalina>7.0.32.v201211201336</commons.catalina>
     <commons.catalina.ha>7.0.32.v201211201952</commons.catalina.ha>
     <commons.catalina.tribes>7.0.32.v201211201952</commons.catalina.tribes>
-    <commons.checkstyle.version>0.0.3-SNAPSHOT</commons.checkstyle.version>
     <commons.coyote>7.0.32.v201211201952</commons.coyote>
     <commons.el>7.0.32.v201211081135</commons.el>
+    <commons.jasper>7.0.32.v201211201952</commons.jasper>
+    <commons.juli.version>7.0.32.v201211081135</commons.juli.version>
+    <commons.tomcat.api>7.0.32.v201211081135</commons.tomcat.api>
+    <commons.tomcat.util>7.0.32.v201211201952</commons.tomcat.util>
+
+    <commons.karaf.catalina>7.0.53.v201406061610</commons.karaf.catalina>
+    <commons.karaf.catalina.ha>7.0.53.v201406070630</commons.karaf.catalina.ha>
+    <commons.karaf.catalina.tribes>7.0.53.v201406070630</commons.karaf.catalina.tribes>
+    <commons.karaf.coyote>7.0.53.v201406070630</commons.karaf.coyote>
+    <commons.karaf.el>7.0.53.v201406060720</commons.karaf.el>
+    <commons.karaf.jasper>7.0.53.v201406070630</commons.karaf.jasper>
+    <commons.karaf.juli.version>7.0.53.v201406060720</commons.karaf.juli.version>
+    <commons.karaf.tomcat.api>7.0.53.v201406060720</commons.karaf.tomcat.api>
+    <commons.karaf.tomcat.util>7.0.53.v201406070630</commons.karaf.tomcat.util>
+
+    <commons.checkstyle.version>0.0.3-SNAPSHOT</commons.checkstyle.version>
     <commons.fileupload.version>1.2.2</commons.fileupload.version>
     <commons.httpclient.version>0.1.2-SNAPSHOT</commons.httpclient.version>
     <commons.io.version>2.4</commons.io.version>
-    <commons.jasper>7.0.32.v201211201952</commons.jasper>
-    <commons.juli.version>7.0.32.v201211081135</commons.juli.version>
     <commons.lang3.version>3.1</commons.lang3.version>
     <commons.logback_settings.version>0.0.2-SNAPSHOT</commons.logback_settings.version>
     <commons.net.version>3.0.1</commons.net.version>
@@ -57,8 +71,6 @@
     <commons.opendaylight.concepts.version>0.5.2-SNAPSHOT</commons.opendaylight.concepts.version>
     <commons.opendaylight.version>1.4.2-SNAPSHOT</commons.opendaylight.version>
     <commons.parent.version>1.0.2-SNAPSHOT</commons.parent.version>
-    <commons.tomcat.api>7.0.32.v201211081135</commons.tomcat.api>
-    <commons.tomcat.util>7.0.32.v201211201952</commons.tomcat.util>
     <compiler.version>2.3.2</compiler.version>
     <commons.httpclient.version>0.1.2-SNAPSHOT</commons.httpclient.version>
     <concepts.version>0.5.2-SNAPSHOT</concepts.version>
@@ -67,6 +79,7 @@
     <config.configfile.directory>etc/opendaylight/karaf</config.configfile.directory>
     <config.netty.configfile>00-netty.xml</config.netty.configfile>
     <config.mdsal.configfile>01-mdsal.xml</config.mdsal.configfile>
+    <config.xsql.configfile>04-xsql.xml</config.xsql.configfile>
     <config.netconf.client.configfile>01-netconf.xml</config.netconf.client.configfile>
     <config.toaster.configfile>03-toaster-sample.xml</config.toaster.configfile>
     <config.restconf.configfile>10-rest-connector.xml</config.restconf.configfile>
@@ -82,6 +95,7 @@
     <devices.web.version>0.4.2-SNAPSHOT</devices.web.version>
     <dummy-console.version>1.1.0-SNAPSHOT</dummy-console.version>
     <eclipse.persistence.version>2.5.0</eclipse.persistence.version>
+    <eclipse.jdt.core.compiler.batch.version>3.8.0.I20120518-2145</eclipse.jdt.core.compiler.batch.version>
     <!-- enforcer version -->
     <enforcer.version>1.3.1</enforcer.version>
     <enunciate.version>1.28</enunciate.version>
     <scala.version>2.10</scala.version>
     <scala.micro.version>4</scala.micro.version>
     <security.version>0.4.2-SNAPSHOT</security.version>
+    <karaf.security.version>0.4.2-SNAPSHOT</karaf.security.version>
     <shapeless.version>1.2.4</shapeless.version>
     <sitedeploy>dav:http://nexus.opendaylight.org/content/sites/site</sitedeploy>
     <sonar.branch>${user.name}-private-view</sonar.branch>
     <usermanager.implementation.version>0.4.2-SNAPSHOT</usermanager.implementation.version>
     <usermanager.northbound.version>0.0.2-SNAPSHOT</usermanager.northbound.version>
     <usermanager.version>0.4.2-SNAPSHOT</usermanager.version>
+    <nsf.version>0.4.2-SNAPSHOT</nsf.version>
     <web.version>0.4.2-SNAPSHOT</web.version>
     <xtend.dstdir>src/main/xtend-gen</xtend.dstdir>
     <yang-ext.version>2013.09.07.4-SNAPSHOT</yang-ext.version>
     <yang-jmx-generator.version>1.0.0-SNAPSHOT</yang-jmx-generator.version>
     <yangtools.version>0.6.2-SNAPSHOT</yangtools.version>
+      <sshd-core.version>0.12.0</sshd-core.version>
   </properties>
 
   <dependencyManagement>
         <artifactId>netconf-netty-util</artifactId>
         <version>${netconf.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.apache.sshd</groupId>
+        <artifactId>sshd-core</artifactId>
+        <version>${sshd-core.version}</version>
+      </dependency>
       <dependency>
         <groupId>ch.qos.logback</groupId>
         <artifactId>logback-classic</artifactId>
         <artifactId>logback-core</artifactId>
         <version>${logback.version}</version>
       </dependency>
+      <dependency>
+        <groupId>com.codahale.metrics</groupId>
+        <artifactId>metrics-core</artifactId>
+        <version>${codahale.metrics.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.codahale.metrics</groupId>
+        <artifactId>metrics-graphite</artifactId>
+        <version>${codahale.metrics.version}</version>
+      </dependency>
       <dependency>
         <groupId>com.fasterxml.jackson.core</groupId>
         <artifactId>jackson-annotations</artifactId>
         <artifactId>jersey-core</artifactId>
         <version>${jersey.version}</version>
       </dependency>
-
       <dependency>
         <groupId>com.sun.jersey</groupId>
         <artifactId>jersey-server</artifactId>
         <version>${jersey.version}</version>
       </dependency>
+      <dependency>
+        <groupId>com.sun.jersey</groupId>
+        <artifactId>jersey-servlet</artifactId>
+        <version>${jersey-servlet.version}</version>
+      </dependency>
 
       <dependency>
         <groupId>com.typesafe.akka</groupId>
         <artifactId>hosttracker.northbound</artifactId>
         <version>${hosttracker.northbound.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>hosttracker.shell</artifactId>
+        <version>${hosttracker.shell.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>hosttracker_new</artifactId>
         <artifactId>logging.bridge</artifactId>
         <version>${logging.bridge.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>dummy-console</artifactId>
+        <version>${dummy-console.version}</version>
+      </dependency>
 
       <!-- Netconf -->
       <dependency>
         <version>${netconf.version}</version>
         <type>test-jar</type>
       </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netconf-auth</artifactId>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netconf-usermanager</artifactId>
+            <version>${netconf.version}</version>
+        </dependency>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>netconf-ssh</artifactId>
         <artifactId>sal-connector-api</artifactId>
         <version>${mdsal.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-dom-xsql</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-dom-xsql-config</artifactId>
+        <version>${mdsal.version}</version>
+        <classifier>config</classifier>
+        <type>xml</type>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>sal-core-api</artifactId>
         <artifactId>security</artifactId>
         <version>${security.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>karaf-tomcat-security</artifactId>
+        <version>${karaf.security.version}</version>
+      </dependency>
 
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>topologymanager</artifactId>
         <version>${topologymanager.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>topologymanager.shell</artifactId>
+        <version>${topologymanager.shell.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>troubleshoot.web</artifactId>
         <artifactId>yang-data-composite-node</artifactId>
         <version>${yangtools.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>yang-data-codec-gson</artifactId>
+        <version>${yangtools.version}</version>
+      </dependency>
 
       <!-- yangtools dependencies -->
       <dependency>
         <type>xml</type>
         <scope>runtime</scope>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>features-base</artifactId>
+        <version>${commons.opendaylight.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>features-adsal</artifactId>
         <type>xml</type>
         <scope>runtime</scope>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>features-nsf</artifactId>
+        <version>${nsf.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>features-mdsal</artifactId>
index fe1012f443fc7824b1e2b8b3d3c4ed15ecbfb30d..ea87afa48dedddfe20ef5430aa60d25ecc594c1a 100644 (file)
@@ -47,10 +47,13 @@ final class ReconnectPromise<S extends ProtocolSession<?>, L extends SessionList
         pending = this.dispatcher.createClient(this.address, cs, b, new AbstractDispatcher.PipelineInitializer<S>() {
             @Override
             public void initializeChannel(final SocketChannel channel, final Promise<S> promise) {
-                initializer.initializeChannel(channel, promise);
-
                 // add closed channel handler
+                // This handler has to be added before initializer.initializeChannel is called
+                // Initializer might add some handlers using addFirst e.g. AsyncSshHandler and in that case
+                // closed channel handler is before the handler that invokes channel inactive event
                 channel.pipeline().addFirst(new ClosedChannelHandler(ReconnectPromise.this));
+
+                initializer.initializeChannel(channel, promise);
             }
         });
     }
@@ -88,6 +91,9 @@ final class ReconnectPromise<S extends ProtocolSession<?>, L extends SessionList
 
         @Override
         public void channelInactive(final ChannelHandlerContext ctx) throws Exception {
+            // Pass info about disconnect further and then reconnect
+            super.channelInactive(ctx);
+
             if (promise.isCancelled()) {
                 return;
             }
index 58a93a188b1886194ceed42845a16524126a0cd2..e145bd2db0de394d64492e64aeeeea5ce432bd8f 100644 (file)
       <groupId>org.osgi</groupId>
       <artifactId>org.osgi.core</artifactId>
     </dependency>
+      <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>mockito-configuration</artifactId>
+      </dependency>
   </dependencies>
 
   <build>
index 649b1eb4676e6ab7dfc2ef81f8b13d2b74753e15..7ce602ae49685600ec4d9a990465ce2ce69398b4 100644 (file)
@@ -39,8 +39,7 @@ public class JmxAttribute {
 
         JmxAttribute that = (JmxAttribute) o;
 
-        if (attributeName != null ? !attributeName.equals(that.attributeName)
-                : that.attributeName != null) {
+        if (!attributeName.equals(that.attributeName)) {
             return false;
         }
 
@@ -49,7 +48,7 @@ public class JmxAttribute {
 
     @Override
     public int hashCode() {
-        return attributeName != null ? attributeName.hashCode() : 0;
+        return attributeName.hashCode();
     }
 
     @Override
diff --git a/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/IdentityAttributeRefTest.java b/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/IdentityAttributeRefTest.java
new file mode 100644 (file)
index 0000000..6e8ece3
--- /dev/null
@@ -0,0 +1,71 @@
+package org.opendaylight.controller.config.api;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+
+import javax.management.*;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
+
+public class IdentityAttributeRefTest {
+
+    IdentityAttributeRef attr = new IdentityAttributeRef("attr");
+
+    @Test
+    public void testConstructor() throws Exception {
+        String param = new String("attr");
+        Assert.assertEquals(attr.getqNameOfIdentity(), param);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testConstructor2() throws Exception {
+        IdentityAttributeRef attr = new IdentityAttributeRef(null);
+    }
+
+    @Test
+    public void testHashCode() throws Exception {
+        Assert.assertEquals(attr.hashCode(), new String("attr").hashCode());
+    }
+
+    @Test
+    public void testEqual() throws Exception {
+        Assert.assertEquals(attr, attr);
+    }
+
+    @Test
+    public void testEqual2() throws Exception {
+        Assert.assertEquals(attr, new IdentityAttributeRef("attr"));
+    }
+
+    @Test
+    public void testNotEqual() throws Exception {
+        Assert.assertNotEquals(attr, new IdentityAttributeRef("different"));
+    }
+
+    @Test
+    public void testResolveIdentity() throws Exception {
+        DependencyResolver res = mock(DependencyResolver.class);
+        IdentityAttributeRef a = new IdentityAttributeRef("abcd");
+        doReturn(SubIdentity.class).when(res).resolveIdentity(a, Identity.class);
+        a.resolveIdentity(res, Identity.class);
+        verify(res).resolveIdentity(a, Identity.class);
+    }
+
+    @Test
+    public void testValidateIdentity() throws Exception {
+        DependencyResolver res = mock(DependencyResolver.class);
+        JmxAttribute jmxAttr = new JmxAttribute("abc");
+        doNothing().when(res).validateIdentity(attr, Identity.class, jmxAttr);
+        attr.validateIdentity(res, Identity.class, jmxAttr);
+        verify(res).validateIdentity(attr, Identity.class, jmxAttr);
+    }
+
+    static class Identity extends BaseIdentity {}
+
+    static class SubIdentity extends Identity {}
+}
diff --git a/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/JmxAttributeTest.java b/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/JmxAttributeTest.java
new file mode 100644 (file)
index 0000000..39609a0
--- /dev/null
@@ -0,0 +1,53 @@
+package org.opendaylight.controller.config.api;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class JmxAttributeTest {
+
+    @Test
+    public void testJmxAttribute() throws Exception {
+        JmxAttribute attr = new JmxAttribute("test");
+        assertEquals("test", attr.getAttributeName());
+    }
+
+    @Test
+    public void testToString() throws Exception {
+        JmxAttribute attr = new JmxAttribute("test");
+        assertEquals(attr.toString(), new JmxAttribute("test").toString());
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testJmxAttributeInvalid() throws Exception {
+        JmxAttribute attr = new JmxAttribute(null);
+    }
+
+    @Test
+    public void testJmxAttributeEqual() throws Exception {
+        JmxAttribute a1 = new JmxAttribute("test_string");
+        JmxAttribute a2 = new JmxAttribute("test_string");
+        assertEquals(a1, a2);
+    }
+
+    @Test
+    public void testJmxAttributeNotEqual() throws Exception {
+        JmxAttribute a1 = new JmxAttribute("test_string");
+        JmxAttribute a2 = new JmxAttribute("different");
+        assertNotEquals(a1, a2);
+    }
+
+    @Test
+    public void testJmxAttributeEqual2() throws Exception {
+        JmxAttribute a1 = new JmxAttribute("test_string");
+        assertNotNull(a1);
+    }
+
+    @Test
+    public void testJmxAttributeHashCode() throws Exception {
+        JmxAttribute a1 = new JmxAttribute("test_string");
+        assertEquals(a1.hashCode(), new String("test_string").hashCode());
+    }
+}
index 7a057bbccb9985262698cc1d48a7f34bc63a329a..f6e7dfb505ed486fb80cb8a5bc7f6799536abed0 100644 (file)
@@ -1,47 +1,87 @@
 package org.opendaylight.controller.config.api;
 
-import static org.junit.Assert.assertEquals;
+import java.nio.file.AccessDeniedException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 import com.google.common.collect.Lists;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
+import javax.management.Query;
+
+import static org.junit.Assert.*;
+
 public class JmxAttributeValidationExceptionTest {
 
     private JmxAttribute jmxAttribute = new JmxAttribute("attr1");
-    private JmxAttribute jmxAttribute2 = new JmxAttribute("attr2");
 
-    @Before
-    public void setUp() throws Exception {
+    @Test
+    public void testJmxAttributeValidationExceptionElement() throws Exception {
+        JmxAttribute attributeName = new JmxAttribute("attr_name");
+        JmxAttributeValidationException e = new JmxAttributeValidationException(attributeName);
+        assertThat(e.getAttributeNames(), CoreMatchers.hasItem(attributeName));
+    }
 
+    @Test
+    public void testJmxAttributeValidationExceptionList() throws Exception {
+        List attributeNames = new ArrayList<JmxAttribute>();
+        attributeNames.add(new JmxAttribute("att1"));
+        attributeNames.add(new JmxAttribute("att2"));
+        attributeNames.add(new JmxAttribute("att3"));
+        JmxAttributeValidationException e = new JmxAttributeValidationException(attributeNames);
+        assertEquals(e.getAttributeNames(), attributeNames);
     }
 
     @Test
-    public void testGetAttributeNames() throws Exception {
+    public void testJmxAttributeValidationExceptionList2() throws Exception {
+        List attributeNames = new ArrayList<JmxAttribute>();
+        attributeNames.add(new JmxAttribute("att1"));
+        attributeNames.add(new JmxAttribute("att2"));
+        attributeNames.add(new JmxAttribute("att3"));
+        JmxAttributeValidationException e = new JmxAttributeValidationException("exception str",
+                new AccessDeniedException(""), attributeNames);
+        assertEquals(e.getAttributeNames(), attributeNames);
+    }
 
+    @Test
+    public void testJmxAttributeValidationExceptionJmxElement() throws Exception {
+        JmxAttribute attributeName = new JmxAttribute("attr_name");
+        JmxAttributeValidationException e = new JmxAttributeValidationException("exception str",
+                new AccessDeniedException(""), attributeName);
+        assertEquals(e.getAttributeNames(), Arrays.asList(attributeName));
     }
 
     @Test
     public void testCheckNotNull() throws Exception {
         try {
-            JmxAttributeValidationException.checkNotNull(false, "message", jmxAttribute);
+            JmxAttributeValidationException.checkNotNull(false, jmxAttribute);
         } catch (JmxAttributeValidationException e) {
             assertJmxEx(e, jmxAttribute.getAttributeName() + " " + "message", jmxAttribute);
         }
     }
 
     @Test
-    public void testWrap() throws Exception {
+    public void testCheckCondition() throws Exception {
+        JmxAttributeValidationException.checkCondition(true, "message", jmxAttribute);
+    }
 
+    @Test(expected = JmxAttributeValidationException.class)
+    public void testJmxAttributeValidationException() throws Exception {
+        JmxAttributeValidationException.wrap(new Exception("tmp"), jmxAttribute);
     }
 
-    @Test
-    public void testCheckCondition() throws Exception {
-        try {
-            JmxAttributeValidationException.checkCondition(false, "message", jmxAttribute);
-        } catch (JmxAttributeValidationException e) {
-            assertJmxEx(e, jmxAttribute.getAttributeName() + " " + "message", jmxAttribute);
-        }
+    @Test(expected = JmxAttributeValidationException.class)
+    public void testJmxAttributeValidationException2() throws Exception {
+        JmxAttributeValidationException.wrap(new Exception("tmp"), "message", jmxAttribute);
+    }
+
+    @Test(expected = JmxAttributeValidationException.class)
+    public void testCheckConditionFalse() throws Exception {
+        JmxAttributeValidationException.checkCondition(false, "message", jmxAttribute);
     }
 
     private void assertJmxEx(JmxAttributeValidationException e, String message, JmxAttribute... attrNames) {
diff --git a/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/ModuleIdentifierTest.java b/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/ModuleIdentifierTest.java
new file mode 100644 (file)
index 0000000..c0e584a
--- /dev/null
@@ -0,0 +1,63 @@
+package org.opendaylight.controller.config.api;
+
+import junit.framework.Assert;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+
+public class ModuleIdentifierTest {
+    String fact = new String("factory");
+    String inst = new String("instance");
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testConstructor() throws Exception {
+        ModuleIdentifier m = new ModuleIdentifier(null, "instance");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testConstructor2() throws Exception {
+        ModuleIdentifier m = new ModuleIdentifier("name", null);
+    }
+
+    @Test
+    public void testEquals() throws Exception {
+
+        ModuleIdentifier m1 = new ModuleIdentifier(fact, inst);
+        assertEquals(m1, new ModuleIdentifier(fact, inst));
+    }
+
+    @Test
+    public void testEquals2() throws Exception {
+        assertNotEquals(new ModuleIdentifier(fact, inst), null);
+    }
+
+    @Test
+    public void testEquals3() throws Exception {
+        assertNotEquals(new ModuleIdentifier(fact, inst), new ModuleIdentifier(fact, "i"));
+    }
+
+    @Test
+    public void testEquals4() throws Exception {
+        assertNotEquals(new ModuleIdentifier(fact, inst), new ModuleIdentifier("f", inst));
+    }
+
+    @Test
+    public void testEquals5() throws Exception {
+        ModuleIdentifier m1 = new ModuleIdentifier(fact, inst);
+        assertEquals(m1, m1);
+    }
+
+    @Test
+    public void testHashCode() throws Exception {
+        int hash = new ModuleIdentifier(fact, inst).hashCode();
+        assertEquals(hash, new ModuleIdentifier("factory", "instance").hashCode());
+    }
+
+    @Test
+    public void testToString() throws Exception {
+        assertEquals( new ModuleIdentifier("factory", "instance").toString(),
+                new ModuleIdentifier("factory", "instance").toString());
+    }
+}
index 1809e458606bd928d7e68ffe83bef287e1736be2..30712c966dfdb1c5b61109f043ce552039b1d084 100644 (file)
@@ -3,11 +3,14 @@ package org.opendaylight.controller.config.api;
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertThat;
 import static org.junit.matchers.JUnitMatchers.containsString;
 
 import com.google.common.collect.Lists;
 import java.util.Map;
+
+import org.junit.Assert;
 import org.junit.Test;
 
 public class ValidationExceptionTest {
@@ -51,4 +54,107 @@ public class ValidationExceptionTest {
         }
         fail("Duplicate exception should have failed");
     }
+
+    @Test
+    public void testGetTrace() throws Exception {
+        ValidationException.ExceptionMessageWithStackTrace exp = new ValidationException.ExceptionMessageWithStackTrace();
+        exp.setTrace("trace");
+        Assert.assertEquals(exp.getTrace(), "trace");
+    }
+
+    @Test
+    public void testSetMessage() throws Exception {
+        ValidationException.ExceptionMessageWithStackTrace exp = new ValidationException.ExceptionMessageWithStackTrace();
+        exp.setMessage("message");
+        Assert.assertEquals(exp.getMessage(), "message");
+    }
+
+    @Test
+    public void testHashCode() throws Exception {
+        ValidationException.ExceptionMessageWithStackTrace exp = new ValidationException.ExceptionMessageWithStackTrace();
+        Assert.assertEquals(exp.hashCode(), new ValidationException.ExceptionMessageWithStackTrace().hashCode());
+    }
+
+    @Test
+    public void testExceptionMessageWithStackTraceConstructor() throws Exception {
+        ValidationException.ExceptionMessageWithStackTrace exp =
+                new ValidationException.ExceptionMessageWithStackTrace("string1", "string2");
+        Assert.assertEquals(exp, exp);
+    }
+
+    @Test
+    public void testExceptionMessageWithStackTraceConstructor2() throws Exception {
+        ValidationException.ExceptionMessageWithStackTrace exp =
+                new ValidationException.ExceptionMessageWithStackTrace("string1", "string2");
+        Assert.assertNotEquals(exp, null);
+    }
+
+    @Test
+    public void testExceptionMessageWithStackTraceConstructor3() throws Exception {
+        ValidationException.ExceptionMessageWithStackTrace exp =
+                new ValidationException.ExceptionMessageWithStackTrace("string1", "string2");
+        Assert.assertNotEquals(exp, new Exception());
+    }
+
+    @Test
+    public void testExceptionMessageWithStackTraceConstructor4() throws Exception {
+        ValidationException.ExceptionMessageWithStackTrace exp =
+                new ValidationException.ExceptionMessageWithStackTrace("string1", "string2");
+        Assert.assertEquals(exp, new ValidationException.ExceptionMessageWithStackTrace("string1", "string2"));
+    }
+
+    @Test
+    public void testEqual() throws Exception {
+        ValidationException.ExceptionMessageWithStackTrace exp =
+                new ValidationException.ExceptionMessageWithStackTrace("string1", "string2");
+        ValidationException.ExceptionMessageWithStackTrace exp2 =
+                new ValidationException.ExceptionMessageWithStackTrace(null, "string2");
+        Assert.assertNotEquals(exp, exp2);
+    }
+
+    @Test
+    public void testEqual2() throws Exception {
+        ValidationException.ExceptionMessageWithStackTrace exp =
+                new ValidationException.ExceptionMessageWithStackTrace("string1", "string2");
+        ValidationException.ExceptionMessageWithStackTrace exp2 =
+                new ValidationException.ExceptionMessageWithStackTrace("different", "string2");
+        Assert.assertNotEquals(exp, exp2);
+    }
+
+
+    @Test
+    public void testEqual3() throws Exception {
+        ValidationException.ExceptionMessageWithStackTrace exp =
+                new ValidationException.ExceptionMessageWithStackTrace("string1", "string2");
+        ValidationException.ExceptionMessageWithStackTrace exp2 =
+                new ValidationException.ExceptionMessageWithStackTrace("string1", null);
+        Assert.assertNotEquals(exp, exp2);
+    }
+
+    @Test
+    public void testEqual4() throws Exception {
+        ValidationException.ExceptionMessageWithStackTrace exp =
+                new ValidationException.ExceptionMessageWithStackTrace("string1", "string2");
+        ValidationException.ExceptionMessageWithStackTrace exp2 =
+                new ValidationException.ExceptionMessageWithStackTrace("string1", "different");
+        Assert.assertNotEquals(exp, exp2);
+    }
+
+    @Test
+    public void testEqual5() throws Exception {
+        ValidationException.ExceptionMessageWithStackTrace exp =
+                new ValidationException.ExceptionMessageWithStackTrace(null, "string2");
+        ValidationException.ExceptionMessageWithStackTrace exp2 =
+                new ValidationException.ExceptionMessageWithStackTrace("string1", "string2");
+        Assert.assertNotEquals(exp, exp2);
+    }
+
+    @Test
+    public void testEqual6() throws Exception {
+        ValidationException.ExceptionMessageWithStackTrace exp =
+                new ValidationException.ExceptionMessageWithStackTrace("string1", null);
+        ValidationException.ExceptionMessageWithStackTrace exp2 =
+                new ValidationException.ExceptionMessageWithStackTrace("string1", "string2");
+        Assert.assertNotEquals(exp, exp2);
+    }
 }
\ No newline at end of file
diff --git a/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/jmx/CommitStatusTest.java b/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/jmx/CommitStatusTest.java
new file mode 100644 (file)
index 0000000..36ebc9d
--- /dev/null
@@ -0,0 +1,63 @@
+package org.opendaylight.controller.config.api.jmx;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.management.ObjectName;
+import java.util.ArrayList;
+import java.util.List;
+
+public class CommitStatusTest {
+    List newInst = new ArrayList<ObjectName>();
+    List reusedInst = new ArrayList<ObjectName>();
+    List recreatedInst = new ArrayList<ObjectName>();
+
+    @Before
+    public void setUp() throws Exception {
+        newInst.add(new ObjectName("domain: key1 = value1 , key2 = value2"));
+        reusedInst.add(new ObjectName("o2: key = val"));
+        recreatedInst.add(new ObjectName("o3: key = k"));
+    }
+    @Test
+    public void testCommitStatus() throws Exception {
+        CommitStatus status = new CommitStatus(newInst, reusedInst, recreatedInst);
+        Assert.assertEquals(status.getNewInstances(), newInst);
+        Assert.assertEquals(status.getRecreatedInstances(), recreatedInst);
+        Assert.assertEquals(status.getReusedInstances(), reusedInst);
+    }
+
+    @Test
+    public void testEqual() throws Exception {
+        CommitStatus status = new CommitStatus(newInst, reusedInst, recreatedInst);
+        Assert.assertEquals(status, new CommitStatus(newInst, reusedInst, recreatedInst));
+        Assert.assertEquals(status.toString(), new CommitStatus(newInst, reusedInst, recreatedInst).toString());
+        Assert.assertEquals(status, status);
+    }
+
+    @Test
+    public void testHashCode() throws Exception {
+        CommitStatus status = new CommitStatus(newInst, reusedInst, recreatedInst);
+        Assert.assertEquals(status.hashCode(), new CommitStatus(newInst, reusedInst, recreatedInst).hashCode());
+    }
+
+    @Test
+    public void testNotEqual() throws Exception {
+        List newInst2 = new ArrayList<ObjectName>();
+        List reusedInst2 = new ArrayList<ObjectName>();
+        List recreatedInst2 = new ArrayList<ObjectName>();
+
+        newInst2.add(new ObjectName("first: key1 = value1"));
+        reusedInst2.add(new ObjectName("second: key = val"));
+        recreatedInst2.add(new ObjectName("third: key = k"));
+
+        CommitStatus status = new CommitStatus(newInst, reusedInst, recreatedInst);
+        Assert.assertNotEquals(status, null);
+        Assert.assertNotEquals(status, new Object());
+        Assert.assertNotEquals(status, new CommitStatus(newInst2, reusedInst, recreatedInst));
+        Assert.assertNotEquals(status, new CommitStatus(newInst, reusedInst2, recreatedInst));
+        Assert.assertNotEquals(status, new CommitStatus(newInst, reusedInst, recreatedInst2));
+
+        CommitStatus status2 = new CommitStatus(newInst, reusedInst, recreatedInst);
+    }
+}
diff --git a/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/jmx/ConfigRegistryConstantsTest.java b/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/jmx/ConfigRegistryConstantsTest.java
new file mode 100644 (file)
index 0000000..e19211d
--- /dev/null
@@ -0,0 +1,13 @@
+package org.opendaylight.controller.config.api.jmx;
+
+
+import org.junit.Test;
+import org.opendaylight.controller.config.api.jmx.constants.ConfigRegistryConstants;
+
+public class ConfigRegistryConstantsTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testCreateON() throws Exception {
+        ConfigRegistryConstants.createON("test.<:", "asd", "asd");
+    }
+}
index d3d8469dfba7b0409a0c7738be2b43ca76f4a57b..02c1c4b9815ff55843e1abb74e99b0b529d48349 100644 (file)
@@ -14,6 +14,8 @@ import static org.junit.Assert.assertTrue;
 
 import com.google.common.base.Throwables;
 import com.google.common.collect.Maps;
+
+import java.util.HashMap;
 import java.util.Map;
 import javax.management.ObjectName;
 import junit.framework.Assert;
@@ -159,4 +161,15 @@ public class ObjectNameUtilTest {
 
         fail(test + " should have failed on " + ex);
     }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testCreateON() throws Exception {
+        ObjectNameUtil.createON(">}+!#");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testCreateON2() throws Exception {
+        Map<String, String> map = new HashMap<>();
+        ObjectNameUtil.createON(">}+!#", map);
+    }
 }
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/RefreshingSCPModuleInfoRegistryTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/RefreshingSCPModuleInfoRegistryTest.java
new file mode 100644 (file)
index 0000000..79391d4
--- /dev/null
@@ -0,0 +1,46 @@
+package org.opendaylight.controller.config.manager.impl.osgi;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.config.manager.impl.osgi.mapping.RefreshingSCPModuleInfoRegistry;
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
+import org.opendaylight.yangtools.sal.binding.generator.api.ModuleInfoRegistry;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+import java.util.*;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+public class RefreshingSCPModuleInfoRegistryTest {
+    @Test
+    public void testConstructor() throws Exception {
+        ModuleInfoRegistry reg = mock(ModuleInfoRegistry.class);
+        SchemaContextProvider prov = mock(SchemaContextProvider.class);
+        doReturn("string").when(prov).toString();
+
+        BundleContext ctxt = mock(BundleContext.class);
+        Dictionary dict = new Hashtable();
+        ServiceRegistration servReg = mock(ServiceRegistration.class);
+        doReturn(servReg).when(ctxt).registerService(Mockito.any(Class.class), Mockito.any(SchemaContextProvider.class), Mockito.any(Dictionary.class));
+        doReturn(servReg).when(ctxt).registerService(Mockito.anyString(), Mockito.any(Object.class), Mockito.any(Dictionary.class));
+        RefreshingSCPModuleInfoRegistry scpreg = new RefreshingSCPModuleInfoRegistry(reg, prov, ctxt);
+
+        YangModuleInfo modInfo = mock(YangModuleInfo.class);
+        doNothing().when(servReg).setProperties(null);
+        doNothing().when(servReg).unregister();
+        doReturn("").when(modInfo).toString();
+        ObjectRegistration<YangModuleInfo> ymi = mock(ObjectRegistration.class);
+        doReturn(ymi).when(reg).registerModuleInfo(modInfo);
+
+        scpreg.registerModuleInfo(modInfo);
+        scpreg.close();
+
+        Mockito.verify(servReg, Mockito.times(1)).setProperties(null);
+        Mockito.verify(servReg, Mockito.times(1)).unregister();
+    }
+}
index dd73675070c95ce2bf3365bf8589843322ddf53d..de7621110e21637b93d1b3531fbe579470b2e6f1 100644 (file)
@@ -44,13 +44,13 @@ import org.slf4j.LoggerFactory;
  *
  */
 
-public class ConfigurationService implements IConfigurationService, ICacheUpdateAware<ConfigurationEvent, String> {
+public class ConfigurationService implements IConfigurationService, ICacheUpdateAware<String, String> {
     private static final Logger logger = LoggerFactory
             .getLogger(ConfigurationService.class);
     public static final String SAVE_EVENT_CACHE = "config.event.save";
     private static final String ROOT = GlobalConstants.STARTUPHOME.toString();
     private IClusterGlobalServices clusterServices;
-    private ConcurrentMap <ConfigurationEvent, String> configEvent;
+    private ConcurrentMap<String, String> configEvent;
     private Set<IConfigurationAware> configurationAwareList = Collections
             .synchronizedSet(new HashSet<IConfigurationAware>());
     private ObjectReader objReader;
@@ -105,7 +105,7 @@ public class ConfigurationService implements IConfigurationService, ICacheUpdate
     @Override
     public Status saveConfigurations() {
         if (configEvent != null) {
-            configEvent.put(ConfigurationEvent.SAVE, "");
+            configEvent.put(ConfigurationEvent.SAVE.toString(), "");
         }
         return saveConfigurationsInternal();
     }
@@ -183,7 +183,7 @@ public class ConfigurationService implements IConfigurationService, ICacheUpdate
     }
 
     @Override
-    public void entryCreated(ConfigurationEvent key, String cacheName,
+    public void entryCreated(String key, String cacheName,
             boolean originLocal) {
         if (originLocal) {
             return;
@@ -191,18 +191,18 @@ public class ConfigurationService implements IConfigurationService, ICacheUpdate
     }
 
     @Override
-    public void entryUpdated(ConfigurationEvent key, String new_value,
+    public void entryUpdated(String key, String new_value,
             String cacheName, boolean originLocal) {
         if (originLocal) {
             return;
         }
-        if (key == ConfigurationEvent.SAVE) {
+        if (key.equals(ConfigurationEvent.SAVE.toString())) {
             saveConfigurationsInternal();
         }
     }
 
     @Override
-    public void entryDeleted(ConfigurationEvent key, String cacheName,
+    public void entryDeleted(String key, String cacheName,
             boolean originLocal) {
         if (originLocal) {
             return;
@@ -230,7 +230,7 @@ public class ConfigurationService implements IConfigurationService, ICacheUpdate
             logger.error("uninitialized clusterServices, can't retrieve cache");
             return;
         }
-        configEvent = (ConcurrentMap<ConfigurationEvent, String>) this.clusterServices.getCache(SAVE_EVENT_CACHE);
+        configEvent = (ConcurrentMap<String, String>) this.clusterServices.getCache(SAVE_EVENT_CACHE);
         if (configEvent == null) {
             logger.error("Failed to retrieve configuration Cache");
         }
index a36d4cc6d78588df5828b175de0facd9fe666f33..dcab1f63fbc1104e4225b0351455fb3de0db1d70 100644 (file)
@@ -47,11 +47,12 @@ import org.slf4j.LoggerFactory;
  */
 
 public class ContainerConfigurationService implements IConfigurationContainerService,
-        IConfigurationAware, ICacheUpdateAware<ConfigurationEvent, String> {
+        IConfigurationAware,
+        ICacheUpdateAware<String, String> {
     public static final String CONTAINER_SAVE_EVENT_CACHE = "config.container.event.save";
     private static final Logger logger = LoggerFactory.getLogger(ContainerConfigurationService.class);
     private IClusterContainerServices clusterServices;
-    private ConcurrentMap <ConfigurationEvent, String> containerConfigEvent;
+    private ConcurrentMap<String, String> containerConfigEvent;
     // Directory which contains the startup files for this container
     private String root;
     private Set<IConfigurationContainerAware> configurationAwareList = Collections
@@ -142,12 +143,12 @@ public class ContainerConfigurationService implements IConfigurationContainerSer
 
     @Override
     public Status saveConfigurations() {
-        containerConfigEvent.put(ConfigurationEvent.SAVE, "");
+        containerConfigEvent.put(ConfigurationEvent.SAVE.toString(), "");
         return saveConfiguration();
     }
 
     @Override
-    public void entryCreated(ConfigurationEvent key, String cacheName,
+    public void entryCreated(String key, String cacheName,
             boolean originLocal) {
         if (originLocal) {
             return;
@@ -155,19 +156,19 @@ public class ContainerConfigurationService implements IConfigurationContainerSer
     }
 
     @Override
-    public void entryUpdated(ConfigurationEvent key, String new_value,
+    public void entryUpdated(String key, String new_value,
             String cacheName, boolean originLocal) {
         if (originLocal) {
             return;
         }
         logger.debug("Processing {} event", key);
-        if (key == ConfigurationEvent.SAVE) {
+        if (key.equals(ConfigurationEvent.SAVE.toString())) {
             saveConfiguration();
         }
     }
 
     @Override
-    public void entryDeleted(ConfigurationEvent key, String cacheName,
+    public void entryDeleted(String key, String cacheName,
             boolean originLocal) {
         if (originLocal) {
             return;
@@ -195,7 +196,8 @@ public class ContainerConfigurationService implements IConfigurationContainerSer
             logger.error("uninitialized clusterServices, can't retrieve cache");
             return;
         }
-        containerConfigEvent = (ConcurrentMap<ConfigurationEvent, String>) this.clusterServices.getCache(CONTAINER_SAVE_EVENT_CACHE);
+        containerConfigEvent =
+                (ConcurrentMap<String, String>) this.clusterServices.getCache(CONTAINER_SAVE_EVENT_CACHE);
         if (containerConfigEvent == null) {
             logger.error("Failed to retrieve configuration Cache");
         }
index f6f923e0d26720bda6960c0acf21954d0f6721f5..fbcd0a4c779ed4203a4f153f67604016f43085e6 100644 (file)
@@ -48,9 +48,8 @@
       <Host name="localhost" appBase=""
             unpackWARs="false" autoDeploy="false"
             deployOnStartup="false" createDirs="false">
-<!--         <Realm className="org.opendaylight.controller.security.ControllerCustomRealm" />
+            <Realm className="org.opendaylight.controller.karafsecurity.ControllerCustomRealm" />
             <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
- -->
             <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
                         prefix="web_access_log_" suffix=".txt" resolveHosts="false"
                         rotatable="true" fileDateFormat="yyyy-MM"
index e9a6992521250d612c1924e4f0fa46548f63d741..c2ac77a5d6f57b3ba24a581a700dead2fcc8a377 100644 (file)
@@ -1,6 +1,20 @@
 # Extra packages to import from the boot class loader
 org.osgi.framework.system.packages.extra=org.apache.karaf.branding,sun.reflect,sun.reflect.misc,sun.misc,sun.nio.ch
 
+# Override the config.properties to remove
+# ${services-${karaf.framework}}
+# This is to work around:
+# https://issues.apache.org/jira/browse/KARAF-3092
+# Which should be fixed in karaf 3.0.2
+# Which is not as of today (2014-08-24) released.
+# Since it is biting folks, we need to fix it here
+# Please remove this when we shift to karaf 3.0.2
+org.osgi.framework.system.capabilities= \
+ ${eecap-${java.specification.version}}, \
+ service-reference;effective:=active;objectClass=org.osgi.service.packageadmin.PackageAdmin, \
+ service-reference;effective:=active;objectClass=org.osgi.service.startlevel.StartLevel, \
+ service-reference;effective:=active;objectClass=org.osgi.service.url.URLHandlers
+
 # https://bugs.eclipse.org/bugs/show_bug.cgi?id=325578
 # Extend the framework to avoid the resources to be presented with
 # a URL of type bundleresource: but to be presented as file:
@@ -105,3 +119,4 @@ java.util.logging.config.file=configuration/tomcat-logging.properties
 
 #Hosttracker hostsdb key scheme setting
 hosttracker.keyscheme=IP
+
index 5cbe412b2b0af28da537a95af2ace0766df8e120..cdc592428f9d685ab0e715a6e9f762e5a743cc83 100644 (file)
           down with testing... ie, no broken feature repos
     -->
 
+    <!-- AD-SAL Related Features -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>features-base</artifactId>
+      <classifier>features</classifier>
+      <type>xml</type>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>features-adsal</artifactId>
+      <classifier>features</classifier>
+      <type>xml</type>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>features-nsf</artifactId>
+      <classifier>features</classifier>
+      <type>xml</type>
+    </dependency>
     <!-- MD-SAL Related Features -->
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
                         <fileset dir="${project.build.directory}/assembly/bin">
                           <include name="karaf"/>
                           <include name="instance"/>
+                          <include name="start"/>
+                          <include name="stop"/>
+                          <include name="status"/>
+                          <include name="client"/>
+                          <include name="shell"/>
                         </fileset>
                     </chmod>
                   </tasks>
index d70bf4641192c488d043e2ba7ff4bc41279b1375..4ae35c905f122a6691072df720882ac88b68ddee 100644 (file)
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>netconf-ssh</artifactId>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>netconf-auth</artifactId>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>netconf-usermanager</artifactId>
+        </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>netconf-tcp</artifactId>
           <groupId>org.opendaylight.controller.thirdparty</groupId>
           <artifactId>ganymed</artifactId>
         </dependency>
+        <dependency>
+          <groupId>org.apache.sshd</groupId>
+          <artifactId>sshd-core</artifactId>
+        </dependency>
         <dependency>
           <groupId>org.opendaylight.yangtools</groupId>
           <artifactId>binding-generator-api</artifactId>
           <groupId>org.opendaylight.yangtools</groupId>
           <artifactId>yang-parser-impl</artifactId>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>yang-data-codec-gson</artifactId>
+        </dependency>
         <dependency>
           <groupId>org.opendaylight.yangtools</groupId>
           <artifactId>yang-data-composite-node</artifactId>
diff --git a/opendaylight/karaf-tomcat-security/pom.xml b/opendaylight/karaf-tomcat-security/pom.xml
new file mode 100644 (file)
index 0000000..817e0fa
--- /dev/null
@@ -0,0 +1,49 @@
+<?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>commons.opendaylight</artifactId>
+    <version>1.4.2-SNAPSHOT</version>
+    <relativePath>../commons/opendaylight</relativePath>
+  </parent>
+
+  <artifactId>karaf-tomcat-security</artifactId>
+  <version>0.4.2-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+  <dependencies>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>org.apache.catalina</artifactId>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Fragment-Host>org.apache.catalina</Fragment-Host>
+            <Import-Package>org.slf4j,
+              javax.servlet,
+              org.apache.catalina,
+              org.apache.catalina.connector,
+              org.apache.catalina.valves,
+              org.apache.catalina.realm
+            </Import-Package>
+            <Export-Package>org.opendaylight.controller.karafsecurity</Export-Package>
+          </instructions>
+          <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+        </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:Main</url>
+  </scm>
+</project>
diff --git a/opendaylight/karaf-tomcat-security/src/main/java/org/opendaylight/controller/karafsecurity/ControllerCustomRealm.java b/opendaylight/karaf-tomcat-security/src/main/java/org/opendaylight/controller/karafsecurity/ControllerCustomRealm.java
new file mode 100644 (file)
index 0000000..316067c
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.karafsecurity;
+
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.catalina.realm.GenericPrincipal;
+import org.apache.catalina.realm.RealmBase;
+
+public class ControllerCustomRealm  extends RealmBase {
+
+    private static final String name = "ControllerCustomRealm";
+
+    @Override
+    protected String getName() {
+        return name;
+    }
+
+    @Override
+    protected String getPassword(String username) {
+        return "admin";
+    }
+
+    @Override
+    protected Principal getPrincipal(String username) {
+        List<String> controllerRoles = new ArrayList<String>();
+        controllerRoles.add("System-Admin");
+        return new GenericPrincipal(username, "", controllerRoles);
+    }
+
+    @Override
+    public Principal authenticate(String username, String credentials) {
+        return this.getPrincipal(username);
+    }
+}
index be087abdb41099b9a5d8505ed20f7ac59624f531..b873f8a9fe060ff93c0279fbef0ad3cf59d0ab84 100644 (file)
@@ -14,6 +14,7 @@ import java.math.BigInteger;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
+import java.util.regex.Pattern;
 import org.opendaylight.controller.sal.common.util.Arguments;
 import org.opendaylight.controller.sal.core.AdvertisedBandwidth;
 import org.opendaylight.controller.sal.core.Bandwidth;
@@ -80,6 +81,12 @@ public final class NodeMapping {
 
     private final static Class<NodeConnector> NODECONNECTOR_CLASS = NodeConnector.class;
 
+    private final static Pattern COLON_NUMBERS_EOL = Pattern.compile(":[0-9]+$");
+
+    private final static Pattern NUMBERS_ONLY = Pattern.compile("[0-9]+");
+
+    private final static Pattern ALL_CHARS_TO_COLON = Pattern.compile("^.*:");
+
     private NodeMapping() {
         throw new UnsupportedOperationException("Utility class. Instantiation is not allowed.");
     }
@@ -182,15 +189,16 @@ public final class NodeMapping {
             return org.opendaylight.controller.sal.core.NodeConnector.SPECIALNODECONNECTORID;
         }
 
-        String nodeConnectorIdStripped = nodeConnectorId.getValue().replaceFirst("^.*:", "");
-        if (nodeConnectorIdStripped.matches("[0-9]+")) {
+        String nodeConnectorIdStripped = ALL_CHARS_TO_COLON.matcher(nodeConnectorId.getValue()).replaceFirst("");
+
+        if (NUMBERS_ONLY.matcher(nodeConnectorIdStripped).matches()) {
             Short nodeConnectorIdVal = null;
             try {
                 nodeConnectorIdVal = Short.valueOf(nodeConnectorIdStripped);
+                return nodeConnectorIdVal;
             } catch (NumberFormatException e) {
-                LOG.warn("nodeConnectorId not supported (short): {}", nodeConnectorIdStripped, e);
+                LOG.warn("nodeConnectorId not supported (long): {}", nodeConnectorIdStripped, e);
             }
-            return nodeConnectorIdVal;
         }
         return nodeConnectorIdStripped;
     }
@@ -198,7 +206,7 @@ public final class NodeMapping {
     public static NodeId toAdNodeId(final NodeConnectorId nodeConnectorId) {
         NodeId nodeId = null;
         if (nodeConnectorId != null) {
-            nodeId = new NodeId(nodeConnectorId.getValue().replaceFirst(":[0-9]+$", ""));
+            nodeId = new NodeId(COLON_NUMBERS_EOL.matcher(nodeConnectorId.getValue()).replaceFirst(""));
         }
         return nodeId;
     }
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractChangeListener.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractChangeListener.java
deleted file mode 100644 (file)
index 130c096..0000000
+++ /dev/null
@@ -1,173 +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.frm;
-
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * AbstractChangeListner implemented basic {@link AsyncDataChangeEvent} processing for
- * flow node subDataObject (flows, groups and meters).
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- */
-public abstract class AbstractChangeListener implements DataChangeListener {
-
-    private final static Logger LOG = LoggerFactory.getLogger(AbstractChangeListener.class);
-
-    private final AtomicLong txNum = new AtomicLong();
-    private String transactionId;
-
-    @Override
-    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
-        this.transactionId = this.newTransactionIdentifier().toString();
-        /* All DataObjects for create */
-        final Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> createdEntries =
-                changeEvent.getCreatedData().entrySet();
-        /* All DataObjects for updates - init HashSet */
-        final Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updatedEntries = new HashSet<>();
-        /* Filtered DataObject for update processing only */
-        Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updateConfigEntrySet =
-                changeEvent.getUpdatedData().entrySet();
-        updatedEntries.addAll(updateConfigEntrySet);
-        updatedEntries.removeAll(createdEntries);
-        /* All DataObjects for remove */
-        final Set<InstanceIdentifier<? extends DataObject>> removeEntriesInstanceIdentifiers =
-                changeEvent.getRemovedPaths();
-        /* Create DataObject processing (send to device) */
-        for (final Entry<InstanceIdentifier<? extends DataObject>, DataObject> createdEntry : createdEntries) {
-            InstanceIdentifier<? extends DataObject> entryKey = createdEntry.getKey();
-            DataObject entryValue = createdEntry.getValue();
-            if (preconditionForChange(entryKey, entryValue, null)) {
-                this.add(entryKey, entryValue);
-            }
-        }
-
-        for (final Entry<InstanceIdentifier<?>, DataObject> updatedEntrie : updatedEntries) {
-            Map<InstanceIdentifier<? extends DataObject>, DataObject> origConfigData =
-                    changeEvent.getOriginalData();
-
-            InstanceIdentifier<? extends Object> entryKey = updatedEntrie.getKey();
-            final DataObject original = origConfigData.get(entryKey);
-            final DataObject updated = updatedEntrie.getValue();
-            if (preconditionForChange(entryKey, original, updated)) {
-                this.update(entryKey, original, updated);
-            }
-        }
-
-        for (final InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers) {
-            Map<InstanceIdentifier<? extends DataObject>, DataObject> origConfigData =
-                    changeEvent.getOriginalData();
-
-            final DataObject removeValue = origConfigData.get(instanceId);
-            if (preconditionForChange(instanceId, removeValue, null)) {
-                this.remove(instanceId, removeValue);
-            }
-        }
-    }
-
-    /**
-     * Method returns generated transaction ID, which is unique for
-     * every transaction. ID is composite from prefix ("DOM") and unique number.
-     *
-     * @return String transactionID
-     */
-    public String getTransactionId() {
-        return this.transactionId;
-    }
-
-    private Object newTransactionIdentifier() {
-        return "DOM-" + txNum.getAndIncrement();
-    }
-
-    /**
-     * Method check all local preconditions for apply relevant changes.
-     *
-     * @param InstanceIdentifier identifier - the whole path to DataObject
-     * @param DataObject original - original DataObject (for update)
-     *                              or relevant DataObject (add/delete operations)
-     * @param DataObject update - changed DataObject (contain updates)
-     *                              or should be null for (add/delete operations)
-     *
-     * @return boolean - applicable
-     */
-    protected abstract boolean preconditionForChange(
-            final InstanceIdentifier<? extends DataObject> identifier,
-            final DataObject original, final DataObject update);
-
-    /**
-     * Method checks the node data path in DataStore/OPERATIONAL because
-     * without the Node Identifier in DataStore/OPERATIONAL, device
-     * is not connected and device pre-configuration is allowed only.
-     *
-     * @param InstanceIdentifier identifier - could be whole path to DataObject,
-     *            but parent Node.class InstanceIdentifier is used for a check only
-     *
-     * @return boolean - is the Node available in DataStore/OPERATIONAL (is connected)
-     */
-    protected boolean isNodeAvailable(final InstanceIdentifier<? extends DataObject> identifier,
-            final ReadOnlyTransaction readTrans) {
-        final InstanceIdentifier<Node> nodeInstanceId = identifier.firstIdentifierOf(Node.class);
-        try {
-            return readTrans.read(LogicalDatastoreType.OPERATIONAL, nodeInstanceId).get().isPresent();
-        }
-        catch (InterruptedException | ExecutionException e) {
-            LOG.error("Unexpected exception by reading Node ".concat(nodeInstanceId.toString()), e);
-            return false;
-        }
-        finally {
-            readTrans.close();
-        }
-    }
-
-    /**
-     * Method removes DataObject which is identified by InstanceIdentifier
-     * from device.
-     *
-     * @param InstanceIdentifier identifier - the whole path to DataObject
-     * @param DataObject remove - DataObject for removing
-     */
-    protected abstract void remove(final InstanceIdentifier<? extends DataObject> identifier,
-            final DataObject remove);
-
-    /**
-     * Method updates the original DataObject to the update DataObject
-     * in device. Both are identified by same InstanceIdentifier
-     *
-     * @param InstanceIdentifier identifier - the whole path to DataObject
-     * @param DataObject original - original DataObject (for update)
-     * @param DataObject update - changed DataObject (contain updates)
-     */
-    protected abstract void update(final InstanceIdentifier<? extends DataObject> identifier,
-            final DataObject original, final DataObject update);
-
-    /**
-     * Method adds the DataObject which is identified by InstanceIdentifier
-     * to device.
-     *
-     * @param InstanceIdentifier identifier - the whole path to new DataObject
-     * @param DataObject add - new DataObject
-     */
-    protected abstract void add(final InstanceIdentifier<? extends DataObject> identifier,
-            final DataObject add);
-}
index c75c644c008dfe0aad4849a98a13a80f053a6e80..9878d16e57bca8450f6217455d58fa3ef2e0a33f 100644 (file)
@@ -7,10 +7,7 @@
  */
 package org.opendaylight.controller.frm;
 
-import org.opendaylight.controller.frm.flow.FlowProvider;
-import org.opendaylight.controller.frm.group.GroupProvider;
-import org.opendaylight.controller.frm.meter.MeterProvider;
-import org.opendaylight.controller.frm.reconil.FlowNodeReconcilProvider;
+import org.opendaylight.controller.frm.impl.ForwardingRulesManagerImpl;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
@@ -21,8 +18,7 @@ import org.slf4j.LoggerFactory;
 /**
  * Forwarding Rules Manager Activator
  *
- * Activator manages all Providers ({@link FlowProvider}, {@link GroupProvider},
- * {@link MeterProvider} and the {@link FlowNodeReconcilProvider}).
+ * Activator {@link ForwardingRulesManager}.
  * It registers all listeners (DataChangeEvent, ReconcilNotification)
  * in the Session Initialization phase.
  *
@@ -33,56 +29,33 @@ public class FRMActivator extends AbstractBindingAwareProvider {
 
     private final static Logger LOG = LoggerFactory.getLogger(FRMActivator.class);
 
-    private final FlowProvider flowProvider;
-    private final GroupProvider groupProvider;
-    private final MeterProvider meterProvider;
-    private final FlowNodeReconcilProvider flowNodeReconcilProvider;
-
-    public FRMActivator() {
-        this.flowProvider = new FlowProvider();
-        this.groupProvider = new GroupProvider();
-        this.meterProvider = new MeterProvider();
-        this.flowNodeReconcilProvider = new FlowNodeReconcilProvider();
-    }
+    private ForwardingRulesManager  manager;
 
     @Override
-    public void onSessionInitiated(final ProviderContext session) {
+    public void onSessionInitiated(ProviderContext session) {
         LOG.info("FRMActivator initialization.");
-        /* Flow */
         try {
-            final DataBroker flowSalService = session.getSALService(DataBroker.class);
-            this.flowProvider.init(flowSalService);
-            this.flowProvider.start(session);
-            /* Group */
-            final DataBroker groupSalService = session.getSALService(DataBroker.class);
-            this.groupProvider.init(groupSalService);
-            this.groupProvider.start(session);
-            /* Meter */
-            final DataBroker meterSalService = session.getSALService(DataBroker.class);
-            this.meterProvider.init(meterSalService);
-            this.meterProvider.start(session);
-            /* FlowNode Reconciliation */
-            final DataBroker dbs = session.getSALService(DataBroker.class);
-            this.flowNodeReconcilProvider.init(dbs);
-            this.flowNodeReconcilProvider.start(session);
-
-            LOG.info("FRMActivator started successfully");
-        } catch (Exception e) {
-            String errMsg = "Unexpected error by starting FRMActivator";
-            LOG.error(errMsg, e);
-            throw new IllegalStateException(errMsg, e);
+            final DataBroker dataBroker = session.getSALService(DataBroker.class);
+            this.manager = new ForwardingRulesManagerImpl(dataBroker, session);
+            this.manager.start();
+            LOG.info("FRMActivator initialization successfull.");
+        }
+        catch (Exception e) {
+            LOG.error("Unexpected error by FRM initialization!", e);
+            this.stopImpl(null);
         }
     }
 
     @Override
     protected void stopImpl(final BundleContext context) {
-        try {
-            this.flowProvider.close();
-            this.groupProvider.close();
-            this.meterProvider.close();
-            this.flowNodeReconcilProvider.close();
-        } catch (Exception e) {
-            LOG.error("Unexpected error by stopping FRMActivator", e);
+        if (manager != null) {
+            try {
+                manager.close();
+            } catch (Exception e) {
+                LOG.error("Unexpected error by stopping FRMActivator", e);
+            }
+            manager = null;
+            LOG.info("FRMActivator stopped.");
         }
     }
   }
\ No newline at end of file
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FlowCookieProducer.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FlowCookieProducer.java
deleted file mode 100644 (file)
index d7b54e8..0000000
+++ /dev/null
@@ -1,79 +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.frm;
-
-import java.math.BigInteger;
-
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.AtomicLongMap;
-
-/**
- * forwardingrules-manager
- * org.opendaylight.controller.frm
- *
- * Singleton FlowCookieProducer contains a FlowCookie generator which is generated unique
- * flowCookie identifier for every flow in same Table. That could help with quick
- * identification of flow statistic because DataStore/CONFIGURATION could contains
- * a lot of flows with same flowCookie. So we are replacing original flowCookie
- * with unique and we are building final FlowCookieMap in DataStore/OPERATIONAL
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- * Created: Jun 13, 2014
- */
-public enum FlowCookieProducer {
-
-    INSTANCE;
-
-    /* Flow_Cookie_Key and Flow_Ids MapHolder */
-    private static final AtomicLongMap<InstanceIdentifier<Table>> cookieKeys = AtomicLongMap.create();
-
-    /**
-     * Method returns the unique cookie for a node table.
-     * Flow Cookie Key signs List<FlowId> for a right flow statistic identification
-     * in the DataStore/operational.
-     * We need a List<FlowId> because system doesn't guarantee unique mapping
-     * from flow_cookie to flow_id. REST Operations doesn't used FRM yet, so
-     * cookie from user input could have a user input flow ID and an alien system ID
-     * which is generated by system.
-     *
-     * @param InstanceIdentifier<Table> tableIdentifier
-     * @return unique BigInteger flowCookie for a node table
-     */
-    public BigInteger getNewCookie(final InstanceIdentifier<Table> tableIdentifier) {
-        FlowCookieProducer.validationTableIdentifier(tableIdentifier);
-        if ( cookieKeys.containsKey(tableIdentifier)) {
-            /* new identifier always starts from ONE because
-             * ZERO is reserved for the NO_COOKIES flows */
-            return BigInteger.valueOf(cookieKeys.addAndGet(tableIdentifier, 1L));
-        } else {
-            return BigInteger.valueOf(cookieKeys.incrementAndGet(tableIdentifier));
-        }
-    }
-
-    /**
-     * Method cleans the node table flow_cookie_key for the disconnected Node.
-     *
-     * @param InstanceIdentifier<Table> tableIdentifier
-     */
-    public void clean(final InstanceIdentifier<Table> tableIdentifier) {
-        FlowCookieProducer.validationTableIdentifier(tableIdentifier);
-        cookieKeys.remove(tableIdentifier);
-    }
-
-    /*
-     * Help the TableIdentifer input validation method
-     */
-    private static void validationTableIdentifier(final InstanceIdentifier<Table> tableIdent) {
-        Preconditions.checkArgument(tableIdent != null, "Input validation exception: TableIdentifier can not be null !");
-    }
-}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FlowNodeReconciliation.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FlowNodeReconciliation.java
new file mode 100644 (file)
index 0000000..fb3178d
--- /dev/null
@@ -0,0 +1,59 @@
+/**
+ * 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.frm;
+
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * forwardingrules-manager
+ * org.opendaylight.controller.frm
+ *
+ * FlowNodeReconciliation
+ * It represent Reconciliation functionality for every new device.
+ * So we have to read all possible pre-configured Flows, Meters and Groups from
+ * Config/DS and add all to new device.
+ * New device is represented by new {@link org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode}
+ * in Operational/DS. So we have to add listener for Wildcarded path in base data change scope.
+ *
+ * WildCarded InstanceIdentifier:
+ * {@code
+ *
+ * InstanceIdentifier.create(Nodes.class).child(Node.class).augmentation(FlowCapableNode.class)
+ *
+ * }
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ * Created: Aug 26, 2014
+ */
+public interface FlowNodeReconciliation extends DataChangeListener, AutoCloseable {
+
+    /**
+     * Method contains Node registration to {@link ForwardingRulesManager} functionality
+     * as a prevention to use a validation check to the Operational/DS for identify
+     * pre-configure transaction and serious device commit in every transaction.
+     *
+     * Second part of functionality is own reconciliation pre-configure
+     * Flows, Meters and Groups.
+     *
+     * @param connectedNode - {@link org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier} to new Node
+     */
+    void flowNodeConnected(InstanceIdentifier<FlowCapableNode> connectedNode);
+
+    /**
+     * Method contains functionality for registered Node {@FlowCapableNode} removing
+     * from {@Link ForwardingRulesManager}
+     *
+     * @param disconnectedNode - {@link org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier} to removed Node
+     */
+    void flowNodeDisconnected(InstanceIdentifier<FlowCapableNode> disconnectedNode);
+}
+
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/ForwardingRulesCommiter.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/ForwardingRulesCommiter.java
new file mode 100644 (file)
index 0000000..2228785
--- /dev/null
@@ -0,0 +1,64 @@
+/**
+ * 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.frm;
+
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * forwardingrules-manager
+ * org.opendaylight.controller.frm
+ *
+ * ForwardingRulesCommiter
+ * It represent a contract between DataStore DataChangeEvent and relevant
+ * SalRpcService for device. Every implementation has to be registered for
+ * Configurational/DS tree path.
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ * Created: Aug 25, 2014
+ */
+public interface ForwardingRulesCommiter <D extends DataObject> extends AutoCloseable, DataChangeListener {
+
+    /**
+     * Method removes DataObject which is identified by InstanceIdentifier
+     * from device.
+     *
+     * @param InstanceIdentifier identifier - the whole path to DataObject
+     * @param DataObject remove - DataObject for removing
+     * @param InstanceIdentifier<FlowCapableNode> parent Node InstanceIdentifier
+     */
+    void remove(InstanceIdentifier<D> identifier, D del,
+            InstanceIdentifier<FlowCapableNode> nodeIdent);
+
+    /**
+     * Method updates the original DataObject to the update DataObject
+     * in device. Both are identified by same InstanceIdentifier
+     *
+     * @param InstanceIdentifier identifier - the whole path to DataObject
+     * @param DataObject original - original DataObject (for update)
+     * @param DataObject update - changed DataObject (contain updates)
+     */
+    void update(InstanceIdentifier<D> identifier, D original, D update,
+            InstanceIdentifier<FlowCapableNode> nodeIdent);
+
+    /**
+     * Method adds the DataObject which is identified by InstanceIdentifier
+     * to device.
+     *
+     * @param InstanceIdentifier identifier - the whole path to new DataObject
+     * @param DataObject add - new DataObject
+     */
+    void add(InstanceIdentifier<D> identifier, D add,
+            InstanceIdentifier<FlowCapableNode> nodeIdent);
+
+}
+
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/ForwardingRulesManager.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/ForwardingRulesManager.java
new file mode 100644 (file)
index 0000000..504c108
--- /dev/null
@@ -0,0 +1,125 @@
+/**
+ * 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.frm;
+
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * forwardingrules-manager
+ * org.opendaylight.controller.frm
+ *
+ * ForwardingRulesManager
+ * It represent a central point for whole modul. Implementation
+ * Flow Provider registers the link FlowChangeListener} and it holds all needed
+ * services for link FlowChangeListener}.
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ * Created: Aug 25, 2014
+ */
+public interface ForwardingRulesManager extends AutoCloseable {
+
+    public void start();
+
+    /**
+     * Method returns information :
+     * "is Node with send InstanceIdentifier connected"?
+     *
+     * @param InstanceIdentifier<FlowCapableNode> ident - the key of the node
+     * @return boolean - is device connected
+     */
+    public boolean isNodeActive(InstanceIdentifier<FlowCapableNode> ident);
+
+    /**
+     * Method add new {@link FlowCapableNode} to active Node Holder.
+     * ActiveNodeHolder prevent unnecessary Operational/DS read for identify
+     * pre-configure and serious Configure/DS transactions.
+     *
+     * @param InstanceIdentifier<FlowCapableNode> ident - the key of the node
+     */
+    public void registrateNewNode(InstanceIdentifier<FlowCapableNode> ident);
+
+    /**
+     * Method remove disconnected {@link FlowCapableNode} from active Node
+     * Holder. And all next flows or groups or meters will stay in Config/DS
+     * only.
+     *
+     * @param InstanceIdentifier<FlowCapableNode> ident - the key of the node
+     */
+    public void unregistrateNode(InstanceIdentifier<FlowCapableNode> ident);
+
+    /**
+     * Method returns generated transaction ID, which is unique for
+     * every transaction. ID is composite from prefix ("DOM") and unique number.
+     *
+     * @return String transactionID for RPC transaction identification
+     */
+    public String getNewTransactionId();
+
+    /**
+     * Method returns Read Transacion. It is need for Node reconciliation only.
+     *
+     * @return ReadOnlyTransaction
+     */
+    public ReadOnlyTransaction getReadTranaction();
+
+    /**
+     * Flow RPC service
+     *
+     * @return
+     */
+    public SalFlowService getSalFlowService();
+
+    /**
+     * Group RPC service
+     *
+     * @return
+     */
+    public SalGroupService getSalGroupService();
+
+    /**
+     * Meter RPC service
+     *
+     * @return
+     */
+    public SalMeterService getSalMeterService();
+
+    /**
+     * Content definition method and prevent code duplicity in Reconcil
+     * @return ForwardingRulesCommiter<Flow>
+     */
+    public ForwardingRulesCommiter<Flow> getFlowCommiter();
+
+    /**
+     * Content definition method and prevent code duplicity in Reconcil
+     * @return ForwardingRulesCommiter<Group>
+     */
+    public ForwardingRulesCommiter<Group> getGroupCommiter();
+
+    /**
+     * Content definition method and prevent code duplicity
+     * @return ForwardingRulesCommiter<Meter>
+     */
+    public ForwardingRulesCommiter<Meter> getMeterCommiter();
+
+    /**
+     * Content definition method
+     * @return FlowNodeReconciliation
+     */
+    public FlowNodeReconciliation getFlowNodeReconciliation();
+}
+
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowChangeListener.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowChangeListener.java
deleted file mode 100644 (file)
index c10b0da..0000000
+++ /dev/null
@@ -1,126 +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.frm.flow;
-
-import java.math.BigInteger;
-
-import org.opendaylight.controller.frm.AbstractChangeListener;
-import org.opendaylight.controller.frm.FlowCookieProducer;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-
-/**
- * Flow Change Listener
- *  add, update and remove {@link Flow} processing from {@link org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent}.
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- */
-public class FlowChangeListener extends AbstractChangeListener {
-
-    private static final Logger LOG = LoggerFactory.getLogger(FlowChangeListener.class);
-
-    private final FlowProvider provider;
-
-    public FlowChangeListener (final FlowProvider provider) {
-        this.provider = Preconditions.checkNotNull(provider, "FlowProvider can not be null !");
-    }
-
-    @Override
-    protected void remove(final InstanceIdentifier<? extends DataObject> identifier,
-                          final DataObject removeDataObj) {
-
-        final Flow flow = ((Flow) removeDataObj);
-        final InstanceIdentifier<Table> tableIdent = identifier.firstIdentifierOf(Table.class);
-        final InstanceIdentifier<Node> nodeIdent = identifier.firstIdentifierOf(Node.class);
-        final RemoveFlowInputBuilder builder = new RemoveFlowInputBuilder(flow);
-
-        // use empty cookie mask in order to delete flow even with generated cookie
-        builder.setCookieMask(new FlowCookie(BigInteger.ZERO));
-
-        builder.setFlowRef(new FlowRef(identifier));
-        builder.setNode(new NodeRef(nodeIdent));
-        builder.setFlowTable(new FlowTableRef(tableIdent));
-
-        Uri uri = new Uri(this.getTransactionId());
-        builder.setTransactionUri(uri);
-        this.provider.getSalFlowService().removeFlow(builder.build());
-        LOG.debug("Transaction {} - Removed Flow has removed flow: {}", new Object[]{uri, removeDataObj});
-    }
-
-    @Override
-    protected void update(final InstanceIdentifier<? extends DataObject> identifier,
-                          final DataObject original, final DataObject update) {
-
-        final Flow originalFlow = ((Flow) original);
-        final Flow updatedFlow = ((Flow) update);
-        final InstanceIdentifier<Node> nodeIdent = identifier.firstIdentifierOf(Node.class);
-        final UpdateFlowInputBuilder builder = new UpdateFlowInputBuilder();
-
-        builder.setNode(new NodeRef(nodeIdent));
-        builder.setFlowRef(new FlowRef(identifier));
-
-        Uri uri = new Uri(this.getTransactionId());
-        builder.setTransactionUri(uri);
-
-        builder.setUpdatedFlow((new UpdatedFlowBuilder(updatedFlow)).build());
-        builder.setOriginalFlow((new OriginalFlowBuilder(originalFlow)).build());
-
-        this.provider.getSalFlowService().updateFlow(builder.build());
-        LOG.debug("Transaction {} - Update Flow has updated flow {} with {}", new Object[]{uri, original, update});
-    }
-
-    @Override
-    protected void add(final InstanceIdentifier<? extends DataObject> identifier,
-                       final DataObject addDataObj) {
-
-        final Flow flow = ((Flow) addDataObj);
-        final InstanceIdentifier<Table> tableIdent = identifier.firstIdentifierOf(Table.class);
-        final NodeRef nodeRef = new NodeRef(identifier.firstIdentifierOf(Node.class));
-        final FlowCookie flowCookie = new FlowCookie(FlowCookieProducer.INSTANCE.getNewCookie(tableIdent));
-        final AddFlowInputBuilder builder = new AddFlowInputBuilder(flow);
-
-        builder.setNode(nodeRef);
-        builder.setFlowRef(new FlowRef(identifier));
-        builder.setFlowTable(new FlowTableRef(tableIdent));
-        builder.setCookie( flowCookie );
-
-        Uri uri = new Uri(this.getTransactionId());
-        builder.setTransactionUri(uri);
-        this.provider.getSalFlowService().addFlow(builder.build());
-        LOG.debug("Transaction {} - Add Flow has added flow: {}", new Object[]{uri, addDataObj});
-    }
-
-    @Override
-    protected boolean preconditionForChange(final InstanceIdentifier<? extends DataObject> identifier,
-            final DataObject dataObj, final DataObject update) {
-
-        final ReadOnlyTransaction trans = this.provider.getDataService().newReadOnlyTransaction();
-        return update != null
-                ? (dataObj instanceof Flow && update instanceof Flow && isNodeAvailable(identifier, trans))
-                : (dataObj instanceof Flow && isNodeAvailable(identifier, trans));
-    }
-}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowProvider.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowProvider.java
deleted file mode 100644 (file)
index 8c248fa..0000000
+++ /dev/null
@@ -1,107 +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.frm.flow;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-
-/**
- * Flow Provider registers the {@link FlowChangeListener} and it holds all needed
- * services for {@link FlowChangeListener}.
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- */
-public class FlowProvider implements AutoCloseable {
-
-    private static final Logger LOG = LoggerFactory.getLogger(FlowProvider.class);
-
-    private SalFlowService salFlowService;
-    private DataBroker dataService;
-
-    /* DataChangeListener */
-    private DataChangeListener flowDataChangeListener;
-    private ListenerRegistration<DataChangeListener> flowDataChangeListenerRegistration;
-
-    /**
-     * Provider Initialization Phase.
-     *
-     * @param DataProviderService dataService
-     */
-    public void init (final DataBroker dataService) {
-        LOG.info("FRM Flow Config Provider initialization.");
-        this.dataService = Preconditions.checkNotNull(dataService, "DataProviderService can not be null !");
-    }
-
-    /**
-     * Listener Registration Phase
-     *
-     * @param RpcConsumerRegistry rpcRegistry
-     */
-    public void start(final RpcConsumerRegistry rpcRegistry) {
-        Preconditions.checkArgument(rpcRegistry != null, "RpcConsumerRegistry can not be null !");
-
-        this.salFlowService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalFlowService.class),
-                "RPC SalFlowService not found.");
-
-        /* Build Path */
-        InstanceIdentifier<Flow> flowIdentifier = InstanceIdentifier.create(Nodes.class)
-                .child(Node.class).augmentation(FlowCapableNode.class).child(Table.class).child(Flow.class);
-
-        /* DataChangeListener registration */
-        this.flowDataChangeListener = new FlowChangeListener(FlowProvider.this);
-        this.flowDataChangeListenerRegistration =
-                this.dataService.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
-                        flowIdentifier, flowDataChangeListener, DataChangeScope.SUBTREE);
-
-        LOG.info("FRM Flow Config Provider started.");
-    }
-
-    @Override
-    public void close() {
-        LOG.info("FRM Flow Config Provider stopped.");
-        if (flowDataChangeListenerRegistration != null) {
-            try {
-                flowDataChangeListenerRegistration.close();
-            } catch (Exception e) {
-                String errMsg = "Error by stop FRM Flow Config Provider.";
-                LOG.error(errMsg, e);
-                throw new IllegalStateException(errMsg, e);
-            } finally {
-                flowDataChangeListenerRegistration = null;
-            }
-        }
-    }
-
-    public DataChangeListener getFlowDataChangeListener() {
-        return flowDataChangeListener;
-    }
-
-    public SalFlowService getSalFlowService() {
-        return salFlowService;
-    }
-
-    public DataBroker getDataService() {
-        return dataService;
-    }
-}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupChangeListener.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupChangeListener.java
deleted file mode 100644 (file)
index 9b03eaa..0000000
+++ /dev/null
@@ -1,111 +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.frm.group;
-
-import org.opendaylight.controller.frm.AbstractChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroupBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-
-/**
- * Group Change Listener
- *  add, update and remove {@link Group} processing from {@link org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent}.
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- */
-public class GroupChangeListener extends AbstractChangeListener {
-
-    private static final Logger LOG = LoggerFactory.getLogger(GroupChangeListener.class);
-
-    private final GroupProvider provider;
-
-    public GroupChangeListener(final GroupProvider provider) {
-        this.provider = Preconditions.checkNotNull(provider, "GroupProvider can not be null !");
-    }
-
-    @Override
-    protected void remove(final InstanceIdentifier<? extends DataObject> identifier,
-                          final DataObject removeDataObj) {
-
-        final Group group = ((Group) removeDataObj);
-        final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
-        final RemoveGroupInputBuilder builder = new RemoveGroupInputBuilder(group);
-
-        builder.setNode(new NodeRef(nodeInstanceId));
-        builder.setGroupRef(new GroupRef(identifier));
-
-        Uri uri = new Uri(this.getTransactionId());
-        builder.setTransactionUri(uri);
-        this.provider.getSalGroupService().removeGroup(builder.build());
-        LOG.debug("Transaction {} - Remove Group has removed group: {}", new Object[]{uri, removeDataObj});
-    }
-
-    @Override
-    protected void update(final InstanceIdentifier<? extends DataObject> identifier,
-                          final DataObject original, final DataObject update) {
-
-        final Group originalGroup = ((Group) original);
-        final Group updatedGroup = ((Group) update);
-        final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
-        final UpdateGroupInputBuilder builder = new UpdateGroupInputBuilder();
-
-        builder.setNode(new NodeRef(nodeInstanceId));
-        builder.setGroupRef(new GroupRef(identifier));
-
-        Uri uri = new Uri(this.getTransactionId());
-        builder.setTransactionUri(uri);
-
-        builder.setUpdatedGroup((new UpdatedGroupBuilder(updatedGroup)).build());
-        builder.setOriginalGroup((new OriginalGroupBuilder(originalGroup)).build());
-
-        this.provider.getSalGroupService().updateGroup(builder.build());
-        LOG.debug("Transaction {} - Update Group has updated group {} with group {}", new Object[]{uri, original, update});
-    }
-
-    @Override
-    protected void add(final InstanceIdentifier<? extends DataObject> identifier,
-                       final DataObject addDataObj) {
-
-        final Group group = ((Group) addDataObj);
-        final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
-        final AddGroupInputBuilder builder = new AddGroupInputBuilder(group);
-
-        builder.setNode(new NodeRef(nodeInstanceId));
-        builder.setGroupRef(new GroupRef(identifier));
-
-        Uri uri = new Uri(this.getTransactionId());
-        builder.setTransactionUri(uri);
-        this.provider.getSalGroupService().addGroup(builder.build());
-        LOG.debug("Transaction {} - Add Group has added group: {}", new Object[]{uri, addDataObj});
-    }
-
-    @Override
-    protected boolean preconditionForChange(final InstanceIdentifier<? extends DataObject> identifier,
-            final DataObject dataObj, final DataObject update) {
-
-        final ReadOnlyTransaction trans = this.provider.getDataService().newReadOnlyTransaction();
-        return update != null
-                ? (dataObj instanceof Group && update instanceof Group && isNodeAvailable(identifier, trans))
-                : (dataObj instanceof Group && isNodeAvailable(identifier, trans));
-    }
-}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupProvider.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupProvider.java
deleted file mode 100644 (file)
index a999242..0000000
+++ /dev/null
@@ -1,105 +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.frm.group;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-
-/**
- * Group Provider registers the {@link GroupChangeListener} and it holds all needed
- * services for {@link GroupChangeListener}.
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- */
-public class GroupProvider implements AutoCloseable {
-
-    private static final Logger LOG = LoggerFactory.getLogger(GroupProvider.class);
-
-    private SalGroupService salGroupService;
-    private DataBroker dataService;
-
-    /* DataChangeListener */
-    private DataChangeListener groupDataChangeListener;
-    private ListenerRegistration<DataChangeListener> groupDataChangeListenerRegistration;
-
-    /**
-     * Provider Initialization Phase.
-     *
-     * @param DataProviderService dataService
-     */
-    public void init (final DataBroker dataService) {
-        LOG.info("FRM Group Config Provider initialization.");
-        this.dataService = Preconditions.checkNotNull(dataService, "DataService can not be null !");
-    }
-
-    /**
-     * Listener Registration Phase
-     *
-     * @param RpcConsumerRegistry rpcRegistry
-     */
-    public void start(final RpcConsumerRegistry rpcRegistry) {
-        Preconditions.checkArgument(rpcRegistry != null, "RpcConsumerRegistry can not be null !");
-
-        this.salGroupService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalGroupService.class),
-                "RPC SalGroupService not found.");
-
-        /* Build Path */
-        InstanceIdentifier<Group> groupIdentifier = InstanceIdentifier.create(Nodes.class)
-                .child(Node.class).augmentation(FlowCapableNode.class).child(Group.class);
-
-        /* DataChangeListener registration */
-        this.groupDataChangeListener = new GroupChangeListener(GroupProvider.this);
-        this.groupDataChangeListenerRegistration = this.dataService.registerDataChangeListener(
-                LogicalDatastoreType.CONFIGURATION, groupIdentifier, groupDataChangeListener, DataChangeScope.SUBTREE);
-
-        LOG.info("FRM Group Config Provider started.");
-    }
-
-    @Override
-    public void close() {
-        LOG.info("FRM Group Config Provider stopped.");
-        if (groupDataChangeListenerRegistration != null) {
-            try {
-                groupDataChangeListenerRegistration.close();
-            } catch (Exception e) {
-                String errMsg = "Error by stop FRM Group Config Provider.";
-                LOG.error(errMsg, e);
-                throw new IllegalStateException(errMsg, e);
-            } finally {
-                groupDataChangeListenerRegistration = null;
-            }
-        }
-    }
-
-    public DataChangeListener getGroupDataChangeListener() {
-        return groupDataChangeListener;
-    }
-
-    public SalGroupService getSalGroupService() {
-        return salGroupService;
-    }
-
-    public DataBroker getDataService() {
-        return dataService;
-    }
-}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/AbstractListeningCommiter.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/AbstractListeningCommiter.java
new file mode 100644 (file)
index 0000000..ec49e61
--- /dev/null
@@ -0,0 +1,134 @@
+/**
+ * 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.frm.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.frm.ForwardingRulesCommiter;
+import org.opendaylight.controller.frm.ForwardingRulesManager;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * AbstractChangeListner implemented basic {@link AsyncDataChangeEvent} processing for
+ * flow node subDataObject (flows, groups and meters).
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ */
+public abstract class AbstractListeningCommiter <T extends DataObject> implements ForwardingRulesCommiter<T> {
+
+    protected ForwardingRulesManager provider;
+
+    protected final Class<T> clazz;
+
+    public AbstractListeningCommiter (ForwardingRulesManager provider, Class<T> clazz) {
+        this.provider = Preconditions.checkNotNull(provider, "ForwardingRulesManager can not be null!");
+        this.clazz = Preconditions.checkNotNull(clazz, "Class can not be null!");
+    }
+
+    @Override
+    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
+        Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!");
+
+        /* All DataObjects for create */
+        final Map<InstanceIdentifier<?>, DataObject> createdData = changeEvent.getCreatedData() != null
+                ? changeEvent.getCreatedData() : Collections.<InstanceIdentifier<?>, DataObject> emptyMap();
+        /* All DataObjects for remove */
+        final Set<InstanceIdentifier<?>> removeData = changeEvent.getRemovedPaths() != null
+                ? changeEvent.getRemovedPaths() : Collections.<InstanceIdentifier<?>> emptySet();
+        /* All DataObjects for updates */
+        final Map<InstanceIdentifier<?>, DataObject> updateData = changeEvent.getUpdatedData() != null
+                ? changeEvent.getUpdatedData() : Collections.<InstanceIdentifier<?>, DataObject> emptyMap();
+        /* All Original DataObjects */
+        final Map<InstanceIdentifier<?>, DataObject> originalData = changeEvent.getOriginalData() != null
+                ? changeEvent.getOriginalData() : Collections.<InstanceIdentifier<?>, DataObject> emptyMap();
+
+        this.createData(createdData);
+        this.updateData(updateData, originalData);
+        this.removeData(removeData, originalData);
+    }
+
+    /**
+     * Method return wildCardPath for Listener registration
+     * and for identify the correct KeyInstanceIdentifier from data;
+     */
+    protected abstract InstanceIdentifier<T> getWildCardPath();
+
+
+
+    @SuppressWarnings("unchecked")
+    private void createData(final Map<InstanceIdentifier<?>, DataObject> createdData) {
+        final Set<InstanceIdentifier<?>> keys = createdData.keySet() != null
+                ? createdData.keySet() : Collections.<InstanceIdentifier<?>> emptySet();
+        for (InstanceIdentifier<?> key : keys) {
+            if (clazz.equals(key.getTargetType())) {
+                final InstanceIdentifier<FlowCapableNode> nodeIdent =
+                        key.firstIdentifierOf(FlowCapableNode.class);
+                if (preConfigurationCheck(nodeIdent)) {
+                    InstanceIdentifier<T> createKeyIdent = key.firstIdentifierOf(clazz);
+                    final Optional<DataObject> value = Optional.of(createdData.get(key));
+                    if (value.isPresent()) {
+                        this.add(createKeyIdent, (T)value.get(), nodeIdent);
+                    }
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private void updateData(final Map<InstanceIdentifier<?>, DataObject> updateData,
+            final Map<InstanceIdentifier<?>, DataObject> originalData) {
+
+        final Set<InstanceIdentifier<?>> keys = updateData.keySet() != null
+                ? updateData.keySet() : Collections.<InstanceIdentifier<?>> emptySet();
+        for (InstanceIdentifier<?> key : keys) {
+            if (clazz.equals(key.getTargetType())) {
+                final InstanceIdentifier<FlowCapableNode> nodeIdent =
+                        key.firstIdentifierOf(FlowCapableNode.class);
+                if (preConfigurationCheck(nodeIdent)) {
+                    InstanceIdentifier<T> updateKeyIdent = key.firstIdentifierOf(clazz);
+                    final Optional<DataObject> value = Optional.of(updateData.get(key));
+                    final Optional<DataObject> original = Optional.of(originalData.get(key));
+                    if (value.isPresent() && original.isPresent()) {
+                        this.update(updateKeyIdent, (T)original.get(), (T)value.get(), nodeIdent);
+                    }
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private void removeData(final Set<InstanceIdentifier<?>> removeData,
+            final Map<InstanceIdentifier<?>, DataObject> originalData) {
+
+        for (InstanceIdentifier<?> key : removeData) {
+            if (clazz.equals(key.getTargetType())) {
+                final InstanceIdentifier<FlowCapableNode> nodeIdent =
+                        key.firstIdentifierOf(FlowCapableNode.class);
+                if (preConfigurationCheck(nodeIdent)) {
+                    final InstanceIdentifier<T> ident = key.firstIdentifierOf(clazz);
+                    final DataObject removeValue = originalData.get(key);
+                    this.remove(ident, (T)removeValue, nodeIdent);
+                }
+            }
+        }
+    }
+
+    private boolean preConfigurationCheck(final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+        Preconditions.checkNotNull(nodeIdent, "FlowCapableNode ident can not be null!");
+        return provider.isNodeActive(nodeIdent);
+    }
+}
+
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/FlowForwarder.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/FlowForwarder.java
new file mode 100644 (file)
index 0000000..fd0ddec
--- /dev/null
@@ -0,0 +1,140 @@
+/**ab
+ * 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.frm.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.frm.ForwardingRulesManager;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
+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.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * GroupForwarder
+ * It implements {@link org.opendaylight.controller.md.sal.binding.api.DataChangeListener}}
+ * for WildCardedPath to {@link Flow} and ForwardingRulesCommiter interface for methods:
+ *  add, update and remove {@link Flow} processing for
+ *  {@link org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent}.
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ */
+public class FlowForwarder extends AbstractListeningCommiter<Flow> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FlowForwarder.class);
+
+    private ListenerRegistration<DataChangeListener> listenerRegistration;
+
+    public FlowForwarder (final ForwardingRulesManager manager, final DataBroker db) {
+        super(manager, Flow.class);
+        Preconditions.checkNotNull(db, "DataBroker can not be null!");
+        this.listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+                getWildCardPath(), FlowForwarder.this, DataChangeScope.BASE);
+    }
+
+    @Override
+    public void close() {
+        if (listenerRegistration != null) {
+            try {
+                listenerRegistration.close();
+            } catch (Exception e) {
+                LOG.error("Error by stop FRM FlowChangeListener.", e);
+            }
+            listenerRegistration = null;
+        }
+    }
+
+    @Override
+    public void remove(final InstanceIdentifier<Flow> identifier,
+                       final Flow removeDataObj,
+                       final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+        final TableKey tableKey = identifier.firstKeyOf(Table.class, TableKey.class);
+        if (tableIdValidationPrecondition(tableKey, removeDataObj)) {
+            final RemoveFlowInputBuilder builder = new RemoveFlowInputBuilder(removeDataObj);
+            builder.setFlowRef(new FlowRef(identifier));
+            builder.setNode(new NodeRef(nodeIdent));
+            builder.setFlowTable(new FlowTableRef(nodeIdent.child(Table.class, tableKey)));
+            builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+            this.provider.getSalFlowService().removeFlow(builder.build());
+        }
+    }
+
+    @Override
+    public void update(final InstanceIdentifier<Flow> identifier,
+                       final Flow original, final Flow update,
+                       final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+        final TableKey tableKey = identifier.firstKeyOf(Table.class, TableKey.class);
+        if (tableIdValidationPrecondition(tableKey, update)) {
+            final UpdateFlowInputBuilder builder = new UpdateFlowInputBuilder();
+
+            builder.setNode(new NodeRef(nodeIdent));
+            builder.setFlowRef(new FlowRef(identifier));
+            builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+            builder.setUpdatedFlow((new UpdatedFlowBuilder(update)).build());
+            builder.setOriginalFlow((new OriginalFlowBuilder(original)).build());
+
+            this.provider.getSalFlowService().updateFlow(builder.build());
+        }
+    }
+
+    @Override
+    public void add(final InstanceIdentifier<Flow> identifier,
+                    final Flow addDataObj,
+                    final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+        final TableKey tableKey = identifier.firstKeyOf(Table.class, TableKey.class);
+        if (tableIdValidationPrecondition(tableKey, addDataObj)) {
+            final AddFlowInputBuilder builder = new AddFlowInputBuilder(addDataObj);
+
+            builder.setNode(new NodeRef(nodeIdent));
+            builder.setFlowRef(new FlowRef(identifier));
+            builder.setFlowTable(new FlowTableRef(nodeIdent.child(Table.class, tableKey)));
+            builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+            this.provider.getSalFlowService().addFlow(builder.build());
+        }
+    }
+
+    @Override
+    protected InstanceIdentifier<Flow> getWildCardPath() {
+        return InstanceIdentifier.create(Nodes.class).child(Node.class)
+                .augmentation(FlowCapableNode.class).child(Table.class).child(Flow.class);
+    }
+
+    private boolean tableIdValidationPrecondition (final TableKey tableKey, final Flow flow) {
+        Preconditions.checkNotNull(tableKey, "TableKey can not be null or empty!");
+        Preconditions.checkNotNull(flow, "Flow can not be null or empty!");
+        if (flow.getTableId() != tableKey.getId()) {
+            LOG.error("TableID in URI tableId={} and in palyload tableId={} is not same.",
+                    flow.getTableId(), tableKey.getId());
+            return false;
+        }
+        return true;
+    }
+}
+
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/FlowNodeReconciliationImpl.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/FlowNodeReconciliationImpl.java
new file mode 100644 (file)
index 0000000..f1e8dfe
--- /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.frm.impl;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.controller.frm.FlowNodeReconciliation;
+import org.opendaylight.controller.frm.ForwardingRulesManager;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+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.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ * forwardingrules-manager
+ * org.opendaylight.controller.frm
+ *
+ * FlowNode Reconciliation Listener
+ * Reconciliation for a new FlowNode
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ * Created: Jun 13, 2014
+ */
+public class FlowNodeReconciliationImpl implements FlowNodeReconciliation {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FlowNodeReconciliationImpl.class);
+
+    private final ForwardingRulesManager provider;
+
+    private ListenerRegistration<DataChangeListener> listenerRegistration;
+
+    public FlowNodeReconciliationImpl (final ForwardingRulesManager manager, final DataBroker db) {
+        this.provider = Preconditions.checkNotNull(manager, "ForwardingRulesManager can not be null!");
+        Preconditions.checkNotNull(db, "DataBroker can not be null!");
+        /* Build Path */
+        InstanceIdentifier<FlowCapableNode> flowNodeWildCardIdentifier = InstanceIdentifier.create(Nodes.class)
+                .child(Node.class).augmentation(FlowCapableNode.class);
+        this.listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                flowNodeWildCardIdentifier, FlowNodeReconciliationImpl.this, DataChangeScope.BASE);
+    }
+
+    @Override
+    public void close() {
+        if (listenerRegistration != null) {
+            try {
+                listenerRegistration.close();
+            } catch (Exception e) {
+                LOG.error("Error by stop FRM FlowNodeReconilListener.", e);
+            }
+            listenerRegistration = null;
+        }
+    }
+
+    @Override
+    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
+        Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!");
+        /* All DataObjects for create */
+        final Set<InstanceIdentifier<?>>  createdData = changeEvent.getCreatedData() != null
+                ? changeEvent.getCreatedData().keySet() : Collections.<InstanceIdentifier<?>> emptySet();
+        /* All DataObjects for remove */
+        final Set<InstanceIdentifier<?>> removeData = changeEvent.getRemovedPaths() != null
+                ? changeEvent.getRemovedPaths() : Collections.<InstanceIdentifier<?>> emptySet();
+
+        for (InstanceIdentifier<?> entryKey : removeData) {
+            final InstanceIdentifier<FlowCapableNode> nodeIdent = entryKey
+                    .firstIdentifierOf(FlowCapableNode.class);
+            if ( ! nodeIdent.isWildcarded()) {
+                flowNodeDisconnected(nodeIdent);
+            }
+        }
+        for (InstanceIdentifier<?> entryKey : createdData) {
+            final InstanceIdentifier<FlowCapableNode> nodeIdent = entryKey
+                    .firstIdentifierOf(FlowCapableNode.class);
+            if ( ! nodeIdent.isWildcarded()) {
+                flowNodeConnected(nodeIdent);
+            }
+        }
+    }
+
+    @Override
+    public void flowNodeDisconnected(InstanceIdentifier<FlowCapableNode> disconnectedNode) {
+        provider.unregistrateNode(disconnectedNode);
+    }
+
+    @Override
+    public void flowNodeConnected(InstanceIdentifier<FlowCapableNode> connectedNode) {
+        if ( ! provider.isNodeActive(connectedNode)) {
+            provider.registrateNewNode(connectedNode);
+            reconciliation(connectedNode);
+        }
+    }
+
+    private void reconciliation(final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+        ReadOnlyTransaction trans = provider.getReadTranaction();
+        Optional<FlowCapableNode> flowNode = Optional.absent();
+
+        try {
+            flowNode = trans.read(LogicalDatastoreType.CONFIGURATION, nodeIdent).get();
+        }
+        catch (Exception e) {
+            LOG.error("Fail with read Config/DS for Node {} !", nodeIdent, e);
+        }
+
+        if (flowNode.isPresent()) {
+            /* Groups - have to be first */
+            List<Group> groups = flowNode.get().getGroup() != null
+                    ? flowNode.get().getGroup() : Collections.<Group> emptyList();
+            for (Group group : groups) {
+                final KeyedInstanceIdentifier<Group, GroupKey> groupIdent =
+                        nodeIdent.child(Group.class, group.getKey());
+                this.provider.getGroupCommiter().add(groupIdent, group, nodeIdent);
+            }
+            /* Meters */
+            List<Meter> meters = flowNode.get().getMeter() != null
+                    ? flowNode.get().getMeter() : Collections.<Meter> emptyList();
+            for (Meter meter : meters) {
+                final KeyedInstanceIdentifier<Meter, MeterKey> meterIdent =
+                        nodeIdent.child(Meter.class, meter.getKey());
+                this.provider.getMeterCommiter().add(meterIdent, meter, nodeIdent);
+            }
+            /* Flows */
+            List<Table> tables = flowNode.get().getTable() != null
+                    ? flowNode.get().getTable() : Collections.<Table> emptyList();
+            for (Table table : tables) {
+                final KeyedInstanceIdentifier<Table, TableKey> tableIdent =
+                        nodeIdent.child(Table.class, table.getKey());
+                List<Flow> flows = table.getFlow() != null ? table.getFlow() : Collections.<Flow> emptyList();
+                for (Flow flow : flows) {
+                    final KeyedInstanceIdentifier<Flow, FlowKey> flowIdent =
+                            tableIdent.child(Flow.class, flow.getKey());
+                    this.provider.getFlowCommiter().add(flowIdent, flow, nodeIdent);
+                }
+            }
+        }
+        /* clean transaction */
+        trans.close();
+    }
+}
+
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/ForwardingRulesManagerImpl.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/ForwardingRulesManagerImpl.java
new file mode 100644 (file)
index 0000000..7cb7acf
--- /dev/null
@@ -0,0 +1,185 @@
+/**
+ * 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.frm.impl;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.opendaylight.controller.frm.FlowNodeReconciliation;
+import org.opendaylight.controller.frm.ForwardingRulesCommiter;
+import org.opendaylight.controller.frm.ForwardingRulesManager;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+
+/**
+ * forwardingrules-manager
+ * org.opendaylight.controller.frm.impl
+ *
+ * Manager and middle point for whole module.
+ * It contains ActiveNodeHolder and provide all RPC services.
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ * Created: Aug 25, 2014
+ */
+public class ForwardingRulesManagerImpl implements ForwardingRulesManager {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ForwardingRulesManagerImpl.class);
+
+    private final AtomicLong txNum = new AtomicLong();
+    private final Object lockObj = new Object();
+    private Set<InstanceIdentifier<FlowCapableNode>> activeNodes = Collections.emptySet();
+
+    private final DataBroker dataService;
+    private final SalFlowService salFlowService;
+    private final SalGroupService salGroupService;
+    private final SalMeterService salMeterService;
+
+    private ForwardingRulesCommiter<Flow> flowListener;
+    private ForwardingRulesCommiter<Group> groupListener;
+    private ForwardingRulesCommiter<Meter> meterListener;
+    private FlowNodeReconciliation nodeListener;
+
+    public ForwardingRulesManagerImpl(final DataBroker dataBroker,
+            final RpcConsumerRegistry rpcRegistry) {
+        this.dataService = Preconditions.checkNotNull(dataBroker, "DataBroker can not be null!");
+
+        Preconditions.checkArgument(rpcRegistry != null, "RpcConsumerRegistry can not be null !");
+
+        this.salFlowService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalFlowService.class),
+                "RPC SalFlowService not found.");
+        this.salGroupService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalGroupService.class),
+                "RPC SalGroupService not found.");
+        this.salMeterService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalMeterService.class),
+                "RPC SalMeterService not found.");
+    }
+
+    @Override
+    public void start() {
+        this.flowListener = new FlowForwarder(this, dataService);
+        this.groupListener = new GroupForwarder(this, dataService);
+        this.meterListener = new MeterForwarder(this, dataService);
+        this.nodeListener = new FlowNodeReconciliationImpl(this, dataService);
+        LOG.info("ForwardingRulesManager has started successfull.");
+    }
+
+    @Override
+    public void close() throws Exception {
+        if(this.flowListener != null) {
+            this.flowListener.close();
+            this.flowListener = null;
+        }
+        if (this.groupListener != null) {
+            this.groupListener.close();
+            this.groupListener = null;
+        }
+        if (this.meterListener != null) {
+            this.meterListener.close();
+            this.meterListener = null;
+        }
+        if (this.nodeListener != null) {
+            this.nodeListener.close();
+            this.nodeListener = null;
+        }
+    }
+
+    @Override
+    public ReadOnlyTransaction getReadTranaction() {
+        return dataService.newReadOnlyTransaction();
+    }
+
+    @Override
+    public String getNewTransactionId() {
+        return "DOM-" + txNum.getAndIncrement();
+    }
+
+    @Override
+    public boolean isNodeActive(InstanceIdentifier<FlowCapableNode> ident) {
+        return activeNodes.contains(ident);
+    }
+
+    @Override
+    public void registrateNewNode(InstanceIdentifier<FlowCapableNode> ident) {
+        if ( ! activeNodes.contains(ident)) {
+            synchronized (lockObj) {
+                if ( ! activeNodes.contains(ident)) {
+                    Set<InstanceIdentifier<FlowCapableNode>> set =
+                            Sets.newHashSet(activeNodes);
+                    set.add(ident);
+                    activeNodes = Collections.unmodifiableSet(set);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void unregistrateNode(InstanceIdentifier<FlowCapableNode> ident) {
+        if (activeNodes.contains(ident)) {
+            synchronized (lockObj) {
+                if (activeNodes.contains(ident)) {
+                    Set<InstanceIdentifier<FlowCapableNode>> set =
+                            Sets.newHashSet(activeNodes);
+                    set.remove(ident);
+                    activeNodes = Collections.unmodifiableSet(set);
+                }
+            }
+        }
+    }
+
+    @Override
+    public SalFlowService getSalFlowService() {
+        return salFlowService;
+    }
+
+    @Override
+    public SalGroupService getSalGroupService() {
+        return salGroupService;
+    }
+
+    @Override
+    public SalMeterService getSalMeterService() {
+        return salMeterService;
+    }
+
+    @Override
+    public ForwardingRulesCommiter<Flow> getFlowCommiter() {
+        return flowListener;
+    }
+
+    @Override
+    public ForwardingRulesCommiter<Group> getGroupCommiter() {
+        return groupListener;
+    }
+
+    @Override
+    public ForwardingRulesCommiter<Meter> getMeterCommiter() {
+        return meterListener;
+    }
+
+    @Override
+    public FlowNodeReconciliation getFlowNodeReconciliation() {
+        return nodeListener;
+    }
+}
+
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/GroupForwarder.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/GroupForwarder.java
new file mode 100644 (file)
index 0000000..77ef162
--- /dev/null
@@ -0,0 +1,118 @@
+/**
+ * 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.frm.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.frm.ForwardingRulesManager;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+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.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * GroupForwarder
+ * It implements {@link org.opendaylight.controller.md.sal.binding.api.DataChangeListener}}
+ * for WildCardedPath to {@link Group} and ForwardingRulesCommiter interface for methods:
+ *  add, update and remove {@link Group} processing for
+ *  {@link org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent}.
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ */
+public class GroupForwarder extends AbstractListeningCommiter<Group> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(GroupForwarder.class);
+
+    private ListenerRegistration<DataChangeListener> listenerRegistration;
+
+    public GroupForwarder (final ForwardingRulesManager manager, final DataBroker db) {
+        super(manager, Group.class);
+        Preconditions.checkNotNull(db, "DataBroker can not be null!");
+        this.listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+                getWildCardPath(), GroupForwarder.this, DataChangeScope.BASE);
+    }
+
+    @Override
+    public void close() {
+        if (listenerRegistration != null) {
+            try {
+                listenerRegistration.close();
+            } catch (Exception e) {
+                LOG.error("Error by stop FRM GroupChangeListener.", e);
+            }
+            listenerRegistration = null;
+        }
+    }
+
+    @Override
+    protected InstanceIdentifier<Group> getWildCardPath() {
+        return InstanceIdentifier.create(Nodes.class).child(Node.class)
+                .augmentation(FlowCapableNode.class).child(Group.class);
+    }
+
+    @Override
+    public void remove(final InstanceIdentifier<Group> identifier, final Group removeDataObj,
+                       final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+        final Group group = (removeDataObj);
+        final RemoveGroupInputBuilder builder = new RemoveGroupInputBuilder(group);
+
+        builder.setNode(new NodeRef(nodeIdent));
+        builder.setGroupRef(new GroupRef(identifier));
+        builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+        this.provider.getSalGroupService().removeGroup(builder.build());
+    }
+
+    @Override
+    public void update(final InstanceIdentifier<Group> identifier,
+                       final Group original, final Group update,
+                       final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+        final Group originalGroup = (original);
+        final Group updatedGroup = (update);
+        final UpdateGroupInputBuilder builder = new UpdateGroupInputBuilder();
+
+        builder.setNode(new NodeRef(nodeIdent));
+        builder.setGroupRef(new GroupRef(identifier));
+        builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+        builder.setUpdatedGroup((new UpdatedGroupBuilder(updatedGroup)).build());
+        builder.setOriginalGroup((new OriginalGroupBuilder(originalGroup)).build());
+
+        this.provider.getSalGroupService().updateGroup(builder.build());
+    }
+
+    @Override
+    public void add(final InstanceIdentifier<Group> identifier, final Group addDataObj,
+                    final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+        final Group group = (addDataObj);
+        final AddGroupInputBuilder builder = new AddGroupInputBuilder(group);
+
+        builder.setNode(new NodeRef(nodeIdent));
+        builder.setGroupRef(new GroupRef(identifier));
+        builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+        this.provider.getSalGroupService().addGroup(builder.build());
+    }
+}
+
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/MeterForwarder.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/MeterForwarder.java
new file mode 100644 (file)
index 0000000..9511fb8
--- /dev/null
@@ -0,0 +1,114 @@
+/**
+ * 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.frm.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.frm.ForwardingRulesManager;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.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.meter.service.rev130918.AddMeterInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * MeterForwarder
+ * It implements {@link org.opendaylight.controller.md.sal.binding.api.DataChangeListener}}
+ * for WildCardedPath to {@link Meter} and ForwardingRulesCommiter interface for methods:
+ *  add, update and remove {@link Meter} processing for
+ *  {@link org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent}.
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ */
+public class MeterForwarder extends AbstractListeningCommiter<Meter> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(MeterForwarder.class);
+
+    private ListenerRegistration<DataChangeListener> listenerRegistration;
+
+    public MeterForwarder (final ForwardingRulesManager manager, final DataBroker db) {
+        super(manager, Meter.class);
+        Preconditions.checkNotNull(db, "DataBroker can not be null!");
+        this.listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+                getWildCardPath(), MeterForwarder.this, DataChangeScope.BASE);
+    }
+
+    @Override
+    public void close() {
+        if (listenerRegistration != null) {
+            try {
+                listenerRegistration.close();
+            } catch (Exception e) {
+                LOG.error("Error by stop FRM MeterChangeListener.", e);
+            }
+            listenerRegistration = null;
+        }
+    }
+
+    @Override
+    protected InstanceIdentifier<Meter> getWildCardPath() {
+        return InstanceIdentifier.create(Nodes.class).child(Node.class)
+                .augmentation(FlowCapableNode.class).child(Meter.class);
+    }
+
+    @Override
+    public void remove(final InstanceIdentifier<Meter> identifier, final Meter removeDataObj,
+                       final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+        final RemoveMeterInputBuilder builder = new RemoveMeterInputBuilder(removeDataObj);
+
+        builder.setNode(new NodeRef(nodeIdent));
+        builder.setMeterRef(new MeterRef(identifier));
+        builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+        this.provider.getSalMeterService().removeMeter(builder.build());
+    }
+
+    @Override
+    public void update(final InstanceIdentifier<Meter> identifier,
+                       final Meter original, final Meter update,
+                       final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+        final UpdateMeterInputBuilder builder = new UpdateMeterInputBuilder();
+
+        builder.setNode(new NodeRef(nodeIdent));
+        builder.setMeterRef(new MeterRef(identifier));
+        builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+        builder.setUpdatedMeter((new UpdatedMeterBuilder(update)).build());
+        builder.setOriginalMeter((new OriginalMeterBuilder(original)).build());
+
+        this.provider.getSalMeterService().updateMeter(builder.build());
+    }
+
+    @Override
+    public void add(final InstanceIdentifier<Meter> identifier, final Meter addDataObj,
+                    final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+        final AddMeterInputBuilder builder = new AddMeterInputBuilder(addDataObj);
+
+        builder.setNode(new NodeRef(nodeIdent));
+        builder.setMeterRef(new MeterRef(identifier));
+        builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+        this.provider.getSalMeterService().addMeter(builder.build());
+    }
+}
+
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterChangeListener.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterChangeListener.java
deleted file mode 100644 (file)
index a2def84..0000000
+++ /dev/null
@@ -1,112 +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.frm.meter;
-
-import org.opendaylight.controller.frm.AbstractChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeterBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeterBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.Meter;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-
-/**
- * Meter Change Listener
- *  add, update and remove {@link Meter} processing from {@link org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent}.
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- */
-public class MeterChangeListener extends AbstractChangeListener {
-
-    private static final Logger LOG = LoggerFactory.getLogger(MeterChangeListener.class);
-
-    private final MeterProvider provider;
-
-    public MeterChangeListener (final MeterProvider provider) {
-        this.provider = Preconditions.checkNotNull(provider, "MeterProvider can not be null !");
-    }
-
-    @Override
-    protected void remove(final InstanceIdentifier<? extends DataObject> identifier,
-                          final DataObject removeDataObj) {
-
-        final Meter meter = ((Meter) removeDataObj);
-        final InstanceIdentifier<Node> nodeIdent = identifier.firstIdentifierOf(Node.class);
-        final RemoveMeterInputBuilder builder = new RemoveMeterInputBuilder(meter);
-
-        builder.setNode(new NodeRef(nodeIdent));
-        builder.setMeterRef(new MeterRef(identifier));
-
-        Uri uri = new Uri(this.getTransactionId());
-        builder.setTransactionUri(uri);
-        this.provider.getSalMeterService().removeMeter(builder.build());
-        LOG.debug("Transaction {} - Remove Meter has removed meter: {}", new Object[]{uri, removeDataObj});
-    }
-
-    @Override
-    protected void update(final InstanceIdentifier<? extends DataObject> identifier,
-                          final DataObject original, final DataObject update) {
-
-        final Meter originalMeter = ((Meter) original);
-        final Meter updatedMeter = ((Meter) update);
-        final InstanceIdentifier<Node> nodeInstanceId = identifier.firstIdentifierOf(Node.class);
-        final UpdateMeterInputBuilder builder = new UpdateMeterInputBuilder();
-
-        builder.setNode(new NodeRef(nodeInstanceId));
-        builder.setMeterRef(new MeterRef(identifier));
-
-        Uri uri = new Uri(this.getTransactionId());
-        builder.setTransactionUri(uri);
-
-        builder.setUpdatedMeter((new UpdatedMeterBuilder(updatedMeter)).build());
-        builder.setOriginalMeter((new OriginalMeterBuilder(originalMeter)).build());
-
-        this.provider.getSalMeterService().updateMeter(builder.build());
-        LOG.debug("Transaction {} - Update Meter has updated meter {} with {}", new Object[]{uri, original, update});
-
-    }
-
-    @Override
-    protected void add(final InstanceIdentifier<? extends DataObject> identifier,
-                       final DataObject addDataObj) {
-
-        final Meter meter = ((Meter) addDataObj);
-        final InstanceIdentifier<Node> nodeInstanceId = identifier.firstIdentifierOf(Node.class);
-        final AddMeterInputBuilder builder = new AddMeterInputBuilder(meter);
-
-        builder.setNode(new NodeRef(nodeInstanceId));
-        builder.setMeterRef(new MeterRef(identifier));
-
-        Uri uri = new Uri(this.getTransactionId());
-        builder.setTransactionUri(uri);
-        this.provider.getSalMeterService().addMeter(builder.build());
-        LOG.debug("Transaction {} - Add Meter has added meter: {}", new Object[]{uri, addDataObj});
-    }
-
-    @Override
-    protected boolean preconditionForChange(final InstanceIdentifier<? extends DataObject> identifier,
-            final DataObject dataObj, final DataObject update) {
-
-        final ReadOnlyTransaction trans = this.provider.getDataService().newReadOnlyTransaction();
-        return update != null
-                ? (dataObj instanceof Meter && update instanceof Meter && isNodeAvailable(identifier, trans))
-                : (dataObj instanceof Meter && isNodeAvailable(identifier, trans));
-    }
-}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterProvider.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterProvider.java
deleted file mode 100644 (file)
index 44de7af..0000000
+++ /dev/null
@@ -1,105 +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.frm.meter;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-
-/**
- * Meter Provider registers the {@link MeterChangeListener} and it holds all needed
- * services for {@link MeterChangeListener}.
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- */
-public class MeterProvider implements AutoCloseable {
-
-    private static final Logger LOG = LoggerFactory.getLogger(MeterProvider.class);
-
-    private SalMeterService salMeterService;
-    private DataBroker dataService;
-
-    /* DataChangeListener */
-    private DataChangeListener meterDataChangeListener;
-    private ListenerRegistration<DataChangeListener> meterDataChangeListenerRegistration;
-
-    /**
-     * Provider Initialization Phase.
-     *
-     * @param DataProviderService dataService
-     */
-    public void init(final DataBroker dataService) {
-        LOG.info("FRM Meter Config Provider initialization.");
-        this.dataService = Preconditions.checkNotNull(dataService, "DataProviderService can not be null !");
-    }
-
-    /**
-     * Listener Registration Phase
-     *
-     * @param RpcConsumerRegistry rpcRegistry
-     */
-    public void start(final RpcConsumerRegistry rpcRegistry) {
-        Preconditions.checkArgument(rpcRegistry != null, "RpcConsumerRegistry can not be null !");
-        this.salMeterService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalMeterService.class),
-                "RPC SalMeterService not found.");
-
-        /* Build Path */
-        InstanceIdentifier<Meter> meterIdentifier = InstanceIdentifier.create(Nodes.class)
-                .child(Node.class).augmentation(FlowCapableNode.class).child(Meter.class);
-
-        /* DataChangeListener registration */
-        this.meterDataChangeListener = new MeterChangeListener(MeterProvider.this);
-        this.meterDataChangeListenerRegistration =
-                this.dataService.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
-                        meterIdentifier, meterDataChangeListener, DataChangeScope.SUBTREE);
-
-        LOG.info("FRM Meter Config Provider started.");
-    }
-
-    @Override
-    public void close() {
-        LOG.info("FRM Meter Config Provider stopped.");
-        if (meterDataChangeListenerRegistration != null) {
-            try {
-                meterDataChangeListenerRegistration.close();
-            } catch (Exception e) {
-                String errMsg = "Error by stop FRM Meter Config Provider.";
-                LOG.error(errMsg, e);
-                throw new IllegalStateException(errMsg, e);
-            } finally {
-                meterDataChangeListenerRegistration = null;
-            }
-        }
-    }
-
-    public DataChangeListener getMeterDataChangeListener() {
-        return meterDataChangeListener;
-    }
-
-    public DataBroker getDataService() {
-        return dataService;
-    }
-
-    public SalMeterService getSalMeterService() {
-        return salMeterService;
-    }
-}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/reconil/FlowNodeReconcilListener.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/reconil/FlowNodeReconcilListener.java
deleted file mode 100644 (file)
index 6308f2a..0000000
+++ /dev/null
@@ -1,196 +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.frm.reconil;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import org.opendaylight.controller.frm.AbstractChangeListener;
-import org.opendaylight.controller.frm.FlowCookieProducer;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-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.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * forwardingrules-manager
- * org.opendaylight.controller.frm
- *
- * FlowNode Reconciliation Listener
- * Reconciliation for a new FlowNode
- * Remove CookieMapKey for removed FlowNode
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- * Created: Jun 13, 2014
- */
-public class FlowNodeReconcilListener extends AbstractChangeListener {
-
-    private static final Logger LOG = LoggerFactory.getLogger(FlowNodeReconcilListener.class);
-
-    private final FlowNodeReconcilProvider provider;
-
-    public FlowNodeReconcilListener(final FlowNodeReconcilProvider provider) {
-        this.provider = Preconditions.checkNotNull(provider, "Flow Node Reconcil Provider can not be null!");
-    }
-
-    @Override
-    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
-        /* FlowCapableNode DataObjects for reconciliation */
-        final Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> createdEntries =
-                changeEvent.getCreatedData().entrySet();
-        /* FlowCapableNode DataObjects for clean FlowCookieHolder */
-        final Set<InstanceIdentifier<? extends DataObject>> removeEntriesInstanceIdentifiers =
-                changeEvent.getRemovedPaths();
-        for (final Entry<InstanceIdentifier<? extends DataObject>, DataObject> createdEntry : createdEntries) {
-            InstanceIdentifier<? extends DataObject> entryKey = createdEntry.getKey();
-            DataObject entryValue = createdEntry.getValue();
-            if (preconditionForChange(entryKey, entryValue, null)) {
-                this.add(entryKey, entryValue);
-            }
-        }
-        for (final InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers) {
-            Map<InstanceIdentifier<? extends DataObject>, DataObject> origConfigData =
-                    changeEvent.getOriginalData();
-            final DataObject removeValue = origConfigData.get(instanceId);
-            if (preconditionForChange(instanceId, removeValue, null)) {
-                this.remove(instanceId, removeValue);
-            }
-        }
-    }
-
-    @Override
-    /* Cleaning FlowCookieManager holder for all node tables */
-    protected void remove(final InstanceIdentifier<? extends DataObject> identifier,
-                          final DataObject removeDataObj) {
-
-        final InstanceIdentifier<FlowCapableNode> flowNodeIdent =
-                identifier.firstIdentifierOf(FlowCapableNode.class);
-        final FlowCapableNode flowNode = ((FlowCapableNode) removeDataObj);
-
-        for (Table flowTable : flowNode.getTable()) {
-            final InstanceIdentifier<Table> tableIdent =
-                    flowNodeIdent.child(Table.class, flowTable.getKey());
-            FlowCookieProducer.INSTANCE.clean(tableIdent);
-        }
-    }
-
-    @Override
-    /* Reconciliation by connect new FlowCapableNode */
-    protected void add(final InstanceIdentifier<? extends DataObject> identifier,
-                       final DataObject addDataObj) {
-
-        final InstanceIdentifier<FlowCapableNode> flowNodeIdent =
-                identifier.firstIdentifierOf(FlowCapableNode.class);
-        final Optional<FlowCapableNode> flowCapNode = this.readFlowCapableNode(flowNodeIdent);
-
-        if (flowCapNode.isPresent()) {
-            final InstanceIdentifier<Node> nodeIdent = identifier.firstIdentifierOf(Node.class);
-            final NodeRef nodeRef = new NodeRef(nodeIdent);
-            /* Groups - have to be first */
-            List<Group> groups = flowCapNode.get().getGroup();
-            if(groups != null) {
-                for (Group group : groups) {
-                    final GroupRef groupRef = new GroupRef(flowNodeIdent.child(Group.class, group.getKey()));
-                    final AddGroupInputBuilder groupBuilder = new AddGroupInputBuilder(group);
-                    groupBuilder.setGroupRef(groupRef);
-                    groupBuilder.setNode(nodeRef);
-                    this.provider.getSalGroupService().addGroup(groupBuilder.build());
-                }
-            }
-            /* Meters */
-            List<Meter> meters = flowCapNode.get().getMeter();
-            if(meters != null) {
-                for (Meter meter : meters) {
-                    final MeterRef meterRef = new MeterRef(flowNodeIdent.child(Meter.class, meter.getKey()));
-                    final AddMeterInputBuilder meterBuilder = new AddMeterInputBuilder(meter);
-                    meterBuilder.setMeterRef(meterRef);
-                    meterBuilder.setNode(nodeRef);
-                    this.provider.getSalMeterService().addMeter(meterBuilder.build());
-                }
-            }
-            /* Flows */
-            List<Table> tables = flowCapNode.get().getTable();
-            if(tables != null) {
-                for (Table flowTable : tables) {
-                    final InstanceIdentifier<Table> tableIdent = flowNodeIdent.child(Table.class, flowTable.getKey());
-                    List<Flow> flows = flowTable.getFlow();
-                    if(flows != null) {
-                        for (Flow flow : flows) {
-                            final FlowCookie flowCookie = new FlowCookie(FlowCookieProducer.INSTANCE.getNewCookie(tableIdent));
-                            final FlowRef flowRef = new FlowRef(tableIdent.child(Flow.class, flow.getKey()));
-                            final FlowTableRef flowTableRef = new FlowTableRef(tableIdent);
-                            final AddFlowInputBuilder flowBuilder = new AddFlowInputBuilder(flow);
-                            flowBuilder.setCookie(flowCookie);
-                            flowBuilder.setNode(nodeRef);
-                            flowBuilder.setFlowTable(flowTableRef);
-                            flowBuilder.setFlowRef(flowRef);
-                            this.provider.getSalFlowService().addFlow(flowBuilder.build());
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    @Override
-    protected void update(final InstanceIdentifier<? extends DataObject> identifier,
-                          final DataObject original, final DataObject update) {
-        // NOOP - Listener is registered for DataChangeScope.BASE only
-    }
-
-    @Override
-    protected boolean preconditionForChange(final InstanceIdentifier<? extends DataObject> identifier,
-                                            final DataObject dataObj, final DataObject update) {
-        return (dataObj instanceof FlowCapableNode);
-    }
-
-    private Optional<FlowCapableNode> readFlowCapableNode(final InstanceIdentifier<FlowCapableNode> flowNodeIdent) {
-        ReadOnlyTransaction readTrans = this.provider.getDataService().newReadOnlyTransaction();
-        try {
-            ListenableFuture<Optional<FlowCapableNode>> confFlowNode =
-                    readTrans.read(LogicalDatastoreType.CONFIGURATION, flowNodeIdent);
-            if (confFlowNode.get().isPresent()) {
-                return Optional.<FlowCapableNode> of(confFlowNode.get().get());
-            } else {
-                return Optional.absent();
-            }
-        }
-        catch (InterruptedException | ExecutionException e) {
-            LOG.error("Unexpected exception by reading flow ".concat(flowNodeIdent.toString()), e);
-            return Optional.absent();
-        }
-        finally {
-            readTrans.close();
-        }
-    }
-}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/reconil/FlowNodeReconcilProvider.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/reconil/FlowNodeReconcilProvider.java
deleted file mode 100644 (file)
index ad970d6..0000000
+++ /dev/null
@@ -1,115 +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.frm.reconil;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-
-/**
- * forwardingrules-manager
- * org.opendaylight.controller.frm
- *
- * FlowNode Reconciliation Provider registers the FlowNodeReconilListener
- * and it holds all needed services for FlowNodeReconcilListener.
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- * Created: Jun 13, 2014
- */
-public class FlowNodeReconcilProvider implements AutoCloseable {
-
-    private static final Logger LOG = LoggerFactory.getLogger(FlowNodeReconcilProvider.class);
-
-    private SalFlowService salFlowService;
-    private SalMeterService salMeterService;
-    private SalGroupService salGroupService;
-    private DataBroker dataService;
-
-    /* DataChangeListener */
-    private DataChangeListener flowNodeReconcilListener;
-    private ListenerRegistration<DataChangeListener> flowNodeReconcilListenerRegistration;
-
-    public void init (final DataBroker dataService) {
-        LOG.info("FRM Flow Node Config Reconcil Provider initialization.");
-
-        this.dataService = Preconditions.checkNotNull(dataService, "DataProviderService can not be null !");
-    }
-
-    public void start( final RpcConsumerRegistry rpcRegistry ) {
-        Preconditions.checkArgument(rpcRegistry != null, "RpcConcumerRegistry can not be null !");
-
-        this.salFlowService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalFlowService.class),
-                "RPC SalFlowService not found.");
-        this.salMeterService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalMeterService.class),
-                "RPC SalMeterService not found.");
-        this.salGroupService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalGroupService.class),
-                "RPC SalGroupService not found.");
-
-        /* Build Path */
-        InstanceIdentifier<FlowCapableNode> flowCapableNodeIdent =
-                InstanceIdentifier.create(Nodes.class).child(Node.class).augmentation(FlowCapableNode.class);
-
-        /* ReconcilNotificationListener registration */
-        this.flowNodeReconcilListener = new FlowNodeReconcilListener(FlowNodeReconcilProvider.this);
-        this.flowNodeReconcilListenerRegistration = this.dataService.registerDataChangeListener(
-                LogicalDatastoreType.OPERATIONAL, flowCapableNodeIdent, flowNodeReconcilListener, DataChangeScope.BASE);
-        LOG.info("FRM Flow Node Config Reconcil Provider started.");
-    }
-
-    @Override
-    public void close() {
-        LOG.info("FRM Flow Node Config Reconcil Provider stopped.");
-        if (flowNodeReconcilListenerRegistration != null) {
-            try {
-                flowNodeReconcilListenerRegistration.close();
-            } catch (Exception e) {
-                String errMsg = "Error by stop FRM Flow Node Config Reconcil Provider.";
-                LOG.error(errMsg, e);
-                throw new IllegalStateException(errMsg, e);
-            } finally {
-                flowNodeReconcilListenerRegistration = null;
-            }
-        }
-    }
-
-    public DataChangeListener getFlowNodeReconcilListener() {
-        return flowNodeReconcilListener;
-    }
-
-    public DataBroker getDataService() {
-        return dataService;
-    }
-
-    public SalFlowService getSalFlowService() {
-        return salFlowService;
-    }
-
-    public SalMeterService getSalMeterService() {
-        return salMeterService;
-    }
-
-    public SalGroupService getSalGroupService() {
-        return salGroupService;
-    }
-}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/FlowListenerTest.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/FlowListenerTest.java
new file mode 100644 (file)
index 0000000..85f4b14
--- /dev/null
@@ -0,0 +1,210 @@
+/**
+ * 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 test.mock;
+
+import org.junit.Test;
+import org.opendaylight.controller.frm.impl.ForwardingRulesManagerImpl;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+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.model.match.types.rev131026.match.IpMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import test.mock.util.FRMTest;
+import test.mock.util.RpcProviderRegistryMock;
+import test.mock.util.SalFlowServiceMock;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+public class FlowListenerTest extends FRMTest {
+    RpcProviderRegistry rpcProviderRegistryMock = new RpcProviderRegistryMock();
+    NodeKey s1Key = new NodeKey(new NodeId("S1"));
+    TableKey tableKey = new TableKey((short) 2);
+
+    @Test
+    public void addTwoFlowsTest() throws Exception {
+        ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+        forwardingRulesManager.start();
+
+        addFlowCapableNode(s1Key);
+
+        FlowKey flowKey = new FlowKey(new FlowId("test_Flow"));
+        InstanceIdentifier<Table> tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Table.class, tableKey);
+        InstanceIdentifier<Flow> flowII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Table.class, tableKey).child(Flow.class, flowKey);
+        Table table = new TableBuilder().setKey(tableKey).setFlow(Collections.<Flow>emptyList()).build();
+        Flow flow = new FlowBuilder().setKey(flowKey).setTableId((short) 2).build();
+
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, tableII, table);
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, flowII, flow);
+        assertCommit(writeTx.submit());
+        SalFlowServiceMock salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
+        List<AddFlowInput> addFlowCalls = salFlowService.getAddFlowCalls();
+        assertEquals(1, addFlowCalls.size());
+        assertEquals("DOM-0", addFlowCalls.get(0).getTransactionUri().getValue());
+
+        flowKey = new FlowKey(new FlowId("test_Flow2"));
+        flowII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Table.class, tableKey).child(Flow.class, flowKey);
+        flow = new FlowBuilder().setKey(flowKey).setTableId((short) 2).build();
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, flowII, flow);
+        assertCommit(writeTx.submit());
+        salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
+        addFlowCalls = salFlowService.getAddFlowCalls();
+        assertEquals(2, addFlowCalls.size());
+        assertEquals("DOM-1", addFlowCalls.get(1).getTransactionUri().getValue());
+        assertEquals(2, addFlowCalls.get(1).getTableId().intValue());
+        assertEquals(flowII, addFlowCalls.get(1).getFlowRef().getValue());
+
+        forwardingRulesManager.close();
+    }
+
+    @Test
+    public void updateFlowTest() throws Exception {
+        ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+        forwardingRulesManager.start();
+
+        addFlowCapableNode(s1Key);
+
+        FlowKey flowKey = new FlowKey(new FlowId("test_Flow"));
+        InstanceIdentifier<Table> tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Table.class, tableKey);
+        InstanceIdentifier<Flow> flowII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Table.class, tableKey).child(Flow.class, flowKey);
+        Table table = new TableBuilder().setKey(tableKey).setFlow(Collections.<Flow>emptyList()).build();
+        Flow flow = new FlowBuilder().setKey(flowKey).setTableId((short) 2).build();
+
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, tableII, table);
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, flowII, flow);
+        assertCommit(writeTx.submit());
+        SalFlowServiceMock salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
+        List<AddFlowInput> addFlowCalls = salFlowService.getAddFlowCalls();
+        assertEquals(1, addFlowCalls.size());
+        assertEquals("DOM-0", addFlowCalls.get(0).getTransactionUri().getValue());
+
+        flowKey = new FlowKey(new FlowId("test_Flow"));
+        flowII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Table.class, tableKey).child(Flow.class, flowKey);
+        flow = new FlowBuilder().setKey(flowKey).setTableId((short) 2).setOutGroup((long) 5).build();
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, flowII, flow);
+        assertCommit(writeTx.submit());
+        salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
+        List<UpdateFlowInput> updateFlowCalls = salFlowService.getUpdateFlowCalls();
+        assertEquals(1, updateFlowCalls.size());
+        assertEquals("DOM-1", updateFlowCalls.get(0).getTransactionUri().getValue());
+        assertEquals(flowII, updateFlowCalls.get(0).getFlowRef().getValue());
+
+        forwardingRulesManager.close();
+    }
+
+    @Test
+    public void updateFlowScopeTest() throws Exception {
+        ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+        forwardingRulesManager.start();
+
+        addFlowCapableNode(s1Key);
+
+        FlowKey flowKey = new FlowKey(new FlowId("test_Flow"));
+        InstanceIdentifier<Table> tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Table.class, tableKey);
+        InstanceIdentifier<Flow> flowII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Table.class, tableKey).child(Flow.class, flowKey);
+        Table table = new TableBuilder().setKey(tableKey).setFlow(Collections.<Flow>emptyList()).build();
+        IpMatch ipMatch = new IpMatchBuilder().setIpDscp(new Dscp((short)4)).build();
+        Match match = new MatchBuilder().setIpMatch(ipMatch).build();
+        Flow flow = new FlowBuilder().setMatch(match).setKey(flowKey).setTableId((short) 2).build();
+
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, tableII, table);
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, flowII, flow);
+        assertCommit(writeTx.submit());
+        SalFlowServiceMock salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
+        List<AddFlowInput> addFlowCalls = salFlowService.getAddFlowCalls();
+        assertEquals(1, addFlowCalls.size());
+        assertEquals("DOM-0", addFlowCalls.get(0).getTransactionUri().getValue());
+
+        flowKey = new FlowKey(new FlowId("test_Flow"));
+        flowII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Table.class, tableKey).child(Flow.class, flowKey);
+        ipMatch = new IpMatchBuilder().setIpDscp(new Dscp((short)5)).build();
+        match = new MatchBuilder().setIpMatch(ipMatch).build();
+        flow = new FlowBuilder().setMatch(match).setKey(flowKey).setTableId((short) 2).build();
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, flowII, flow);
+        assertCommit(writeTx.submit());
+        salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
+        List<UpdateFlowInput> updateFlowCalls = salFlowService.getUpdateFlowCalls();
+        assertEquals(1, updateFlowCalls.size());
+        assertEquals("DOM-1", updateFlowCalls.get(0).getTransactionUri().getValue());
+        assertEquals(flowII, updateFlowCalls.get(0).getFlowRef().getValue());
+        assertEquals(ipMatch, updateFlowCalls.get(0).getUpdatedFlow().getMatch().getIpMatch());
+        forwardingRulesManager.close();
+    }
+
+    @Test
+    public void deleteFlowTest() throws Exception {
+        ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+        forwardingRulesManager.start();
+
+        addFlowCapableNode(s1Key);
+
+        FlowKey flowKey = new FlowKey(new FlowId("test_Flow"));
+        InstanceIdentifier<Table> tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Table.class, tableKey);
+        InstanceIdentifier<Flow> flowII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Table.class, tableKey).child(Flow.class, flowKey);
+        Table table = new TableBuilder().setKey(tableKey).setFlow(Collections.<Flow>emptyList()).build();
+        Flow flow = new FlowBuilder().setKey(flowKey).setTableId((short) 2).build();
+
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, tableII, table);
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, flowII, flow);
+        assertCommit(writeTx.submit());
+        SalFlowServiceMock salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
+        List<AddFlowInput> addFlowCalls = salFlowService.getAddFlowCalls();
+        assertEquals(1, addFlowCalls.size());
+        assertEquals("DOM-0", addFlowCalls.get(0).getTransactionUri().getValue());
+
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.delete(LogicalDatastoreType.CONFIGURATION, flowII);
+        assertCommit(writeTx.submit());
+        salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
+        List<RemoveFlowInput> removeFlowCalls = salFlowService.getRemoveFlowCalls();
+        assertEquals(1, removeFlowCalls.size());
+        assertEquals("DOM-1", removeFlowCalls.get(0).getTransactionUri().getValue());
+        assertEquals(flowII, removeFlowCalls.get(0).getFlowRef().getValue());
+
+        forwardingRulesManager.close();
+    }
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/GroupListenerTest.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/GroupListenerTest.java
new file mode 100644 (file)
index 0000000..97eb899
--- /dev/null
@@ -0,0 +1,137 @@
+/**
+ * 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 test.mock;
+
+import org.junit.Test;
+import org.opendaylight.controller.frm.impl.ForwardingRulesManagerImpl;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+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.yangtools.yang.binding.InstanceIdentifier;
+import test.mock.util.FRMTest;
+import test.mock.util.RpcProviderRegistryMock;
+import test.mock.util.SalGroupServiceMock;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+public class GroupListenerTest extends FRMTest {
+    RpcProviderRegistry rpcProviderRegistryMock = new RpcProviderRegistryMock();
+    NodeKey s1Key = new NodeKey(new NodeId("S1"));
+
+    @Test
+    public void addTwoGroupsTest() throws Exception {
+        ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+        forwardingRulesManager.start();
+
+        addFlowCapableNode(s1Key);
+
+        GroupKey groupKey = new GroupKey(new GroupId((long) 255));
+        InstanceIdentifier<Group> groupII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Group.class, groupKey);
+        Group group = new GroupBuilder().setKey(groupKey).setGroupName("Group1").build();
+
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, groupII, group);
+        assertCommit(writeTx.submit());
+        SalGroupServiceMock salGroupService = (SalGroupServiceMock) forwardingRulesManager.getSalGroupService();
+        List<AddGroupInput> addGroupCalls = salGroupService.getAddGroupCalls();
+        assertEquals(1, addGroupCalls.size());
+        assertEquals("DOM-0", addGroupCalls.get(0).getTransactionUri().getValue());
+
+        groupKey = new GroupKey(new GroupId((long) 256));
+        groupII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Group.class, groupKey);
+        group = new GroupBuilder().setKey(groupKey).setGroupName("Group1").build();
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, groupII, group);
+        assertCommit(writeTx.submit());
+        salGroupService = (SalGroupServiceMock) forwardingRulesManager.getSalGroupService();
+        addGroupCalls = salGroupService.getAddGroupCalls();
+        assertEquals(2, addGroupCalls.size());
+        assertEquals("DOM-1", addGroupCalls.get(1).getTransactionUri().getValue());
+
+        forwardingRulesManager.close();
+    }
+
+    @Test
+    public void updateGroupTest() throws Exception {
+        ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+        forwardingRulesManager.start();
+
+        addFlowCapableNode(s1Key);
+
+        GroupKey groupKey = new GroupKey(new GroupId((long) 255));
+        InstanceIdentifier<Group> groupII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Group.class, groupKey);
+        Group group = new GroupBuilder().setKey(groupKey).setGroupName("Group1").build();
+
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, groupII, group);
+        assertCommit(writeTx.submit());
+        SalGroupServiceMock salGroupService = (SalGroupServiceMock) forwardingRulesManager.getSalGroupService();
+        List<AddGroupInput> addGroupCalls = salGroupService.getAddGroupCalls();
+        assertEquals(1, addGroupCalls.size());
+        assertEquals("DOM-0", addGroupCalls.get(0).getTransactionUri().getValue());
+
+        group = new GroupBuilder().setKey(groupKey).setGroupName("Group2").build();
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, groupII, group);
+        assertCommit(writeTx.submit());
+        salGroupService = (SalGroupServiceMock) forwardingRulesManager.getSalGroupService();
+        List<UpdateGroupInput> updateGroupCalls = salGroupService.getUpdateGroupCalls();
+        assertEquals(1, updateGroupCalls.size());
+        assertEquals("DOM-1", updateGroupCalls.get(0).getTransactionUri().getValue());
+
+        forwardingRulesManager.close();
+    }
+
+    @Test
+    public void removeGroupTest() throws Exception {
+        ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+        forwardingRulesManager.start();
+
+        addFlowCapableNode(s1Key);
+
+        GroupKey groupKey = new GroupKey(new GroupId((long) 255));
+        InstanceIdentifier<Group> groupII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Group.class, groupKey);
+        Group group = new GroupBuilder().setKey(groupKey).setGroupName("Group1").build();
+
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, groupII, group);
+        assertCommit(writeTx.submit());
+        SalGroupServiceMock salGroupService = (SalGroupServiceMock) forwardingRulesManager.getSalGroupService();
+        List<AddGroupInput> addGroupCalls = salGroupService.getAddGroupCalls();
+        assertEquals(1, addGroupCalls.size());
+        assertEquals("DOM-0", addGroupCalls.get(0).getTransactionUri().getValue());
+
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.delete(LogicalDatastoreType.CONFIGURATION, groupII);
+        assertCommit(writeTx.submit());
+        salGroupService = (SalGroupServiceMock) forwardingRulesManager.getSalGroupService();
+        List<RemoveGroupInput> removeGroupCalls = salGroupService.getRemoveGroupCalls();
+        assertEquals(1, removeGroupCalls.size());
+        assertEquals("DOM-1", removeGroupCalls.get(0).getTransactionUri().getValue());
+
+        forwardingRulesManager.close();
+    }
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/MeterListenerTest.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/MeterListenerTest.java
new file mode 100644 (file)
index 0000000..0d32f9f
--- /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 test.mock;
+
+import org.junit.Test;
+import org.opendaylight.controller.frm.impl.ForwardingRulesManagerImpl;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+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.meter.service.rev130918.AddMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import test.mock.util.FRMTest;
+import test.mock.util.RpcProviderRegistryMock;
+import test.mock.util.SalMeterServiceMock;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+public class MeterListenerTest extends FRMTest {
+    RpcProviderRegistry rpcProviderRegistryMock = new RpcProviderRegistryMock();
+    NodeKey s1Key = new NodeKey(new NodeId("S1"));
+
+    @Test
+    public void addTwoMetersTest() throws Exception {
+        ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+        forwardingRulesManager.start();
+
+        addFlowCapableNode(s1Key);
+
+        MeterKey meterKey = new MeterKey(new MeterId((long) 2000));
+        InstanceIdentifier<Meter> meterII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Meter.class, meterKey);
+        Meter meter = new MeterBuilder().setKey(meterKey).setMeterName("meter_one").build();
+
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, meterII, meter);
+        assertCommit(writeTx.submit());
+        SalMeterServiceMock salMeterService = (SalMeterServiceMock) forwardingRulesManager.getSalMeterService();
+        List<AddMeterInput> addMeterCalls = salMeterService.getAddMeterCalls();
+        assertEquals(1, addMeterCalls.size());
+        assertEquals("DOM-0", addMeterCalls.get(0).getTransactionUri().getValue());
+
+        meterKey = new MeterKey(new MeterId((long) 2001));
+        meterII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Meter.class, meterKey);
+        meter = new MeterBuilder().setKey(meterKey).setMeterName("meter_two").setBarrier(true).build();
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, meterII, meter);
+        assertCommit(writeTx.submit());
+        salMeterService = (SalMeterServiceMock) forwardingRulesManager.getSalMeterService();
+        addMeterCalls = salMeterService.getAddMeterCalls();
+        assertEquals(2, addMeterCalls.size());
+        assertEquals("DOM-1", addMeterCalls.get(1).getTransactionUri().getValue());
+        assertEquals(meterII, addMeterCalls.get(1).getMeterRef().getValue());
+
+        forwardingRulesManager.close();
+    }
+
+    @Test
+    public void updateMeterTest() throws Exception {
+        ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+        forwardingRulesManager.start();
+
+        addFlowCapableNode(s1Key);
+
+        MeterKey meterKey = new MeterKey(new MeterId((long) 2000));
+        InstanceIdentifier<Meter> meterII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Meter.class, meterKey);
+        Meter meter = new MeterBuilder().setKey(meterKey).setMeterName("meter_one").setBarrier(false).build();
+
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, meterII, meter);
+        assertCommit(writeTx.submit());
+        SalMeterServiceMock salMeterService = (SalMeterServiceMock) forwardingRulesManager.getSalMeterService();
+        List<AddMeterInput> addMeterCalls = salMeterService.getAddMeterCalls();
+        assertEquals(1, addMeterCalls.size());
+        assertEquals("DOM-0", addMeterCalls.get(0).getTransactionUri().getValue());
+
+        meter = new MeterBuilder().setKey(meterKey).setMeterName("meter_two").setBarrier(true).build();
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, meterII, meter);
+        assertCommit(writeTx.submit());
+        salMeterService = (SalMeterServiceMock) forwardingRulesManager.getSalMeterService();
+        List<UpdateMeterInput> updateMeterCalls = salMeterService.getUpdateMeterCalls();
+        assertEquals(1, updateMeterCalls.size());
+        assertEquals("DOM-1", updateMeterCalls.get(0).getTransactionUri().getValue());
+        assertEquals(meterII, updateMeterCalls.get(0).getMeterRef().getValue());
+
+        forwardingRulesManager.close();
+    }
+
+    @Test
+    public void removeMeterTest() throws Exception {
+        ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+        forwardingRulesManager.start();
+
+        addFlowCapableNode(s1Key);
+
+        MeterKey meterKey = new MeterKey(new MeterId((long) 2000));
+        InstanceIdentifier<Meter> meterII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class).child(Meter.class, meterKey);
+        Meter meter = new MeterBuilder().setKey(meterKey).setMeterName("meter_one").build();
+
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, meterII, meter);
+        assertCommit(writeTx.submit());
+        SalMeterServiceMock salMeterService = (SalMeterServiceMock) forwardingRulesManager.getSalMeterService();
+        List<AddMeterInput> addMeterCalls = salMeterService.getAddMeterCalls();
+        assertEquals(1, addMeterCalls.size());
+        assertEquals("DOM-0", addMeterCalls.get(0).getTransactionUri().getValue());
+
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.delete(LogicalDatastoreType.CONFIGURATION, meterII);
+        assertCommit(writeTx.submit());
+        salMeterService = (SalMeterServiceMock) forwardingRulesManager.getSalMeterService();
+        List<RemoveMeterInput> removeMeterCalls = salMeterService.getRemoveMeterCalls();
+        assertEquals(1, removeMeterCalls.size());
+        assertEquals("DOM-1", removeMeterCalls.get(0).getTransactionUri().getValue());
+        assertEquals(meterII, removeMeterCalls.get(0).getMeterRef().getValue());
+
+        forwardingRulesManager.close();
+    }
+
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/NodeListenerTest.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/NodeListenerTest.java
new file mode 100644 (file)
index 0000000..3cf2e93
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * 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 test.mock;
+
+import org.junit.Test;
+import org.opendaylight.controller.frm.impl.ForwardingRulesManagerImpl;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+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.yangtools.yang.binding.InstanceIdentifier;
+import test.mock.util.FRMTest;
+import test.mock.util.RpcProviderRegistryMock;
+
+import java.util.concurrent.ExecutionException;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class NodeListenerTest extends FRMTest {
+
+    RpcProviderRegistry rpcProviderRegistryMock = new RpcProviderRegistryMock();
+    NodeKey s1Key = new NodeKey(new NodeId("S1"));
+
+    @Test
+    public void addRemoveNodeTest() throws ExecutionException, InterruptedException {
+        ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+        forwardingRulesManager.start();
+
+        addFlowCapableNode(s1Key);
+
+        InstanceIdentifier<FlowCapableNode> nodeII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+                .augmentation(FlowCapableNode.class);
+
+        boolean nodeActive = forwardingRulesManager.isNodeActive(nodeII);
+        assertTrue(nodeActive);
+
+        removeNode(s1Key);
+
+        nodeActive = forwardingRulesManager.isNodeActive(nodeII);
+        assertFalse(nodeActive);
+    }
+
+
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/AbstractDataBrokerTest.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/AbstractDataBrokerTest.java
new file mode 100644 (file)
index 0000000..f9efa51
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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 test.mock.util;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class AbstractDataBrokerTest extends AbstractSchemaAwareTest {
+
+    private DataBrokerTestCustomizer testCustomizer;
+    private DataBroker dataBroker;
+    private DOMDataBroker domBroker;
+
+
+    @Override
+    protected void setupWithSchema(final SchemaContext context) {
+        testCustomizer = createDataBrokerTestCustomizer();
+        dataBroker = testCustomizer.createDataBroker();
+        domBroker = testCustomizer.createDOMDataBroker();
+        testCustomizer.updateSchema(context);
+        setupWithDataBroker(dataBroker);
+    }
+
+    protected void setupWithDataBroker(final DataBroker dataBroker) {
+        // Intentionally left No-op, subclasses may customize it
+    }
+
+   protected DataBrokerTestCustomizer createDataBrokerTestCustomizer() {
+        return new DataBrokerTestCustomizer();
+    }
+
+    public DataBroker getDataBroker() {
+        return dataBroker;
+    }
+
+    public DOMDataBroker getDomBroker() {
+        return domBroker;
+    }
+
+    protected static final void assertCommit(final ListenableFuture<Void> commit) {
+        try {
+            commit.get(500, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException | ExecutionException | TimeoutException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/AbstractSchemaAwareTest.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/AbstractSchemaAwareTest.java
new file mode 100644 (file)
index 0000000..d520d59
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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 test.mock.util;
+
+import org.junit.Before;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public abstract class AbstractSchemaAwareTest {
+
+    private Iterable<YangModuleInfo> moduleInfos;
+    private SchemaContext schemaContext;
+
+
+    protected Iterable<YangModuleInfo> getModuleInfos() {
+        return BindingReflections.loadModuleInfos();
+    }
+
+
+    @Before
+    public final void setup() {
+        moduleInfos = getModuleInfos();
+        ModuleInfoBackedContext moduleContext = ModuleInfoBackedContext.create();
+        moduleContext.addModuleInfos(moduleInfos);
+        schemaContext = moduleContext.tryToCreateSchemaContext().get();
+        setupWithSchema(schemaContext);
+    }
+
+    /**
+     * Setups test with Schema context.
+     * This method is called before {@link #setupWithSchemaService(SchemaService)}
+     *
+     * @param context
+     */
+    protected abstract void setupWithSchema(SchemaContext context);
+
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/DataBrokerTestCustomizer.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/DataBrokerTestCustomizer.java
new file mode 100644 (file)
index 0000000..36ab41f
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * 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 test.mock.util;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import javassist.ClassPool;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker;
+import org.opendaylight.controller.md.sal.binding.impl.ForwardedBindingDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+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.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.spi.data.DOMStore;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.DataObjectSerializerGenerator;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
+import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class DataBrokerTestCustomizer {
+
+    private DOMDataBroker domDataBroker;
+    private final RuntimeGeneratedMappingServiceImpl mappingService;
+    private final MockSchemaService schemaService;
+    private ImmutableMap<LogicalDatastoreType, DOMStore> datastores;
+    private final BindingToNormalizedNodeCodec bindingToNormalized ;
+
+    public ImmutableMap<LogicalDatastoreType, DOMStore> createDatastores() {
+        return ImmutableMap.<LogicalDatastoreType, DOMStore>builder()
+                .put(LogicalDatastoreType.OPERATIONAL, createOperationalDatastore())
+                .put(LogicalDatastoreType.CONFIGURATION,createConfigurationDatastore())
+                .build();
+    }
+
+    public DataBrokerTestCustomizer() {
+        schemaService = new MockSchemaService();
+        ClassPool pool = ClassPool.getDefault();
+        mappingService = new RuntimeGeneratedMappingServiceImpl(pool);
+        DataObjectSerializerGenerator generator = StreamWriterGenerator.create(JavassistUtils.forClassPool(pool));
+        BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(generator);
+        GeneratedClassLoadingStrategy loading = GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy();
+        bindingToNormalized = new BindingToNormalizedNodeCodec(loading, mappingService, codecRegistry);
+        schemaService.registerSchemaContextListener(bindingToNormalized);
+    }
+
+    public DOMStore createConfigurationDatastore() {
+        InMemoryDOMDataStore store = new InMemoryDOMDataStore("CFG",
+                MoreExecutors.sameThreadExecutor(), MoreExecutors.sameThreadExecutor());
+        schemaService.registerSchemaContextListener(store);
+        return store;
+    }
+
+    public DOMStore createOperationalDatastore() {
+        InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER",
+                MoreExecutors.sameThreadExecutor(), MoreExecutors.sameThreadExecutor());
+        schemaService.registerSchemaContextListener(store);
+        return store;
+    }
+
+    public DOMDataBroker createDOMDataBroker() {
+        return new DOMDataBrokerImpl(getDatastores(), getCommitCoordinatorExecutor());
+    }
+
+    public ListeningExecutorService getCommitCoordinatorExecutor() {
+        return MoreExecutors.sameThreadExecutor();
+    }
+
+    public DataBroker createDataBroker() {
+        return new ForwardedBindingDataBroker(getDOMDataBroker(), bindingToNormalized, schemaService );
+    }
+
+    public ForwardedBackwardsCompatibleDataBroker createBackwardsCompatibleDataBroker() {
+        return new ForwardedBackwardsCompatibleDataBroker(getDOMDataBroker(), bindingToNormalized, getSchemaService(), MoreExecutors.sameThreadExecutor());
+    }
+
+    private SchemaService getSchemaService() {
+        return schemaService;
+    }
+
+    private DOMDataBroker getDOMDataBroker() {
+        if(domDataBroker == null) {
+            domDataBroker = createDOMDataBroker();
+        }
+        return domDataBroker;
+    }
+
+    private synchronized ImmutableMap<LogicalDatastoreType, DOMStore> getDatastores() {
+        if (datastores == null) {
+            datastores = createDatastores();
+        }
+        return datastores;
+    }
+
+    public void updateSchema(final SchemaContext ctx) {
+        schemaService.changeSchema(ctx);
+        mappingService.onGlobalContextUpdated(ctx);
+    }
+
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/FRMTest.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/FRMTest.java
new file mode 100644 (file)
index 0000000..811d6ca
--- /dev/null
@@ -0,0 +1,42 @@
+package test.mock.util;
+
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
+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.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.Collections;
+import java.util.concurrent.ExecutionException;
+
+public abstract class FRMTest extends AbstractDataBrokerTest{
+
+    public void addFlowCapableNode(NodeKey nodeKey) throws ExecutionException, InterruptedException {
+        Nodes nodes = new NodesBuilder().setNode(Collections.<Node>emptyList()).build();
+        InstanceIdentifier<Node> flowNodeIdentifier = InstanceIdentifier.create(Nodes.class)
+                .child(Node.class, nodeKey);
+
+        FlowCapableNodeBuilder fcnBuilder = new FlowCapableNodeBuilder();
+        NodeBuilder nodeBuilder = new NodeBuilder();
+        nodeBuilder.setKey(nodeKey);
+        nodeBuilder.addAugmentation(FlowCapableNode.class, fcnBuilder.build());
+
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class), nodes);
+        writeTx.put(LogicalDatastoreType.OPERATIONAL, flowNodeIdentifier, nodeBuilder.build());
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Nodes.class), nodes);
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, flowNodeIdentifier, nodeBuilder.build());
+        assertCommit(writeTx.submit());
+    }
+
+    public void removeNode(NodeKey nodeKey) throws ExecutionException, InterruptedException {
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.delete(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class).child(Node.class, nodeKey));
+        writeTx.submit().get();
+    }
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/MockSchemaService.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/MockSchemaService.java
new file mode 100644 (file)
index 0000000..b4876a3
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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 test.mock.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.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;
+
+@SuppressWarnings("deprecation")
+public final class MockSchemaService implements SchemaService, SchemaContextProvider {
+
+    private SchemaContext schemaContext;
+
+    ListenerRegistry<SchemaContextListener> listeners = ListenerRegistry.create();
+
+    @Override
+    public void addModule(final Module module) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public synchronized SchemaContext getGlobalContext() {
+        return schemaContext;
+    }
+
+    @Override
+    public synchronized SchemaContext getSessionContext() {
+        return schemaContext;
+    }
+
+    @Override
+    public ListenerRegistration<SchemaContextListener> registerSchemaContextListener(
+            final SchemaContextListener listener) {
+        return listeners.register(listener);
+    }
+
+    @Override
+    public void removeModule(final Module module) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public synchronized SchemaContext getSchemaContext() {
+        return schemaContext;
+    }
+
+    public synchronized void changeSchema(final SchemaContext newContext) {
+        schemaContext = newContext;
+        for (ListenerRegistration<SchemaContextListener> listener : listeners) {
+            listener.getInstance().onGlobalContextUpdated(schemaContext);
+        }
+    }
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/RpcProviderRegistryMock.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/RpcProviderRegistryMock.java
new file mode 100644 (file)
index 0000000..ff17a0c
--- /dev/null
@@ -0,0 +1,42 @@
+package test.mock.util;
+
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+
+public class RpcProviderRegistryMock implements RpcProviderRegistry {
+    @Override
+    public <T extends RpcService> BindingAwareBroker.RpcRegistration<T> addRpcImplementation(Class<T> serviceInterface, T implementation) throws IllegalStateException {
+        return null;
+    }
+
+    @Override
+    public <T extends RpcService> BindingAwareBroker.RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> serviceInterface, T implementation) throws IllegalStateException {
+        return null;
+    }
+
+    @Override
+    public <L extends RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>> ListenerRegistration<L> registerRouteChangeListener(L listener) {
+        return null;
+    }
+
+    @Override
+    public <T extends RpcService> T getRpcService(Class<T> serviceInterface) {
+        if (serviceInterface.equals(SalFlowService.class)) {
+            return (T) new SalFlowServiceMock();
+        } else if (serviceInterface.equals(SalGroupService.class)) {
+            return (T) new SalGroupServiceMock();
+        } else if (serviceInterface.equals(SalMeterService.class)) {
+            return (T) new SalMeterServiceMock();
+        } else {
+            return null;
+        }
+    }
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalFlowServiceMock.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalFlowServiceMock.java
new file mode 100644 (file)
index 0000000..4bddc69
--- /dev/null
@@ -0,0 +1,51 @@
+package test.mock.util;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+
+public class SalFlowServiceMock implements SalFlowService{
+    private List<AddFlowInput> addFlowCalls = new ArrayList<>();
+    private List<RemoveFlowInput> removeFlowCalls = new ArrayList<>();
+    private List<UpdateFlowInput> updateFlowCalls = new ArrayList<>();
+
+    @Override
+    public Future<RpcResult<AddFlowOutput>> addFlow(AddFlowInput input) {
+        addFlowCalls.add(input);
+        return null;
+    }
+
+
+    @Override
+    public Future<RpcResult<RemoveFlowOutput>> removeFlow(RemoveFlowInput input) {
+        removeFlowCalls.add(input);
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<UpdateFlowOutput>> updateFlow(UpdateFlowInput input) {
+        updateFlowCalls.add(input);
+        return null;
+    }
+
+    public List<AddFlowInput> getAddFlowCalls() {
+        return addFlowCalls;
+    }
+
+    public List<RemoveFlowInput> getRemoveFlowCalls() {
+        return removeFlowCalls;
+    }
+
+    public List<UpdateFlowInput> getUpdateFlowCalls() {
+        return updateFlowCalls;
+    }
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalGroupServiceMock.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalGroupServiceMock.java
new file mode 100644 (file)
index 0000000..9fa7b76
--- /dev/null
@@ -0,0 +1,50 @@
+package test.mock.util;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+
+public class SalGroupServiceMock implements SalGroupService {
+    private List<AddGroupInput> addGroupCalls = new ArrayList<>();
+    private List<RemoveGroupInput> removeGroupCalls = new ArrayList<>();
+    private List<UpdateGroupInput> updateGroupCalls = new ArrayList<>();
+
+    @Override
+    public Future<RpcResult<AddGroupOutput>> addGroup(AddGroupInput input) {
+        addGroupCalls.add(input);
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<RemoveGroupOutput>> removeGroup(RemoveGroupInput input) {
+        removeGroupCalls.add(input);
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<UpdateGroupOutput>> updateGroup(UpdateGroupInput input) {
+        updateGroupCalls.add(input);
+        return null;
+    }
+
+    public List<AddGroupInput> getAddGroupCalls() {
+        return addGroupCalls;
+    }
+
+    public List<RemoveGroupInput> getRemoveGroupCalls() {
+        return removeGroupCalls;
+    }
+
+    public List<UpdateGroupInput> getUpdateGroupCalls() {
+        return updateGroupCalls;
+    }
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalMeterServiceMock.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalMeterServiceMock.java
new file mode 100644 (file)
index 0000000..fb053cb
--- /dev/null
@@ -0,0 +1,50 @@
+package test.mock.util;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterOutput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+
+public class SalMeterServiceMock implements SalMeterService {
+    private List<AddMeterInput> addMeterCalls = new ArrayList<>();
+    private List<RemoveMeterInput> removeMeterCalls = new ArrayList<>();
+    private List<UpdateMeterInput> updateMeterCalls = new ArrayList<>();
+
+    @Override
+    public Future<RpcResult<AddMeterOutput>> addMeter(AddMeterInput input) {
+        addMeterCalls.add(input);
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<RemoveMeterOutput>> removeMeter(RemoveMeterInput input) {
+        removeMeterCalls.add(input);
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<UpdateMeterOutput>> updateMeter(UpdateMeterInput input) {
+        updateMeterCalls.add(input);
+        return null;
+    }
+
+    public List<AddMeterInput> getAddMeterCalls() {
+        return addMeterCalls;
+    }
+
+    public List<RemoveMeterInput> getRemoveMeterCalls() {
+        return removeMeterCalls;
+    }
+
+    public List<UpdateMeterInput> getUpdateMeterCalls() {
+        return updateMeterCalls;
+    }
+}
index c58f6cb6abe414ec1778943a5d7bb0563920ca28..7664a9bfe4bc37db0241a37f5c3d4983d7435b28 100644 (file)
                 <module>
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:inmemory-datastore-provider">prefix:inmemory-config-datastore-provider</type>
                     <name>config-store-service</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>
+                    <inmemory-config-datastore-provider xmlns="urn:opendaylight:params:xml:ns:yang:controller:inmemory-datastore-provider">
+                        <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>
+                    </inmemory-config-datastore-provider>
                 </module>
 
                 <module>
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:inmemory-datastore-provider">prefix:inmemory-operational-datastore-provider</type>
                     <name>operational-store-service</name>
-                    <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>
-                    </operational-schema-service>
+                    <inmemory-operational-datastore-provider xmlns="urn:opendaylight:params:xml:ns:yang:controller:inmemory-datastore-provider">
+                        <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>
+                    </inmemory-operational-datastore-provider>
                 </module>
                 <!--
                      Tree-based in-memory data store. This is the data store which is currently
index 605cb9004a65235dd6cf66b0ff065514f54ad183..5a40022963f9b35520cc47148e0d777f5693c7b7 100644 (file)
@@ -122,10 +122,15 @@ module flow-node-inventory {
             uses meter:meter;
         }
     }
-    
-    
-    grouping flow-node {
 
+    grouping ip-address-grouping {
+        leaf ip-address {
+            description "IP address of a flow capable node.";
+            type inet:ip-address;
+        }
+    }
+
+    grouping flow-node {
         leaf manufacturer {
             type string;
         }
@@ -145,6 +150,7 @@ module flow-node-inventory {
         uses tables;
         uses group:groups;
         uses meters;
+        uses ip-address-grouping;
         // TODO: ports
         
         container supported-match-types {
@@ -197,7 +203,7 @@ module flow-node-inventory {
             
         }
     }
-    
+
     grouping flow-node-connector {
 
         uses port:flow-capable-port;
index 6c6760d789a086157bdb35a0a66d620db8057d3c..ce830eaa62d3e1f23c288f1969b1e79969252cf7 100644 (file)
@@ -77,6 +77,7 @@
 
     <!-- XSQL -->
     <module>sal-dom-xsql</module>
+    <module>sal-dom-xsql-config</module>
 
     <!-- Yang Test Models for MD-SAL -->
     <module>sal-test-model</module>
                     </goals>
                   </pluginExecutionFilter>
                   <action>
-                    <ignore></ignore>
+                    <ignore/>
                   </action>
                 </pluginExecution>
                 <pluginExecution>
                     </goals>
                   </pluginExecutionFilter>
                   <action>
-                    <ignore></ignore>
+                    <ignore/>
                   </action>
                 </pluginExecution>
               </pluginExecutions>
       </modules>
     </profile>
   </profiles>
-</project>
+</project>
\ No newline at end of file
index 3dcc546426165ac578486c5dd528b7b8cb4d0766..325005b239f83cbdf2a28bd7e01fbd1e88eb1ebe 100644 (file)
@@ -11,9 +11,9 @@
 
   <dependencies>
     <dependency>
-      <groupId>com.google.protobuf</groupId>
-      <artifactId>protobuf-java</artifactId>
-      <version>2.5.0</version>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-clustering-commons</artifactId>
+      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>com.google.guava</groupId>
       <artifactId>scala-library</artifactId>
     </dependency>
 
-    <!-- Test Dependencies -->
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.typesafe.akka</groupId>
+      <artifactId>akka-slf4j_${scala.version}</artifactId>
+    </dependency>
+
+
+      <!-- Test Dependencies -->
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
         <artifactId>jacoco-maven-plugin</artifactId>
         <configuration>
           <includes>
-            <include>org.opendaylight.controller.*</include>
+            <include>org/opendaylight/controller/cluster/**/*</include>
           </includes>
+          <excludes>
+              <exclude>org/opendaylight/controller/cluster/raft/protobuff/**/*</exclude>
+              <exclude>org/opendaylight/controller/cluster/example/**/*</exclude>
+          </excludes>
           <check>false</check>
         </configuration>
         <executions>
index 560d5fc19461db3dc49c24a78c227659f4978576..db3e683130952ec9baeb785ec2feecd04b89a8a0 100644 (file)
@@ -9,9 +9,9 @@
 package org.opendaylight.controller.cluster.example.messages;
 
 import com.google.protobuf.GeneratedMessage;
-import org.opendaylight.controller.cluster.example.protobuff.messages.KeyValueMessages;
+import org.opendaylight.controller.protobuff.messages.cluster.example.KeyValueMessages;
 import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
-import org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages;
+import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
 
 import java.io.Serializable;
 import java.util.HashMap;
index ae8b6fe8e3aadc23a33cf57531a43ff9cefed8d4..988789b4011e4f3ba9e9e9abe6b0c3009704c810 100644 (file)
@@ -168,8 +168,7 @@ public abstract class RaftActor extends UntypedPersistentActor {
 
         } else if (message instanceof FindLeader) {
             getSender().tell(
-                new FindLeaderReply(
-                    context.getPeerAddress(currentBehavior.getLeaderId())),
+                new FindLeaderReply(getLeaderAddress()),
                 getSelf()
             );
 
@@ -183,12 +182,6 @@ public abstract class RaftActor extends UntypedPersistentActor {
 
             // TODO: Handle failure in saving the snapshot
 
-        } else if (message instanceof FindLeader){
-
-            getSender().tell(new FindLeaderReply(
-                context.getPeerAddress(currentBehavior.getLeaderId())),
-                getSelf());
-
         } else if (message instanceof AddRaftPeer){
 
             // FIXME : Do not add raft peers like this.
@@ -269,18 +262,9 @@ public abstract class RaftActor extends UntypedPersistentActor {
      * @return A reference to the leader if known, null otherwise
      */
     protected ActorSelection getLeader(){
-        String leaderId = currentBehavior.getLeaderId();
-        if (leaderId == null) {
-            return null;
-        }
-        String peerAddress = context.getPeerAddress(leaderId);
-        LOG.debug("getLeader leaderId = " + leaderId + " peerAddress = "
-            + peerAddress);
+        String leaderAddress = getLeaderAddress();
 
-        if(peerAddress == null){
-            return null;
-        }
-        return context.actorSelection(peerAddress);
+        return context.actorSelection(leaderAddress);
     }
 
     /**
@@ -424,6 +408,21 @@ public abstract class RaftActor extends UntypedPersistentActor {
         deleteMessages(sequenceNumber);
     }
 
+    private String getLeaderAddress(){
+        if(isLeader()){
+            return getSelf().path().toString();
+        }
+        String leaderId = currentBehavior.getLeaderId();
+        if (leaderId == null) {
+            return null;
+        }
+        String peerAddress = context.getPeerAddress(leaderId);
+        LOG.debug("getLeaderAddress leaderId = " + leaderId + " peerAddress = "
+            + peerAddress);
+
+        return peerAddress;
+    }
+
 
     private class ReplicatedLogImpl extends AbstractReplicatedLogImpl {
 
index a60aea46e82965d0ded03eb7464941bf1a62f4af..98dd0d46531cadef35f8832a89237a1a95ae44fd 100644 (file)
@@ -8,6 +8,8 @@
 
 package org.opendaylight.controller.cluster.raft.client.messages;
 
-public class FindLeader {
+import java.io.Serializable;
+
+public class FindLeader implements Serializable{
 
 }
index b36ef112b364371d01d9e7f411fdf27761938606..64c73508960144ab3f0095ba3af34c897217c336 100644 (file)
@@ -8,7 +8,9 @@
 
 package org.opendaylight.controller.cluster.raft.client.messages;
 
-public class FindLeaderReply {
+import java.io.Serializable;
+
+public class FindLeaderReply implements Serializable {
     private final String leaderActor;
 
     public FindLeaderReply(String leaderActor) {
index 94366efd5e897657744df37b0a475a847273e1b4..6665d7549b0d82abe752bcd50aed1826455b331e 100644 (file)
@@ -12,7 +12,7 @@ import com.google.protobuf.GeneratedMessage;
 import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
 import org.opendaylight.controller.cluster.raft.ReplicatedLogImplEntry;
 import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
-import org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages;
+import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
 
 import java.util.ArrayList;
 import java.util.Iterator;
index 9a251cd64586741de2ec69ca288dc21189ca027e..502c338f2298ea34b443d0b0f1e8d3a4d36df721 100644 (file)
@@ -10,7 +10,7 @@ package org.opendaylight.controller.cluster.raft.protobuff.client.messages;
 
 
 import com.google.protobuf.GeneratedMessage;
-import org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages;
+import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
 
 import java.util.Map;
 
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/protobuff/messages/VotingMessages.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/protobuff/messages/VotingMessages.java
deleted file mode 100644 (file)
index 5b3bd2b..0000000
+++ /dev/null
@@ -1,767 +0,0 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: VotingMessages.proto
-
-package org.opendaylight.controller.cluster.raft.protobuff.messages;
-
-public final class VotingMessages {
-  private VotingMessages() {}
-  public static void registerAllExtensions(
-      com.google.protobuf.ExtensionRegistry registry) {
-  }
-  public interface RequestVoteOrBuilder
-      extends com.google.protobuf.MessageOrBuilder {
-
-    // optional int64 term = 1;
-    /**
-     * <code>optional int64 term = 1;</code>
-     */
-    boolean hasTerm();
-    /**
-     * <code>optional int64 term = 1;</code>
-     */
-    long getTerm();
-
-    // optional string candidateId = 2;
-    /**
-     * <code>optional string candidateId = 2;</code>
-     */
-    boolean hasCandidateId();
-    /**
-     * <code>optional string candidateId = 2;</code>
-     */
-    java.lang.String getCandidateId();
-    /**
-     * <code>optional string candidateId = 2;</code>
-     */
-    com.google.protobuf.ByteString
-        getCandidateIdBytes();
-
-    // optional int64 lastLongIndex = 3;
-    /**
-     * <code>optional int64 lastLongIndex = 3;</code>
-     */
-    boolean hasLastLongIndex();
-    /**
-     * <code>optional int64 lastLongIndex = 3;</code>
-     */
-    long getLastLongIndex();
-
-    // optional int64 lastLongTerm = 4;
-    /**
-     * <code>optional int64 lastLongTerm = 4;</code>
-     */
-    boolean hasLastLongTerm();
-    /**
-     * <code>optional int64 lastLongTerm = 4;</code>
-     */
-    long getLastLongTerm();
-  }
-  /**
-   * Protobuf type {@code org.opendaylight.controller.cluster.raft.RequestVote}
-   */
-  public static final class RequestVote extends
-      com.google.protobuf.GeneratedMessage
-      implements RequestVoteOrBuilder {
-    // Use RequestVote.newBuilder() to construct.
-    private RequestVote(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
-      super(builder);
-      this.unknownFields = builder.getUnknownFields();
-    }
-    private RequestVote(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
-
-    private static final RequestVote defaultInstance;
-    public static RequestVote getDefaultInstance() {
-      return defaultInstance;
-    }
-
-    public RequestVote getDefaultInstanceForType() {
-      return defaultInstance;
-    }
-
-    private final com.google.protobuf.UnknownFieldSet unknownFields;
-    @java.lang.Override
-    public final com.google.protobuf.UnknownFieldSet
-        getUnknownFields() {
-      return this.unknownFields;
-    }
-    private RequestVote(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      initFields();
-      int mutable_bitField0_ = 0;
-      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
-          com.google.protobuf.UnknownFieldSet.newBuilder();
-      try {
-        boolean done = false;
-        while (!done) {
-          int tag = input.readTag();
-          switch (tag) {
-            case 0:
-              done = true;
-              break;
-            default: {
-              if (!parseUnknownField(input, unknownFields,
-                                     extensionRegistry, tag)) {
-                done = true;
-              }
-              break;
-            }
-            case 8: {
-              bitField0_ |= 0x00000001;
-              term_ = input.readInt64();
-              break;
-            }
-            case 18: {
-              bitField0_ |= 0x00000002;
-              candidateId_ = input.readBytes();
-              break;
-            }
-            case 24: {
-              bitField0_ |= 0x00000004;
-              lastLongIndex_ = input.readInt64();
-              break;
-            }
-            case 32: {
-              bitField0_ |= 0x00000008;
-              lastLongTerm_ = input.readInt64();
-              break;
-            }
-          }
-        }
-      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-        throw e.setUnfinishedMessage(this);
-      } catch (java.io.IOException e) {
-        throw new com.google.protobuf.InvalidProtocolBufferException(
-            e.getMessage()).setUnfinishedMessage(this);
-      } finally {
-        this.unknownFields = unknownFields.build();
-        makeExtensionsImmutable();
-      }
-    }
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.internal_static_org_opendaylight_controller_cluster_raft_RequestVote_descriptor;
-    }
-
-    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.internal_static_org_opendaylight_controller_cluster_raft_RequestVote_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote.class, org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote.Builder.class);
-    }
-
-    public static com.google.protobuf.Parser<RequestVote> PARSER =
-        new com.google.protobuf.AbstractParser<RequestVote>() {
-      public RequestVote parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        return new RequestVote(input, extensionRegistry);
-      }
-    };
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<RequestVote> getParserForType() {
-      return PARSER;
-    }
-
-    private int bitField0_;
-    // optional int64 term = 1;
-    public static final int TERM_FIELD_NUMBER = 1;
-    private long term_;
-    /**
-     * <code>optional int64 term = 1;</code>
-     */
-    public boolean hasTerm() {
-      return ((bitField0_ & 0x00000001) == 0x00000001);
-    }
-    /**
-     * <code>optional int64 term = 1;</code>
-     */
-    public long getTerm() {
-      return term_;
-    }
-
-    // optional string candidateId = 2;
-    public static final int CANDIDATEID_FIELD_NUMBER = 2;
-    private java.lang.Object candidateId_;
-    /**
-     * <code>optional string candidateId = 2;</code>
-     */
-    public boolean hasCandidateId() {
-      return ((bitField0_ & 0x00000002) == 0x00000002);
-    }
-    /**
-     * <code>optional string candidateId = 2;</code>
-     */
-    public java.lang.String getCandidateId() {
-      java.lang.Object ref = candidateId_;
-      if (ref instanceof java.lang.String) {
-        return (java.lang.String) ref;
-      } else {
-        com.google.protobuf.ByteString bs = 
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        if (bs.isValidUtf8()) {
-          candidateId_ = s;
-        }
-        return s;
-      }
-    }
-    /**
-     * <code>optional string candidateId = 2;</code>
-     */
-    public com.google.protobuf.ByteString
-        getCandidateIdBytes() {
-      java.lang.Object ref = candidateId_;
-      if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        candidateId_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
-    }
-
-    // optional int64 lastLongIndex = 3;
-    public static final int LASTLONGINDEX_FIELD_NUMBER = 3;
-    private long lastLongIndex_;
-    /**
-     * <code>optional int64 lastLongIndex = 3;</code>
-     */
-    public boolean hasLastLongIndex() {
-      return ((bitField0_ & 0x00000004) == 0x00000004);
-    }
-    /**
-     * <code>optional int64 lastLongIndex = 3;</code>
-     */
-    public long getLastLongIndex() {
-      return lastLongIndex_;
-    }
-
-    // optional int64 lastLongTerm = 4;
-    public static final int LASTLONGTERM_FIELD_NUMBER = 4;
-    private long lastLongTerm_;
-    /**
-     * <code>optional int64 lastLongTerm = 4;</code>
-     */
-    public boolean hasLastLongTerm() {
-      return ((bitField0_ & 0x00000008) == 0x00000008);
-    }
-    /**
-     * <code>optional int64 lastLongTerm = 4;</code>
-     */
-    public long getLastLongTerm() {
-      return lastLongTerm_;
-    }
-
-    private void initFields() {
-      term_ = 0L;
-      candidateId_ = "";
-      lastLongIndex_ = 0L;
-      lastLongTerm_ = 0L;
-    }
-    private byte memoizedIsInitialized = -1;
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized != -1) return isInitialized == 1;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      getSerializedSize();
-      if (((bitField0_ & 0x00000001) == 0x00000001)) {
-        output.writeInt64(1, term_);
-      }
-      if (((bitField0_ & 0x00000002) == 0x00000002)) {
-        output.writeBytes(2, getCandidateIdBytes());
-      }
-      if (((bitField0_ & 0x00000004) == 0x00000004)) {
-        output.writeInt64(3, lastLongIndex_);
-      }
-      if (((bitField0_ & 0x00000008) == 0x00000008)) {
-        output.writeInt64(4, lastLongTerm_);
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    private int memoizedSerializedSize = -1;
-    public int getSerializedSize() {
-      int size = memoizedSerializedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      if (((bitField0_ & 0x00000001) == 0x00000001)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(1, term_);
-      }
-      if (((bitField0_ & 0x00000002) == 0x00000002)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeBytesSize(2, getCandidateIdBytes());
-      }
-      if (((bitField0_ & 0x00000004) == 0x00000004)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(3, lastLongIndex_);
-      }
-      if (((bitField0_ & 0x00000008) == 0x00000008)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(4, lastLongTerm_);
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSerializedSize = size;
-      return size;
-    }
-
-    private static final long serialVersionUID = 0L;
-    @java.lang.Override
-    protected java.lang.Object writeReplace()
-        throws java.io.ObjectStreamException {
-      return super.writeReplace();
-    }
-
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return PARSER.parseFrom(input);
-    }
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return PARSER.parseFrom(input, extensionRegistry);
-    }
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return PARSER.parseDelimitedFrom(input);
-    }
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return PARSER.parseDelimitedFrom(input, extensionRegistry);
-    }
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return PARSER.parseFrom(input);
-    }
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return PARSER.parseFrom(input, extensionRegistry);
-    }
-
-    public static Builder newBuilder() { return Builder.create(); }
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder(org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote prototype) {
-      return newBuilder().mergeFrom(prototype);
-    }
-    public Builder toBuilder() { return newBuilder(this); }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * Protobuf type {@code org.opendaylight.controller.cluster.raft.RequestVote}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessage.Builder<Builder>
-       implements org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVoteOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.internal_static_org_opendaylight_controller_cluster_raft_RequestVote_descriptor;
-      }
-
-      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.internal_static_org_opendaylight_controller_cluster_raft_RequestVote_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote.class, org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote.Builder.class);
-      }
-
-      // Construct using org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote.newBuilder()
-      private Builder() {
-        maybeForceBuilderInitialization();
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
-        super(parent);
-        maybeForceBuilderInitialization();
-      }
-      private void maybeForceBuilderInitialization() {
-        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
-        }
-      }
-      private static Builder create() {
-        return new Builder();
-      }
-
-      public Builder clear() {
-        super.clear();
-        term_ = 0L;
-        bitField0_ = (bitField0_ & ~0x00000001);
-        candidateId_ = "";
-        bitField0_ = (bitField0_ & ~0x00000002);
-        lastLongIndex_ = 0L;
-        bitField0_ = (bitField0_ & ~0x00000004);
-        lastLongTerm_ = 0L;
-        bitField0_ = (bitField0_ & ~0x00000008);
-        return this;
-      }
-
-      public Builder clone() {
-        return create().mergeFrom(buildPartial());
-      }
-
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.internal_static_org_opendaylight_controller_cluster_raft_RequestVote_descriptor;
-      }
-
-      public org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote getDefaultInstanceForType() {
-        return org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote.getDefaultInstance();
-      }
-
-      public org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote build() {
-        org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      public org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote buildPartial() {
-        org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote result = new org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote(this);
-        int from_bitField0_ = bitField0_;
-        int to_bitField0_ = 0;
-        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
-          to_bitField0_ |= 0x00000001;
-        }
-        result.term_ = term_;
-        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
-          to_bitField0_ |= 0x00000002;
-        }
-        result.candidateId_ = candidateId_;
-        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
-          to_bitField0_ |= 0x00000004;
-        }
-        result.lastLongIndex_ = lastLongIndex_;
-        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
-          to_bitField0_ |= 0x00000008;
-        }
-        result.lastLongTerm_ = lastLongTerm_;
-        result.bitField0_ = to_bitField0_;
-        onBuilt();
-        return result;
-      }
-
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote) {
-          return mergeFrom((org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote other) {
-        if (other == org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote.getDefaultInstance()) return this;
-        if (other.hasTerm()) {
-          setTerm(other.getTerm());
-        }
-        if (other.hasCandidateId()) {
-          bitField0_ |= 0x00000002;
-          candidateId_ = other.candidateId_;
-          onChanged();
-        }
-        if (other.hasLastLongIndex()) {
-          setLastLongIndex(other.getLastLongIndex());
-        }
-        if (other.hasLastLongTerm()) {
-          setLastLongTerm(other.getLastLongTerm());
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        return this;
-      }
-
-      public final boolean isInitialized() {
-        return true;
-      }
-
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote parsedMessage = null;
-        try {
-          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (org.opendaylight.controller.cluster.raft.protobuff.messages.VotingMessages.RequestVote) e.getUnfinishedMessage();
-          throw e;
-        } finally {
-          if (parsedMessage != null) {
-            mergeFrom(parsedMessage);
-          }
-        }
-        return this;
-      }
-      private int bitField0_;
-
-      // optional int64 term = 1;
-      private long term_ ;
-      /**
-       * <code>optional int64 term = 1;</code>
-       */
-      public boolean hasTerm() {
-        return ((bitField0_ & 0x00000001) == 0x00000001);
-      }
-      /**
-       * <code>optional int64 term = 1;</code>
-       */
-      public long getTerm() {
-        return term_;
-      }
-      /**
-       * <code>optional int64 term = 1;</code>
-       */
-      public Builder setTerm(long value) {
-        bitField0_ |= 0x00000001;
-        term_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>optional int64 term = 1;</code>
-       */
-      public Builder clearTerm() {
-        bitField0_ = (bitField0_ & ~0x00000001);
-        term_ = 0L;
-        onChanged();
-        return this;
-      }
-
-      // optional string candidateId = 2;
-      private java.lang.Object candidateId_ = "";
-      /**
-       * <code>optional string candidateId = 2;</code>
-       */
-      public boolean hasCandidateId() {
-        return ((bitField0_ & 0x00000002) == 0x00000002);
-      }
-      /**
-       * <code>optional string candidateId = 2;</code>
-       */
-      public java.lang.String getCandidateId() {
-        java.lang.Object ref = candidateId_;
-        if (!(ref instanceof java.lang.String)) {
-          java.lang.String s = ((com.google.protobuf.ByteString) ref)
-              .toStringUtf8();
-          candidateId_ = s;
-          return s;
-        } else {
-          return (java.lang.String) ref;
-        }
-      }
-      /**
-       * <code>optional string candidateId = 2;</code>
-       */
-      public com.google.protobuf.ByteString
-          getCandidateIdBytes() {
-        java.lang.Object ref = candidateId_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          candidateId_ = b;
-          return b;
-        } else {
-          return (com.google.protobuf.ByteString) ref;
-        }
-      }
-      /**
-       * <code>optional string candidateId = 2;</code>
-       */
-      public Builder setCandidateId(
-          java.lang.String value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000002;
-        candidateId_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>optional string candidateId = 2;</code>
-       */
-      public Builder clearCandidateId() {
-        bitField0_ = (bitField0_ & ~0x00000002);
-        candidateId_ = getDefaultInstance().getCandidateId();
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>optional string candidateId = 2;</code>
-       */
-      public Builder setCandidateIdBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000002;
-        candidateId_ = value;
-        onChanged();
-        return this;
-      }
-
-      // optional int64 lastLongIndex = 3;
-      private long lastLongIndex_ ;
-      /**
-       * <code>optional int64 lastLongIndex = 3;</code>
-       */
-      public boolean hasLastLongIndex() {
-        return ((bitField0_ & 0x00000004) == 0x00000004);
-      }
-      /**
-       * <code>optional int64 lastLongIndex = 3;</code>
-       */
-      public long getLastLongIndex() {
-        return lastLongIndex_;
-      }
-      /**
-       * <code>optional int64 lastLongIndex = 3;</code>
-       */
-      public Builder setLastLongIndex(long value) {
-        bitField0_ |= 0x00000004;
-        lastLongIndex_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>optional int64 lastLongIndex = 3;</code>
-       */
-      public Builder clearLastLongIndex() {
-        bitField0_ = (bitField0_ & ~0x00000004);
-        lastLongIndex_ = 0L;
-        onChanged();
-        return this;
-      }
-
-      // optional int64 lastLongTerm = 4;
-      private long lastLongTerm_ ;
-      /**
-       * <code>optional int64 lastLongTerm = 4;</code>
-       */
-      public boolean hasLastLongTerm() {
-        return ((bitField0_ & 0x00000008) == 0x00000008);
-      }
-      /**
-       * <code>optional int64 lastLongTerm = 4;</code>
-       */
-      public long getLastLongTerm() {
-        return lastLongTerm_;
-      }
-      /**
-       * <code>optional int64 lastLongTerm = 4;</code>
-       */
-      public Builder setLastLongTerm(long value) {
-        bitField0_ |= 0x00000008;
-        lastLongTerm_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>optional int64 lastLongTerm = 4;</code>
-       */
-      public Builder clearLastLongTerm() {
-        bitField0_ = (bitField0_ & ~0x00000008);
-        lastLongTerm_ = 0L;
-        onChanged();
-        return this;
-      }
-
-      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.cluster.raft.RequestVote)
-    }
-
-    static {
-      defaultInstance = new RequestVote(true);
-      defaultInstance.initFields();
-    }
-
-    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.cluster.raft.RequestVote)
-  }
-
-  private static com.google.protobuf.Descriptors.Descriptor
-    internal_static_org_opendaylight_controller_cluster_raft_RequestVote_descriptor;
-  private static
-    com.google.protobuf.GeneratedMessage.FieldAccessorTable
-      internal_static_org_opendaylight_controller_cluster_raft_RequestVote_fieldAccessorTable;
-
-  public static com.google.protobuf.Descriptors.FileDescriptor
-      getDescriptor() {
-    return descriptor;
-  }
-  private static com.google.protobuf.Descriptors.FileDescriptor
-      descriptor;
-  static {
-    java.lang.String[] descriptorData = {
-      "\n\024VotingMessages.proto\022(org.opendaylight" +
-      ".controller.cluster.raft\"]\n\013RequestVote\022" +
-      "\014\n\004term\030\001 \001(\003\022\023\n\013candidateId\030\002 \001(\t\022\025\n\rla" +
-      "stLongIndex\030\003 \001(\003\022\024\n\014lastLongTerm\030\004 \001(\003B" +
-      "O\n;org.opendaylight.controller.cluster.r" +
-      "aft.protobuff.messagesB\016VotingMessagesH\001"
-    };
-    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
-      new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
-        public com.google.protobuf.ExtensionRegistry assignDescriptors(
-            com.google.protobuf.Descriptors.FileDescriptor root) {
-          descriptor = root;
-          internal_static_org_opendaylight_controller_cluster_raft_RequestVote_descriptor =
-            getDescriptor().getMessageTypes().get(0);
-          internal_static_org_opendaylight_controller_cluster_raft_RequestVote_fieldAccessorTable = new
-            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
-              internal_static_org_opendaylight_controller_cluster_raft_RequestVote_descriptor,
-              new java.lang.String[] { "Term", "CandidateId", "LastLongIndex", "LastLongTerm", });
-          return null;
-        }
-      };
-    com.google.protobuf.Descriptors.FileDescriptor
-      .internalBuildGeneratedFileFrom(descriptorData,
-        new com.google.protobuf.Descriptors.FileDescriptor[] {
-        }, assigner);
-  }
-
-  // @@protoc_insertion_point(outer_class_scope)
-}
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/resources/VotingMessages.proto b/opendaylight/md-sal/sal-akka-raft/src/main/resources/VotingMessages.proto
deleted file mode 100644 (file)
index 6a45a2b..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.opendaylight.controller.cluster.raft;
-
-option java_package = "org.opendaylight.controller.cluster.raft.protobuff.messages";
-option java_outer_classname = "VotingMessages";
-option optimize_for = SPEED;
-
-message RequestVote {
-    optional int64 term = 1;
-    optional string candidateId = 2;
-    optional int64 lastLongIndex = 3;
-    optional int64 lastLongTerm = 4;
-
-}
index 1971432fb9844f747d39e37c8546c7568632f7c0..ec5381546964d7c8846ed446e4947baebe48380f 100644 (file)
@@ -10,20 +10,26 @@ package org.opendaylight.controller.cluster.raft;
 
 import akka.actor.ActorSystem;
 import akka.testkit.JavaTestKit;
+import org.apache.commons.io.FileUtils;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 
+import java.io.File;
+import java.io.IOException;
+
 public abstract class AbstractActorTest {
     private static ActorSystem system;
 
     @BeforeClass
-    public static void setUpClass() {
+    public static void setUpClass() throws Exception{
+        deleteJournal();
         System.setProperty("shard.persistent", "false");
         system = ActorSystem.create("test");
     }
 
     @AfterClass
-    public static void tearDownClass() {
+    public static void tearDownClass() throws Exception{
+        deleteJournal();
         JavaTestKit.shutdownActorSystem(system);
         system = null;
     }
@@ -32,4 +38,12 @@ public abstract class AbstractActorTest {
         return system;
     }
 
+    protected static void deleteJournal() throws IOException {
+        File journal = new File("journal");
+
+        if(journal.exists()) {
+            FileUtils.deleteDirectory(journal);
+        }
+    }
+
 }
index 70671a6a21ab112b339a07b6ab37b4c56c176b47..ea3c9e759d51744fb2dd36212bf8372e2f06f0c8 100644 (file)
@@ -16,8 +16,8 @@ import akka.event.Logging;
 import akka.event.LoggingAdapter;
 import com.google.protobuf.GeneratedMessage;
 import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
-import org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages;
-import org.opendaylight.controller.cluster.raft.protobuff.messages.MockPayloadMessages;
+import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
+import org.opendaylight.controller.protobuff.messages.cluster.raft.test.MockPayloadMessages;
 import com.google.common.base.Preconditions;
 
 import java.io.Serializable;
diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java
new file mode 100644 (file)
index 0000000..ff0ffeb
--- /dev/null
@@ -0,0 +1,137 @@
+package org.opendaylight.controller.cluster.raft;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import akka.event.Logging;
+import akka.japi.Creator;
+import akka.testkit.JavaTestKit;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.raft.client.messages.FindLeader;
+import org.opendaylight.controller.cluster.raft.client.messages.FindLeaderReply;
+
+import java.util.Collections;
+import java.util.Map;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class RaftActorTest extends AbstractActorTest {
+
+
+    public static class MockRaftActor extends RaftActor {
+
+        public MockRaftActor(String id,
+            Map<String, String> peerAddresses) {
+            super(id, peerAddresses);
+        }
+
+        public static Props props(final String id, final Map<String, String> peerAddresses){
+            return Props.create(new Creator<MockRaftActor>(){
+
+                @Override public MockRaftActor create() throws Exception {
+                    return new MockRaftActor(id, peerAddresses);
+                }
+            });
+        }
+
+        @Override protected void applyState(ActorRef clientActor,
+            String identifier,
+            Object data) {
+        }
+
+        @Override protected Object createSnapshot() {
+            throw new UnsupportedOperationException("createSnapshot");
+        }
+
+        @Override protected void applySnapshot(Object snapshot) {
+            throw new UnsupportedOperationException("applySnapshot");
+        }
+
+        @Override protected void onStateChanged() {
+        }
+
+        @Override public String persistenceId() {
+            return this.getId();
+        }
+
+    }
+
+
+    private static class RaftActorTestKit extends JavaTestKit {
+        private final ActorRef raftActor;
+
+        public RaftActorTestKit(ActorSystem actorSystem, String actorName) {
+            super(actorSystem);
+
+            raftActor = this.getSystem()
+                .actorOf(MockRaftActor.props(actorName,
+                    Collections.EMPTY_MAP), actorName);
+
+        }
+
+
+        public boolean waitForStartup(){
+            // Wait for a specific log message to show up
+            return
+                new JavaTestKit.EventFilter<Boolean>(Logging.Info.class
+                ) {
+                    protected Boolean run() {
+                        return true;
+                    }
+                }.from(raftActor.path().toString())
+                    .message("Switching from state Candidate to Leader")
+                    .occurrences(1).exec();
+
+
+        }
+
+        public void findLeader(final String expectedLeader){
+
+
+            new Within(duration("1 seconds")) {
+                protected void run() {
+
+                    raftActor.tell(new FindLeader(), getRef());
+
+                    String s = new ExpectMsg<String>(duration("1 seconds"),
+                        "findLeader") {
+                        // do not put code outside this method, will run afterwards
+                        protected String match(Object in) {
+                            if (in instanceof FindLeaderReply) {
+                                return ((FindLeaderReply) in).getLeaderActor();
+                            } else {
+                                throw noMatch();
+                            }
+                        }
+                    }.get();// this extracts the received message
+
+                    assertEquals(expectedLeader, s);
+
+                }
+
+
+            };
+        }
+
+        public ActorRef getRaftActor() {
+            return raftActor;
+        }
+
+    }
+
+
+    @Test
+    public void testConstruction() {
+        boolean started = new RaftActorTestKit(getSystem(), "testConstruction").waitForStartup();
+        assertEquals(true, started);
+    }
+
+    @Test
+    public void testFindLeaderWhenLeaderIsSelf(){
+        RaftActorTestKit kit = new RaftActorTestKit(getSystem(), "testFindLeader");
+        kit.waitForStartup();
+        kit.findLeader(kit.getRaftActor().path().toString());
+    }
+
+
+}
index dbe7508cc8c185a33a35fcf072498041b589854c..2b753004c48265620628fdbc58a1e41a96a65c51 100644 (file)
@@ -1,6 +1,6 @@
 akka {
-
     loglevel = "DEBUG"
+    loggers = ["akka.testkit.TestEventListener", "akka.event.slf4j.Slf4jLogger"]
 
     actor {
         # enable to test serialization only.
@@ -12,6 +12,7 @@ akka {
         }
 
         serialization-bindings {
+            "org.opendaylight.controller.cluster.raft.client.messages.FindLeader" = java
             "org.opendaylight.controller.cluster.raft.ReplicatedLogImplEntry" = java
             "com.google.protobuf.Message" = proto
             "com.google.protobuf.GeneratedMessage" = proto
index 24ec89ebb27da82f92fa569216ee7db5fc07d6cc..c71aa049c0622397773d5547faa773aac45ad7fd 100644 (file)
@@ -1,18 +1,41 @@
+/*
+ * 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.sal.binding.api;
 
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
+/**
+ * A chain of transactions.
+ * <p>
+ * For more information about transaction chaining and transaction chains
+ * see {@link TransactionChain}.
+ *
+ * @see TransactionChain
+ *
+ */
 public interface BindingTransactionChain extends TransactionFactory, TransactionChain<InstanceIdentifier<?>, DataObject> {
-
+    /**
+     * {@inheritDoc}
+     */
     @Override
     ReadOnlyTransaction newReadOnlyTransaction();
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     ReadWriteTransaction newReadWriteTransaction();
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     WriteTransaction newWriteOnlyTransaction();
-
 }
index 619a08eac5f30a6f3a7ff7f5f154b1be4c74bdbc..cc8deb81b31777ee6dd4aa3b5bf19a97f3ababb5 100644 (file)
@@ -20,22 +20,39 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
  * subscribe for changes to data under a given branch of the tree.
  * <p>
  * For more information on usage, please see the documentation in {@link AsyncDataBroker}.
+ *
+ * @see AsyncDataBroker
+ * @see TransactionChainFactory
  */
 public interface DataBroker extends TransactionFactory, AsyncDataBroker<InstanceIdentifier<?>, DataObject, DataChangeListener>, BindingService, TransactionChainFactory<InstanceIdentifier<?>, DataObject> {
-
+    /**
+     * {@inheritDoc}
+     */
     @Override
     ReadOnlyTransaction newReadOnlyTransaction();
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     ReadWriteTransaction newReadWriteTransaction();
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     WriteTransaction newWriteOnlyTransaction();
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     ListenerRegistration<DataChangeListener> registerDataChangeListener(LogicalDatastoreType store,
             InstanceIdentifier<?> path, DataChangeListener listener, DataChangeScope triggeringScope);
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     BindingTransactionChain createTransactionChain(TransactionChainListener listener);
 }
index f843b23f9b2cc9d15a55c2d9a4373cde3baffecc..d4b1d84aa77c5d648291dba26025bad8511618a8 100644 (file)
@@ -9,15 +9,14 @@ package org.opendaylight.controller.md.sal.binding.impl;
 
 import com.google.common.base.Objects;
 import com.google.common.base.Optional;
-import java.util.ArrayList;
+
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
@@ -88,7 +87,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
             final Map<YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized) {
         Map<InstanceIdentifier<?>, DataObject> newMap = new HashMap<>();
 
-        for (Map.Entry<YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> entry : sortedEntries(normalized)) {
+        for (Map.Entry<YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> entry : normalized.entrySet()) {
             try {
                 Optional<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> potential = getCodec().toBinding(entry);
                 if (potential.isPresent()) {
@@ -102,38 +101,6 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         return newMap;
     }
 
-    private static final Comparator<Entry<YangInstanceIdentifier, ?>> MAP_ENTRY_COMPARATOR = new Comparator<Entry<YangInstanceIdentifier, ?>>() {
-        @Override
-        public int compare(final Entry<YangInstanceIdentifier, ?> left, final Entry<YangInstanceIdentifier, ?> right) {
-            final Iterator<?> li = left.getKey().getPathArguments().iterator();
-            final Iterator<?> ri = right.getKey().getPathArguments().iterator();
-
-            // Iterate until left is exhausted...
-            while (li.hasNext()) {
-                if (!ri.hasNext()) {
-                    // Left is deeper
-                    return 1;
-                }
-
-                li.next();
-                ri.next();
-            }
-
-            // Check if right is exhausted
-            return ri.hasNext() ? -1 : 0;
-        }
-    };
-
-    private static <T> Iterable<Entry<YangInstanceIdentifier, T>> sortedEntries(final Map<YangInstanceIdentifier, T> map) {
-        if (!map.isEmpty()) {
-            ArrayList<Entry<YangInstanceIdentifier, T>> entries = new ArrayList<>(map.entrySet());
-            Collections.sort(entries, MAP_ENTRY_COMPARATOR);
-            return entries;
-        } else {
-            return Collections.emptySet();
-        }
-    }
-
     protected Set<InstanceIdentifier<?>> toBinding(final InstanceIdentifier<?> path,
             final Set<YangInstanceIdentifier> normalized) {
         Set<InstanceIdentifier<?>> hashSet = new HashSet<>();
@@ -178,6 +145,11 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         public void onDataChanged(final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
             bindingDataChangeListener.onDataChanged(new TranslatedDataChangeEvent(change, path));
         }
+
+        @Override
+        public String toString() {
+            return bindingDataChangeListener.getClass().getName();
+        }
     }
 
     private class TranslatedDataChangeEvent implements AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> {
index 9ad35fcdda85347de6a7680c4f91dabbeed8e2a7..d7314e5362873b0db2e3fa6a2a20b93f527725d2 100644 (file)
@@ -13,6 +13,8 @@ import com.google.common.base.Optional;
 import java.util.Iterator;
 import java.util.Map.Entry;
 
+import javax.annotation.Nonnull;
+
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
@@ -21,6 +23,7 @@ import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadi
 import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
@@ -43,20 +46,19 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener,AutoC
 
     }
 
-    public org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier toNormalized(
-            final InstanceIdentifier<? extends DataObject> binding) {
+    public YangInstanceIdentifier toNormalized(final InstanceIdentifier<? extends DataObject> binding) {
         return codecRegistry.toYangInstanceIdentifier(binding);
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    public Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
+    public Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
             final InstanceIdentifier<? extends DataObject> bindingPath, final DataObject bindingObject) {
         return codecRegistry.toNormalizedNode((InstanceIdentifier) bindingPath, bindingObject);
 
     }
 
-    public Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
-            final Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> binding) {
+    public Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
+            final Entry<InstanceIdentifier<? extends DataObject>, DataObject> binding) {
         return toNormalizedNode(binding.getKey(),binding.getValue());
     }
 
@@ -69,11 +71,10 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener,AutoC
      * augmentation.
      *
      */
-    public Optional<InstanceIdentifier<? extends DataObject>> toBinding(
-            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
+    public Optional<InstanceIdentifier<? extends DataObject>> toBinding(final YangInstanceIdentifier normalized)
                     throws DeserializationException {
         try {
-            return  Optional.<InstanceIdentifier<? extends DataObject>>of(codecRegistry.fromYangInstanceIdentifier(normalized));
+            return Optional.<InstanceIdentifier<? extends DataObject>>fromNullable(codecRegistry.fromYangInstanceIdentifier(normalized));
         } catch (IllegalArgumentException e) {
             return Optional.absent();
         }
@@ -83,14 +84,26 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener,AutoC
         return legacyToNormalized;
     }
 
-    @SuppressWarnings("unchecked")
-    public Optional<Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject>> toBinding(
-            final Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized)
+    public Optional<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> toBinding(
+            final @Nonnull Entry<YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized)
                     throws DeserializationException {
         try {
-            @SuppressWarnings("rawtypes")
-            Entry binding = codecRegistry.fromNormalizedNode(normalized.getKey(), normalized.getValue());
-            return Optional.<Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject>>fromNullable(binding);
+            /*
+             * This cast is required, due to generics behaviour in openjdk / oracle javac
+             *
+             * InstanceIdentifier has definition InstanceIdentifier<T extends DataObject>,
+             * this means '?' is always Â <? extends DataObject>. Eclipse compiler
+             * is able to determine this relationship and treats
+             * Entry<InstanceIdentifier<?>,DataObject> and Entry<InstanceIdentifier<? extends DataObject,DataObject>
+             * as assignable. However openjdk / oracle javac treats this two types
+             * as incompatible and issues a compile error.
+             *
+             * It is safe to  loose generic information and cast it to other generic signature.
+             *
+             */
+            @SuppressWarnings({ "unchecked", "rawtypes" })
+            final Entry<InstanceIdentifier<? extends DataObject>, DataObject> binding = (Entry) codecRegistry.fromNormalizedNode(normalized.getKey(), normalized.getValue());
+            return Optional.fromNullable(binding);
         } catch (IllegalArgumentException e) {
             return Optional.absent();
         }
@@ -112,7 +125,7 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener,AutoC
      * @param path DOM Path
      * @return Node with defaults set on.
      */
-    public NormalizedNode<?, ?> getDefaultNodeFor(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier path) {
+    public NormalizedNode<?, ?> getDefaultNodeFor(final YangInstanceIdentifier path) {
         Iterator<PathArgument> iterator = path.getPathArguments().iterator();
         DataNormalizationOperation<?> currentOp = legacyToNormalized.getRootOperation();
         while (iterator.hasNext()) {
@@ -131,7 +144,7 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener,AutoC
     }
 
     @Override
-    public void close() throws Exception {
+    public void close() {
         // NOOP Intentionally
     }
 }
index ab6d56c15a5bdb696f5cb136965519206f40ef79..6be5f2d481515c1dd0b6fb140ff63fdf2e9d019b 100644 (file)
@@ -3,6 +3,12 @@ package org.opendaylight.controller.sal.binding.impl.connect.dom;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
 
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
 import java.lang.ref.WeakReference;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
@@ -21,13 +27,13 @@ import org.opendaylight.controller.sal.core.api.RpcImplementation;
 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
 import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
 import org.opendaylight.yangtools.concepts.ObjectRegistration;
+import org.opendaylight.yangtools.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
 import org.opendaylight.yangtools.yang.binding.BindingMapping;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
-import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
@@ -35,12 +41,6 @@ import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMapping
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Function;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-
 class DomToBindingRpcForwarder implements RpcImplementation, InvocationHandler {
 
     private final Logger LOG = LoggerFactory.getLogger(DomToBindingRpcForwarder.class);
@@ -65,8 +65,8 @@ class DomToBindingRpcForwarder implements RpcImplementation, InvocationHandler {
     static {
         try {
             EQUALS_METHOD = Object.class.getMethod("equals", Object.class);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new ExceptionInInitializerError(e);
         }
     }
 
@@ -94,7 +94,7 @@ class DomToBindingRpcForwarder implements RpcImplementation, InvocationHandler {
     }
 
     /**
-     * Constructor for Routed RPC Forwareder.
+     * Constructor for Routed RPC Forwarder.
      *
      * @param service
      * @param context
index f91e356b8e2a1d883a2dfee05142e2250aa4b3be..2ec1c43c9be4c4d65a8a4f0a98a96f305a8f962e 100644 (file)
@@ -1,5 +1,6 @@
 package org.opendaylight.controller.md.sal.binding.impl.test;
 
+import com.google.common.util.concurrent.MoreExecutors;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker;
 import org.opendaylight.controller.md.sal.binding.test.AbstractSchemaAwareTest;
@@ -39,10 +40,17 @@ public class ForwardedBackwardsCompatibleDataBrokerTest extends
         testCustomizer = createDataBrokerTestCustomizer();
 
         domBroker = testCustomizer.createDOMDataBroker();
-        dataBroker = testCustomizer.createBackwardsCompatibleDataBroker();
+        dataBroker = createBackwardsCompatibleDataBroker();
         testCustomizer.updateSchema(context);
     }
 
+    public ForwardedBackwardsCompatibleDataBroker createBackwardsCompatibleDataBroker() {
+        return new ForwardedBackwardsCompatibleDataBroker(domBroker, testCustomizer.getBindingToNormalized(), testCustomizer.getSchemaService(), MoreExecutors
+            .sameThreadExecutor());
+    }
+
+
+
 
     /**
      * The purpose of this test is to exercise the backwards compatible broker
@@ -53,7 +61,7 @@ public class ForwardedBackwardsCompatibleDataBrokerTest extends
      * @see org.opendaylight.controller.md.sal.binding.impl.AbstractReadWriteTransaction#ensureParentsByMerge(org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType, org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, org.opendaylight.yangtools.yang.binding.InstanceIdentifier)
      */
     @Test
-    public void test() throws InterruptedException, ExecutionException {
+    public void testEnsureParentsByMerge() throws InterruptedException, ExecutionException {
         DataModificationTransaction writeTx =
             dataBroker.beginTransaction();
 
index 106fcea0e9f178470c26eab42fe1bf7c36eb4e08..c869b1dbd3e1df95165f46b5ef992bbe4199cafc 100644 (file)
@@ -10,12 +10,9 @@ package org.opendaylight.controller.md.sal.binding.test;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
-
 import javassist.ClassPool;
-
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
-import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker;
 import org.opendaylight.controller.md.sal.binding.impl.ForwardedBindingDataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
@@ -30,7 +27,6 @@ import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeC
 import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
 import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
 import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
-import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 public class DataBrokerTestCustomizer {
@@ -85,18 +81,14 @@ public class DataBrokerTestCustomizer {
         return new ForwardedBindingDataBroker(getDOMDataBroker(), bindingToNormalized, schemaService );
     }
 
-    public ForwardedBackwardsCompatibleDataBroker createBackwardsCompatibleDataBroker() {
-        return new ForwardedBackwardsCompatibleDataBroker(getDOMDataBroker(), bindingToNormalized, getSchemaService(), MoreExecutors.sameThreadExecutor());
+    public BindingToNormalizedNodeCodec getBindingToNormalized() {
+        return bindingToNormalized;
     }
 
-    private SchemaService getSchemaService() {
+    public SchemaService getSchemaService() {
         return schemaService;
     }
 
-    private BindingIndependentMappingService getMappingService() {
-        return mappingService;
-    }
-
     private DOMDataBroker getDOMDataBroker() {
         if(domDataBroker == null) {
             domDataBroker = createDOMDataBroker();
@@ -104,8 +96,8 @@ public class DataBrokerTestCustomizer {
         return domDataBroker;
     }
 
-    private ImmutableMap<LogicalDatastoreType, DOMStore> getDatastores() {
-        if(datastores == null) {
+    private synchronized ImmutableMap<LogicalDatastoreType, DOMStore> getDatastores() {
+        if (datastores == null) {
             datastores = createDatastores();
         }
         return datastores;
index 344694381a222850fb23ccac0cc8415b3296f472..efd35ccfa606d298834cb0eaa05a4d5d393a825a 100644 (file)
@@ -73,6 +73,7 @@ public class TestHelper {
                 mavenBundle(CONTROLLER, "netconf-client").versionAsInProject(), //
                 mavenBundle(CONTROLLER, "netconf-util").versionAsInProject(), //
                 mavenBundle(CONTROLLER, "netconf-netty-util").versionAsInProject(), //
+                mavenBundle("org.apache.sshd", "sshd-core").versionAsInProject(), //
                 mavenBundle("org.openexi", "nagasena").versionAsInProject(), //
                 mavenBundle("org.openexi", "nagasena-rta").versionAsInProject(), //
                 mavenBundle(CONTROLLER + ".thirdparty", "ganymed").versionAsInProject(), //
@@ -99,6 +100,7 @@ public class TestHelper {
                 mavenBundle("org.javassist", "javassist").versionAsInProject(), // //
 
                 mavenBundle(YANGTOOLS, "yang-data-api").versionAsInProject(), // //
+                mavenBundle(YANGTOOLS, "yang-data-util").versionAsInProject(), // //
                 mavenBundle(YANGTOOLS, "yang-data-impl").versionAsInProject(), // //
                 mavenBundle(YANGTOOLS, "yang-model-api").versionAsInProject(), // //
                 mavenBundle(YANGTOOLS, "yang-model-util").versionAsInProject(), // //
index 4419d19f527c9c096718496041dee08933275106..b8980cd0bea46b22676ccec1cb38def91239d275 100644 (file)
 
   <packaging>bundle</packaging>
 
-  <dependencies>
+    <dependencies>
+
+    <dependency>
+        <groupId>com.typesafe.akka</groupId>
+        <artifactId>akka-actor_${scala.version}</artifactId>
+    </dependency>
+
+    <dependency>
+        <groupId>com.typesafe.akka</groupId>
+        <artifactId>akka-cluster_${scala.version}</artifactId>
+    </dependency>
+
+    <dependency>
+        <groupId>com.typesafe.akka</groupId>
+        <artifactId>akka-persistence-experimental_${scala.version}</artifactId>
+    </dependency>
+
+    <dependency>
+        <groupId>com.typesafe.akka</groupId>
+        <artifactId>akka-remote_${scala.version}</artifactId>
+    </dependency>
+
+    <dependency>
+        <groupId>com.typesafe.akka</groupId>
+        <artifactId>akka-testkit_${scala.version}</artifactId>
+    </dependency>
+
+
+    <dependency>
+        <groupId>org.scala-lang</groupId>
+        <artifactId>scala-library</artifactId>
+    </dependency>
+
+
+    <dependency>
+        <groupId>com.typesafe.akka</groupId>
+        <artifactId>akka-slf4j_${scala.version}</artifactId>
+    </dependency>
+
+
     <dependency>
       <groupId>com.google.code.findbugs</groupId>
       <artifactId>jsr305</artifactId>
       <artifactId>junit</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-simple</artifactId>
           <artifactId>yang-binding</artifactId>
       </dependency>
 
-      <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>sal-akka-raft</artifactId>
-          <version>1.1-SNAPSHOT</version>
-      </dependency>
 
       <dependency>
           <groupId>com.google.guava</groupId>
           <artifactId>jsr305</artifactId>
           <version>2.0.1</version>
       </dependency>
-
       <dependency>
           <groupId>com.codahale.metrics</groupId>
           <artifactId>metrics-core</artifactId>
-          <version>3.0.1</version>
+      </dependency>
+      <dependency>
+          <groupId>com.codahale.metrics</groupId>
+          <artifactId>metrics-graphite</artifactId>
       </dependency>
   </dependencies>
+  <build>
+      <plugins>
+          <plugin>
+              <groupId>org.jacoco</groupId>
+              <artifactId>jacoco-maven-plugin</artifactId>
+              <configuration>
+                  <includes>
+                      <include>org.opendaylight.controller.*</include>
+                  </includes>
+                  <excludes>
+                      <exclude>org.opendaylight.controller.protobuff.*</exclude>
+                  </excludes>
+                  <check>false</check>
+              </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>
+      </plugins>
+  </build>
 
 </project>
index 17bdb36e569612ef513a787e010aeb8583167984..4e76e37fa25c179ac3f2b196f97ee389261a8c97 100644 (file)
@@ -10,9 +10,9 @@
 
 package org.opendaylight.controller.cluster.datastore.node;
 
-import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
 import org.opendaylight.controller.cluster.datastore.node.utils.PathUtils;
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeSerializer;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
 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;
@@ -29,45 +29,27 @@ public class NormalizedNodeToNodeCodec {
     }
 
     public NormalizedNodeMessages.Container encode(YangInstanceIdentifier id, NormalizedNode node){
+
+        NormalizedNodeMessages.Container.Builder builder = NormalizedNodeMessages.Container.newBuilder();
         String parentPath = "";
 
         if(id != null){
-            parentPath = PathUtils.getParentPath(id.toString());
+            parentPath = PathUtils.getParentPath(PathUtils.toString(id));
         }
 
+        builder.setParentPath(parentPath);
+        if(node != null) {
+            builder.setNormalizedNode(NormalizedNodeSerializer.serialize(node));
+        }
 
-        NormalizedNodeToProtocolBufferNode encoder = new NormalizedNodeToProtocolBufferNode();
-        encoder.encode(parentPath, node);
-
-        return encoder.getContainer();
-
-
+        return builder.build();
     }
 
     public NormalizedNode<?,?> decode(YangInstanceIdentifier id, NormalizedNodeMessages.Node node){
-            NodeToNormalizedNodeBuilder currentOp = NodeToNormalizedNodeBuilder.from(ctx);
-
-            for(YangInstanceIdentifier.PathArgument pathArgument : id.getPathArguments()){
-                currentOp = currentOp.getChild(pathArgument);
-            }
-
-            QName nodeType = null;
-
-            if(id.getPath().size() < 1){
-                nodeType = null;
-            } else {
-                final YangInstanceIdentifier.PathArgument pathArgument = id.getPath().get(id.getPath().size() - 1);
-                if(pathArgument instanceof YangInstanceIdentifier.AugmentationIdentifier){
-                    nodeType = null;
-                } else {
-                    nodeType = pathArgument.getNodeType();
-                }
-            }
-            if((node != null)&& (!node.getType().isEmpty())){
-               return currentOp.normalize(nodeType, node);
-            } else{
-              return null;
-            }
+        if(node.getIntType() < 0 || node.getSerializedSize() == 0){
+            return null;
+        }
+        return NormalizedNodeSerializer.deSerialize(node);
     }
 
 
index 31e6521a2861e65f1412b99818d4d47684e04c7b..32f3be82fcd0648e35796c5e3c835332825a20e9 100644 (file)
@@ -25,7 +25,7 @@ public class NormalizedNodeGetter implements
 
     @Override
     public void visitNode(int level, String parentPath, NormalizedNode normalizedNode) {
-        String nodePath = parentPath + "/"+ normalizedNode.getIdentifier().toString();
+        String nodePath = parentPath + "/"+ PathUtils.toString(normalizedNode.getIdentifier());
 
         if(nodePath.toString().equals(path)){
             output = normalizedNode;
index 1dd0f3b8278407752b91afbb24548eb857385cbc..25b65f01681ac4b9dcaa6354ec001c85bc531981 100644 (file)
 
 package org.opendaylight.controller.cluster.datastore.node.utils;
 
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
 public class PathUtils {
+
     public static String getParentPath(String currentElementPath){
         StringBuilder parentPath = new StringBuilder();
 
@@ -27,4 +36,86 @@ public class PathUtils {
         }
         return parentPath.toString();
     }
+
+    /**
+     * Given a YangInstanceIdentifier return a serialized version of the same
+     * as a String
+     *
+     * @param path
+     * @return
+     */
+    public static String toString(YangInstanceIdentifier path){
+        StringBuilder sb = new StringBuilder();
+        Iterator<YangInstanceIdentifier.PathArgument> iterator =
+            path.getPathArguments().iterator();
+
+        while(iterator.hasNext()){
+            sb.append(toString(iterator.next()));
+            if(iterator.hasNext()){
+                sb.append("/");
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Given a YangInstanceIdentifier.PathArgument return a serialized version
+     * of the same as a String
+     *
+     * @param pathArgument
+     * @return
+     */
+    public static String toString(YangInstanceIdentifier.PathArgument pathArgument){
+        if(pathArgument instanceof YangInstanceIdentifier.NodeIdentifier){
+            return toString((YangInstanceIdentifier.NodeIdentifier) pathArgument);
+        } else if(pathArgument instanceof YangInstanceIdentifier.AugmentationIdentifier){
+            return toString((YangInstanceIdentifier.AugmentationIdentifier) pathArgument);
+        } else if(pathArgument instanceof YangInstanceIdentifier.NodeWithValue){
+            return toString((YangInstanceIdentifier.NodeWithValue) pathArgument);
+        } else if(pathArgument instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates){
+            return toString((YangInstanceIdentifier.NodeIdentifierWithPredicates) pathArgument);
+        }
+
+        return pathArgument.toString();
+    }
+
+    /**
+     * Given a serialized string version of a YangInstanceIdentifier convert
+     * to a YangInstanceIdentifier
+     *
+     * @param path
+     * @return
+     */
+    public static YangInstanceIdentifier toYangInstanceIdentifier(String path){
+        String[] segments = path.split("/");
+
+        List<YangInstanceIdentifier.PathArgument> pathArguments = new ArrayList<>();
+        for (String segment : segments) {
+            if (!"".equals(segment)) {
+                pathArguments.add(NodeIdentifierFactory.getArgument(segment));
+            }
+        }
+        return YangInstanceIdentifier.create(pathArguments);
+    }
+
+    private static String toString(YangInstanceIdentifier.NodeIdentifier pathArgument){
+        return pathArgument.getNodeType().toString();
+    }
+
+    private static String toString(YangInstanceIdentifier.AugmentationIdentifier pathArgument){
+        Set<QName> childNames = pathArgument.getPossibleChildNames();
+        final StringBuilder sb = new StringBuilder("AugmentationIdentifier{");
+        sb.append("childNames=").append(childNames).append('}');
+        return sb.toString();
+
+    }
+
+    private static String toString(YangInstanceIdentifier.NodeWithValue pathArgument){
+        return pathArgument.getNodeType().toString() + "[" + pathArgument.getValue() + "]";
+    }
+
+    private static String toString(YangInstanceIdentifier.NodeIdentifierWithPredicates pathArgument){
+        return pathArgument.getNodeType().toString() + '[' + pathArgument.getKeyValues() + ']';
+    }
+
 }
index 002b9ff82e53eea0b62fd98d97756926a2e21bea..5a8f5228619e9f80a091da123aa734fb59dcd85f 100644 (file)
 
 package org.opendaylight.controller.cluster.datastore.node.utils;
 
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
 import org.opendaylight.yangtools.yang.common.QName;
 
-import java.util.HashMap;
-import java.util.Map;
-
 public class QNameFactory {
-    private static final Map<String, QName> cache = new HashMap<>();
 
-    public static QName create(String name){
-        QName value = cache.get(name);
-        if(value == null){
-            synchronized (cache){
-                value = cache.get(name);
-                if(value == null) {
-                    value = QName.create(name);
-                    cache.put(name, value);
+    private static final int MAX_QNAME_CACHE_SIZE = 10000;
+
+    private static LoadingCache<String, QName> cache = CacheBuilder.newBuilder()
+        .maximumSize(MAX_QNAME_CACHE_SIZE)
+        .softValues()
+        .build(
+            new CacheLoader<String, QName>() {
+                public QName load(String key) {
+                    return QName.create(key);
                 }
             }
-        }
-        return value;
+        );
+
+
+    public static QName create(String name){
+        return cache.getUnchecked(name);
     }
 }
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/NormalizedNodeDeSerializationContext.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/NormalizedNodeDeSerializationContext.java
new file mode 100644 (file)
index 0000000..0ed1317
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * 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.node.utils.serialization;
+
+/**
+ * NormalizedNodeDeSerializationContext provides methods which help in decoding
+ * certain components of a NormalizedNode properly
+ */
+
+public interface NormalizedNodeDeSerializationContext {
+    String getNamespace(int namespace);
+    String getRevision(int revision);
+    String getLocalName(int localName);
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/NormalizedNodeSerializationContext.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/NormalizedNodeSerializationContext.java
new file mode 100644 (file)
index 0000000..660bc28
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * 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.node.utils.serialization;
+
+import java.net.URI;
+import java.util.Date;
+
+/**
+ * NormalizedNodeSerializationContext provides methods which help in encoding
+ * certain components of a NormalizedNode properly
+ */
+public interface NormalizedNodeSerializationContext {
+    int addNamespace(URI namespace);
+    int addRevision(Date revision);
+    int addLocalName(String localName);
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/NormalizedNodeSerializer.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/NormalizedNodeSerializer.java
new file mode 100644 (file)
index 0000000..3e1bd35
--- /dev/null
@@ -0,0 +1,551 @@
+/*
+ * 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.node.utils.serialization;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
+import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
+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.api.DataContainerNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeType.ANY_XML_NODE_TYPE;
+import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeType.AUGMENTATION_NODE_TYPE;
+import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeType.CHOICE_NODE_TYPE;
+import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeType.CONTAINER_NODE_TYPE;
+import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeType.LEAF_NODE_TYPE;
+import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeType.LEAF_SET_ENTRY_NODE_TYPE;
+import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeType.LEAF_SET_NODE_TYPE;
+import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeType.MAP_ENTRY_NODE_TYPE;
+import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeType.MAP_NODE_TYPE;
+import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeType.ORDERED_LEAF_SET_NODE_TYPE;
+import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeType.ORDERED_MAP_NODE_TYPE;
+import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeType.UNKEYED_LIST_ENTRY_NODE_TYPE;
+import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeType.UNKEYED_LIST_NODE_TYPE;
+import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeType.getSerializableNodeType;
+
+/**
+ * NormalizedNodeSerializer can be used to convert a Normalized node to and and
+ * from a protocol buffer message.
+ *
+ *
+ */
+public class NormalizedNodeSerializer {
+
+    /**
+     * Serialize a NormalizedNode into a protocol buffer message
+     * <p>
+     * The significant things to be aware of the Serialization process are
+     * <ul>
+     *     <li>Repeated strings like namespaces, revisions and localNames are
+     *     compressed to codes and stored in the top level of the normalized
+     *     node protocol buffer message
+     *     </li>
+     *     <li>All value types are encoded for each leaf value. This is so that
+     *     the deSerialization process does not need to use the schema context to
+     *     figure out how to decode values
+     *     </li>
+     * </ul>
+     *
+     * One question which may arise is why not use something like gzip to
+     * compress the protocol buffer message instead of rolling our own
+     * encoding scheme. This has to be explored further as it is a more
+     * general solution.
+     *
+     * @param node
+     * @return
+     */
+    public static NormalizedNodeMessages.Node serialize(NormalizedNode node){
+        Preconditions.checkNotNull(node, "node should not be null");
+        return new Serializer(node).serialize();
+    }
+
+
+    /**
+     * DeSerialize a protocol buffer message back into a NormalizedNode
+     *
+     * @param node
+     * @return
+     */
+    public static NormalizedNode deSerialize(NormalizedNodeMessages.Node node){
+        return new DeSerializer(node).deSerialize();
+    }
+
+    /**
+     * DeSerialize a PathArgument which is in the protocol buffer format into
+     * a yang PathArgument. The protocol buffer path argument is specially
+     * encoded and can only be interpreted in the context of a top level
+     * serialized NormalizedNode protocol buffer message. The reason for this
+     * is that during the NormalizedNode serialization process certain repeated
+     * strings are encoded into a "codes" list and the actual strings are
+     * replaced by an integer which is an index into that list.
+     *
+     * @param node
+     * @param pathArgument
+     * @return
+     */
+    public static YangInstanceIdentifier.PathArgument deSerialize(NormalizedNodeMessages.Node node, NormalizedNodeMessages.PathArgument pathArgument){
+        Preconditions.checkNotNull(node, "node should not be null");
+        Preconditions.checkNotNull(pathArgument, "pathArgument should not be null");
+        return new DeSerializer(node).deSerialize(pathArgument);
+    }
+
+    private static class Serializer implements NormalizedNodeSerializationContext {
+
+        private final NormalizedNode node;
+
+        private final Map<Object, Integer> codeMap = new HashMap<>();
+        private final List<String> codes = new ArrayList<>();
+
+        private Serializer(NormalizedNode node) {
+            this.node = node;
+        }
+
+        private NormalizedNodeMessages.Node serialize() {
+            return this.serialize(node).addAllCode(codes).build();
+        }
+
+        private NormalizedNodeMessages.Node.Builder serialize(
+            NormalizedNode node) {
+            NormalizedNodeMessages.Node.Builder builder =
+                NormalizedNodeMessages.Node.newBuilder();
+
+            builder.setPathArgument(PathArgumentSerializer.serialize(this, node.getIdentifier()));
+            Integer nodeType = getSerializableNodeType(node).ordinal();
+            builder.setIntType(nodeType);
+            Object value = node.getValue();
+
+            // We need to do a specific check of the type of the node here
+            // because if we looked at the value type alone we will not be
+            // able to distinguish if the value was supposed to be added
+            // as a child or whether the value should be added as a value of the
+            // node.
+            // One use case where this check is necessary when you have a node
+            // with a bits value. In that case the value of the node is a Set
+            // which is also a Collection. Without the following check being
+            // done first the code would flow into the Collection if condition
+            // and the Set would be added as child nodes
+            if(nodeType == NormalizedNodeType.LEAF_NODE_TYPE.ordinal() ||
+               nodeType == NormalizedNodeType.LEAF_SET_ENTRY_NODE_TYPE.ordinal()){
+
+                ValueSerializer.serialize(builder, this, value);
+
+            } else if (value instanceof Iterable) {
+                Iterable iterable = (Iterable) value;
+
+                for (Object o : iterable) {
+                    if (o instanceof NormalizedNode) {
+                        builder.addChild(serialize((NormalizedNode) o));
+                    }
+                }
+
+            } else if (value instanceof NormalizedNode) {
+
+                builder.addChild(serialize((NormalizedNode) value));
+
+            } else {
+
+                ValueSerializer.serialize(builder, this, value);
+            }
+
+            return builder;
+        }
+
+
+        @Override public int addNamespace(URI namespace) {
+            int namespaceInt = getCode(namespace);
+
+            if(namespaceInt == -1) {
+                namespaceInt = addCode(namespace, namespace.toString());
+            }
+            return namespaceInt;
+        }
+
+        @Override public int addRevision(Date revision) {
+            if(revision == null){
+                return -1;
+            }
+
+            int revisionInt = getCode(revision);
+            if(revisionInt == -1) {
+                String formattedRevision =
+                    SimpleDateFormatUtil.getRevisionFormat().format(revision);
+                revisionInt = addCode(revision, formattedRevision);
+            }
+            return revisionInt;
+        }
+
+        @Override public int addLocalName(String localName) {
+            int localNameInt = getCode(localName);
+            if(localNameInt == -1) {
+                localNameInt = addCode(localName, localName.toString());
+            }
+            return localNameInt;
+
+        }
+
+        public int addCode(Object code, String codeStr){
+            int count = codes.size();
+            codes.add(codeStr);
+            codeMap.put(code, Integer.valueOf(count));
+            return count;
+        }
+
+        public int getCode(Object code){
+            if(codeMap.containsKey(code)){
+                return codeMap.get(code);
+            }
+            return -1;
+        }
+    }
+
+    private static class DeSerializer implements NormalizedNodeDeSerializationContext {
+        private static Map<NormalizedNodeType, DeSerializationFunction>
+            deSerializationFunctions = new HashMap<>();
+
+        static {
+            deSerializationFunctions.put(CONTAINER_NODE_TYPE,
+                new DeSerializationFunction() {
+                    @Override public NormalizedNode apply(
+                        DeSerializer deSerializer,
+                        NormalizedNodeMessages.Node node) {
+                        DataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifier, ContainerNode>
+                            builder = Builders.containerBuilder();
+
+                        builder
+                            .withNodeIdentifier(deSerializer.toNodeIdentifier(
+                                node.getPathArgument()));
+
+                        return deSerializer.buildDataContainer(builder, node);
+
+                    }
+
+                });
+
+            deSerializationFunctions.put(LEAF_NODE_TYPE,
+                new DeSerializationFunction() {
+                    @Override public NormalizedNode apply(
+                        DeSerializer deSerializer,
+                        NormalizedNodeMessages.Node node) {
+                        NormalizedNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifier, Object, LeafNode<Object>>
+                            builder = Builders.leafBuilder();
+
+                        builder
+                            .withNodeIdentifier(deSerializer.toNodeIdentifier(
+                                node.getPathArgument()));
+
+                        return deSerializer.buildNormalizedNode(builder, node);
+
+                    }
+                });
+
+            deSerializationFunctions.put(MAP_NODE_TYPE,
+                new DeSerializationFunction() {
+                    @Override public NormalizedNode apply(
+                        DeSerializer deSerializer,
+                        NormalizedNodeMessages.Node node) {
+                        CollectionNodeBuilder<MapEntryNode, MapNode>
+                            builder = Builders.mapBuilder();
+
+                        return deSerializer.buildCollectionNode(builder, node);
+                    }
+                });
+
+            deSerializationFunctions.put(MAP_ENTRY_NODE_TYPE,
+                new DeSerializationFunction() {
+                    @Override public NormalizedNode apply(
+                        DeSerializer deSerializer,
+                        NormalizedNodeMessages.Node node) {
+                        DataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode>
+                            builder = Builders.mapEntryBuilder();
+
+                        builder.withNodeIdentifier(deSerializer.toNodeIdentifierWithPredicates(
+                            node.getPathArgument()));
+
+                        return deSerializer.buildDataContainer(builder, node);
+                    }
+                });
+
+            deSerializationFunctions.put(AUGMENTATION_NODE_TYPE,
+                new DeSerializationFunction() {
+                    @Override public NormalizedNode apply(
+                        DeSerializer deSerializer,
+                        NormalizedNodeMessages.Node node) {
+                        DataContainerNodeBuilder<YangInstanceIdentifier.AugmentationIdentifier, AugmentationNode>
+                            builder = Builders.augmentationBuilder();
+
+                        builder.withNodeIdentifier(
+                            deSerializer.toAugmentationIdentifier(
+                                node.getPathArgument()));
+
+                        return deSerializer.buildDataContainer(builder, node);
+                    }
+                });
+
+            deSerializationFunctions.put(LEAF_SET_NODE_TYPE,
+                new DeSerializationFunction() {
+                    @Override public NormalizedNode apply(
+                        DeSerializer deSerializer,
+                        NormalizedNodeMessages.Node node) {
+                        ListNodeBuilder<Object, LeafSetEntryNode<Object>>
+                            builder = Builders.leafSetBuilder();
+
+                        return deSerializer.buildListNode(builder, node);
+                    }
+                });
+
+            deSerializationFunctions.put(LEAF_SET_ENTRY_NODE_TYPE,
+                new DeSerializationFunction() {
+                    @Override public NormalizedNode apply(
+                        DeSerializer deSerializer,
+                        NormalizedNodeMessages.Node node) {
+                        NormalizedNodeAttrBuilder<YangInstanceIdentifier.NodeWithValue, Object, LeafSetEntryNode<Object>>
+                            builder = Builders.leafSetEntryBuilder();
+
+                        builder.withNodeIdentifier(deSerializer.toNodeWithValue(
+                            node.getPathArgument()));
+
+                        return deSerializer.buildNormalizedNode(builder, node);
+                    }
+                });
+
+            deSerializationFunctions.put(CHOICE_NODE_TYPE,
+                new DeSerializationFunction() {
+                    @Override public NormalizedNode apply(
+                        DeSerializer deSerializer,
+                        NormalizedNodeMessages.Node node) {
+                        DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ChoiceNode>
+                            builder =
+                            Builders.choiceBuilder();
+
+                        builder
+                            .withNodeIdentifier(deSerializer.toNodeIdentifier(
+                                node.getPathArgument()));
+
+                        return deSerializer.buildDataContainer(builder, node);
+                    }
+                });
+
+            deSerializationFunctions.put(ORDERED_LEAF_SET_NODE_TYPE,
+                new DeSerializationFunction() {
+                    @Override public NormalizedNode apply(
+                        DeSerializer deSerializer,
+                        NormalizedNodeMessages.Node node) {
+                        ListNodeBuilder<Object, LeafSetEntryNode<Object>>
+                            builder =
+                            Builders.orderedLeafSetBuilder();
+
+                        return deSerializer.buildListNode(builder, node);
+
+
+                    }
+                });
+
+            deSerializationFunctions.put(ORDERED_MAP_NODE_TYPE,
+                new DeSerializationFunction() {
+                    @Override public NormalizedNode apply(
+                        DeSerializer deSerializer,
+                        NormalizedNodeMessages.Node node) {
+                        CollectionNodeBuilder<MapEntryNode, OrderedMapNode>
+                            builder =
+                            Builders.orderedMapBuilder();
+
+                        return deSerializer.buildCollectionNode(builder, node);
+                    }
+                });
+
+            deSerializationFunctions.put(UNKEYED_LIST_NODE_TYPE,
+                new DeSerializationFunction() {
+                    @Override public NormalizedNode apply(
+                        DeSerializer deSerializer,
+                        NormalizedNodeMessages.Node node) {
+                        CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode>
+                            builder =
+                            Builders.unkeyedListBuilder();
+
+                        return deSerializer.buildCollectionNode(builder, node);
+                    }
+                });
+
+            deSerializationFunctions.put(UNKEYED_LIST_ENTRY_NODE_TYPE,
+                new DeSerializationFunction() {
+                    @Override public NormalizedNode apply(
+                        DeSerializer deSerializer,
+                        NormalizedNodeMessages.Node node) {
+                        DataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifier, UnkeyedListEntryNode>
+                            builder =
+                            Builders.unkeyedListEntryBuilder();
+
+                        builder
+                            .withNodeIdentifier(deSerializer.toNodeIdentifier(
+                                node.getPathArgument()));
+
+                        return deSerializer.buildDataContainer(builder, node);
+                    }
+                });
+
+            deSerializationFunctions.put(ANY_XML_NODE_TYPE,
+                new DeSerializationFunction() {
+
+                    @Override public NormalizedNode apply(
+                        DeSerializer deSerializer,
+                        NormalizedNodeMessages.Node node) {
+                        NormalizedNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifier, Node<?>, AnyXmlNode>
+                            builder =
+                            Builders.anyXmlBuilder();
+
+                        builder
+                            .withNodeIdentifier(deSerializer.toNodeIdentifier(
+                                node.getPathArgument()));
+
+                        return deSerializer.buildNormalizedNode(builder, node);
+                    }
+                });
+
+        }
+
+        private final NormalizedNodeMessages.Node node;
+
+        public DeSerializer(NormalizedNodeMessages.Node node){
+            this.node = node;
+        }
+
+        public NormalizedNode deSerialize(){
+            return deSerialize(node);
+        }
+
+        private NormalizedNode deSerialize(NormalizedNodeMessages.Node node){
+            Preconditions.checkNotNull(node, "node should not be null");
+            DeSerializationFunction deSerializationFunction =
+                Preconditions.checkNotNull(deSerializationFunctions.get(NormalizedNodeType.values()[node.getIntType()]), "Unknown type " + node);
+
+            return deSerializationFunction.apply(this, node);
+        }
+
+
+        private NormalizedNode buildCollectionNode(
+            CollectionNodeBuilder builder,
+            NormalizedNodeMessages.Node node) {
+
+            builder.withNodeIdentifier(toNodeIdentifier(node.getPathArgument()));
+
+            for(NormalizedNodeMessages.Node child : node.getChildList()){
+                builder.withChild(deSerialize(child));
+            }
+
+            return builder.build();
+        }
+
+
+        private NormalizedNode buildListNode(
+            ListNodeBuilder<Object, LeafSetEntryNode<Object>> builder,
+            NormalizedNodeMessages.Node node) {
+            builder.withNodeIdentifier(toNodeIdentifier(node.getPathArgument()));
+
+            for(NormalizedNodeMessages.Node child : node.getChildList()){
+                builder.withChild((LeafSetEntryNode<Object>) deSerialize(child));
+            }
+
+            return builder.build();
+        }
+
+        private NormalizedNode buildDataContainer(DataContainerNodeBuilder builder, NormalizedNodeMessages.Node node){
+
+            for(NormalizedNodeMessages.Node child : node.getChildList()){
+                builder.withChild((DataContainerChild<?, ?>) deSerialize(child));
+            }
+
+            //TODO : Also handle attributes
+
+            return builder.build();
+        }
+
+        private NormalizedNode buildNormalizedNode(NormalizedNodeAttrBuilder builder, NormalizedNodeMessages.Node node){
+
+            builder.withValue(ValueSerializer.deSerialize(this, node));
+
+            //TODO : Also handle attributes
+
+            return builder.build();
+
+        }
+
+
+        private YangInstanceIdentifier.NodeIdentifierWithPredicates toNodeIdentifierWithPredicates(
+            NormalizedNodeMessages.PathArgument path) {
+            return (YangInstanceIdentifier.NodeIdentifierWithPredicates) PathArgumentSerializer.deSerialize(this, path);
+        }
+
+        private YangInstanceIdentifier.AugmentationIdentifier toAugmentationIdentifier(
+            NormalizedNodeMessages.PathArgument path) {
+            return (YangInstanceIdentifier.AugmentationIdentifier) PathArgumentSerializer.deSerialize(this, path);
+        }
+
+        private YangInstanceIdentifier.NodeWithValue toNodeWithValue(
+            NormalizedNodeMessages.PathArgument path) {
+            return (YangInstanceIdentifier.NodeWithValue) PathArgumentSerializer.deSerialize(
+                this, path);
+        }
+
+        private YangInstanceIdentifier.NodeIdentifier toNodeIdentifier(NormalizedNodeMessages.PathArgument path){
+            return (YangInstanceIdentifier.NodeIdentifier) PathArgumentSerializer.deSerialize(
+                this, path);
+        }
+
+        @Override public String getNamespace(int namespace) {
+            return node.getCode(namespace);
+        }
+
+        @Override public String getRevision(int revision) {
+            return node.getCode(revision);
+        }
+
+        @Override public String getLocalName(int localName) {
+            return node.getCode(localName);
+        }
+
+        public YangInstanceIdentifier.PathArgument deSerialize(
+            NormalizedNodeMessages.PathArgument pathArgument) {
+            return PathArgumentSerializer.deSerialize(this, pathArgument);
+        }
+
+        private static interface DeSerializationFunction {
+            NormalizedNode apply(DeSerializer deserializer, NormalizedNodeMessages.Node node);
+        }
+    }
+
+
+
+
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/NormalizedNodeType.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/NormalizedNodeType.java
new file mode 100644 (file)
index 0000000..eebd580
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * 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.node.utils.serialization;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
+
+public enum NormalizedNodeType {
+    CONTAINER_NODE_TYPE,
+    LEAF_NODE_TYPE,
+    MAP_NODE_TYPE,
+    MAP_ENTRY_NODE_TYPE,
+    AUGMENTATION_NODE_TYPE,
+    LEAF_SET_NODE_TYPE,
+    LEAF_SET_ENTRY_NODE_TYPE,
+    CHOICE_NODE_TYPE,
+    ORDERED_LEAF_SET_NODE_TYPE,
+    ORDERED_MAP_NODE_TYPE,
+    UNKEYED_LIST_NODE_TYPE,
+    UNKEYED_LIST_ENTRY_NODE_TYPE,
+    ANY_XML_NODE_TYPE;
+
+    public static NormalizedNodeType getSerializableNodeType(NormalizedNode node){
+        Preconditions.checkNotNull(node, "node should not be null");
+
+        if(node instanceof ContainerNode){
+            return CONTAINER_NODE_TYPE;
+        } else if(node instanceof LeafNode){
+            return LEAF_NODE_TYPE;
+        } else if(node instanceof MapNode){
+            return MAP_NODE_TYPE;
+        } else if(node instanceof MapEntryNode){
+            return MAP_ENTRY_NODE_TYPE;
+        } else if(node instanceof AugmentationNode){
+            return AUGMENTATION_NODE_TYPE;
+        } else if(node instanceof LeafSetNode){
+            return LEAF_SET_NODE_TYPE;
+        } else if(node instanceof LeafSetEntryNode){
+            return LEAF_SET_ENTRY_NODE_TYPE;
+        } else if(node instanceof ChoiceNode){
+            return CHOICE_NODE_TYPE;
+        } else if(node instanceof OrderedLeafSetNode){
+            return ORDERED_LEAF_SET_NODE_TYPE;
+        } else if(node instanceof OrderedMapNode){
+            return ORDERED_MAP_NODE_TYPE;
+        } else if(node instanceof UnkeyedListNode){
+            return UNKEYED_LIST_NODE_TYPE;
+        } else if(node instanceof UnkeyedListEntryNode){
+            return UNKEYED_LIST_ENTRY_NODE_TYPE;
+        } else if(node instanceof AnyXmlNode){
+            return ANY_XML_NODE_TYPE;
+        }
+        throw new IllegalArgumentException("Node type unknown : " + node.getClass().getSimpleName());
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/PathArgumentSerializer.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/PathArgumentSerializer.java
new file mode 100644 (file)
index 0000000..d7627c0
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * 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.node.utils.serialization;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.cluster.datastore.node.utils.NodeIdentifierFactory;
+import org.opendaylight.controller.cluster.datastore.node.utils.QNameFactory;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.PathArgumentType.getSerializablePathArgumentType;
+
+public class PathArgumentSerializer {
+    private static final Map<Class, PathArgumentAttributesGetter> pathArgumentAttributesGetters = new HashMap<>();
+
+    public static NormalizedNodeMessages.PathArgument serialize(NormalizedNodeSerializationContext context, YangInstanceIdentifier.PathArgument pathArgument){
+        Preconditions.checkNotNull(context, "context should not be null");
+        Preconditions.checkNotNull(pathArgument, "pathArgument should not be null");
+
+        QName nodeType = null;
+        if (!(pathArgument instanceof YangInstanceIdentifier.AugmentationIdentifier)) {
+            nodeType = pathArgument.getNodeType();
+        }
+
+        NormalizedNodeMessages.PathArgument.Builder builder =
+            NormalizedNodeMessages.PathArgument.newBuilder();
+
+        NormalizedNodeMessages.PathArgument serializablePathArgument =
+            builder
+                .setIntType(getSerializablePathArgumentType(pathArgument))
+                .setNodeType(encodeQName(context, nodeType))
+                .addAllAttribute(getPathArgumentAttributes(context, pathArgument))
+                .build();
+
+        return serializablePathArgument;
+    }
+
+
+    public static YangInstanceIdentifier.PathArgument deSerialize(NormalizedNodeDeSerializationContext context, NormalizedNodeMessages.PathArgument pathArgument){
+        Preconditions.checkNotNull(context, "context should not be null");
+        Preconditions.checkNotNull(pathArgument, "pathArgument should not be null");
+
+        return parsePathArgument(context, pathArgument);
+    }
+
+
+    private static interface PathArgumentAttributesGetter {
+        Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(NormalizedNodeSerializationContext context,
+            YangInstanceIdentifier.PathArgument pathArgument);
+    }
+
+    static {
+        pathArgumentAttributesGetters.put(YangInstanceIdentifier.NodeWithValue.class, new PathArgumentAttributesGetter() {
+            @Override
+            public Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(
+                NormalizedNodeSerializationContext context,
+                YangInstanceIdentifier.PathArgument pathArgument) {
+                List<NormalizedNodeMessages.PathArgumentAttribute> attributes =
+                    new ArrayList<>();
+
+                YangInstanceIdentifier.NodeWithValue identifier
+                    = (YangInstanceIdentifier.NodeWithValue) pathArgument;
+
+                NormalizedNodeMessages.PathArgumentAttribute attribute =
+                    buildAttribute(context, null, identifier.getValue());
+
+                attributes.add(attribute);
+
+                return attributes;
+
+            }
+        });
+
+        pathArgumentAttributesGetters.put(YangInstanceIdentifier.NodeIdentifierWithPredicates.class, new PathArgumentAttributesGetter() {
+            @Override
+            public Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(
+                NormalizedNodeSerializationContext context,
+                YangInstanceIdentifier.PathArgument pathArgument) {
+
+                List<NormalizedNodeMessages.PathArgumentAttribute> attributes =
+                    new ArrayList<>();
+
+                YangInstanceIdentifier.NodeIdentifierWithPredicates identifier
+                    = (YangInstanceIdentifier.NodeIdentifierWithPredicates) pathArgument;
+
+                for (QName key : identifier.getKeyValues().keySet()) {
+                    Object value = identifier.getKeyValues().get(key);
+                    NormalizedNodeMessages.PathArgumentAttribute attribute =
+                        buildAttribute(context, key, value);
+
+                    attributes.add(attribute);
+
+                }
+
+                return attributes;
+
+            }
+        });
+
+        pathArgumentAttributesGetters.put(YangInstanceIdentifier.AugmentationIdentifier.class, new PathArgumentAttributesGetter() {
+            @Override
+            public Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(
+                NormalizedNodeSerializationContext context,
+                YangInstanceIdentifier.PathArgument pathArgument) {
+
+                List<NormalizedNodeMessages.PathArgumentAttribute> attributes =
+                    new ArrayList<>();
+
+                YangInstanceIdentifier.AugmentationIdentifier identifier
+                    = (YangInstanceIdentifier.AugmentationIdentifier) pathArgument;
+
+                for (QName key : identifier.getPossibleChildNames()) {
+                    Object value = key;
+                    NormalizedNodeMessages.PathArgumentAttribute attribute =
+                        buildAttribute(context, key, value);
+
+                    attributes.add(attribute);
+
+                }
+
+                return attributes;
+
+            }
+        });
+
+
+        pathArgumentAttributesGetters.put(YangInstanceIdentifier.NodeIdentifier.class, new PathArgumentAttributesGetter() {
+            @Override
+            public Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(
+                NormalizedNodeSerializationContext context,
+                YangInstanceIdentifier.PathArgument pathArgument) {
+                return Collections.emptyList();
+            }
+        });
+    }
+
+    private static NormalizedNodeMessages.PathArgumentAttribute buildAttribute(NormalizedNodeSerializationContext context,QName name, Object value){
+        NormalizedNodeMessages.PathArgumentAttribute.Builder builder =
+            NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
+
+        builder.setName(encodeQName(context, name));
+        ValueSerializer.serialize(builder, context, value);
+
+        return builder.build();
+
+    }
+
+    private static NormalizedNodeMessages.QName.Builder encodeQName(NormalizedNodeSerializationContext context, QName qName){
+        if(qName == null){
+            return NormalizedNodeMessages.QName.getDefaultInstance().toBuilder();
+        }
+        NormalizedNodeMessages.QName.Builder qNameBuilder =
+            NormalizedNodeMessages.QName.newBuilder();
+
+        qNameBuilder.setNamespace(context.addNamespace(qName.getNamespace()));
+
+        qNameBuilder.setRevision(context.addRevision(qName.getRevision()));
+
+        qNameBuilder.setLocalName(context.addLocalName(qName.getLocalName()));
+
+        return qNameBuilder;
+    }
+
+    private static Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> getPathArgumentAttributes(
+            NormalizedNodeSerializationContext context,
+            YangInstanceIdentifier.PathArgument pathArgument) {
+
+        return pathArgumentAttributesGetters.get(pathArgument.getClass()).get(context, pathArgument);
+
+    }
+
+
+    private static String qNameToString(NormalizedNodeDeSerializationContext context,
+        NormalizedNodeMessages.QName qName){
+        // If this serializer is used qName cannot be null (see encodeQName)
+        // adding null check only in case someone tried to deSerialize a protocol buffer node
+        // that was not serialized using the PathArgumentSerializer
+        Preconditions.checkNotNull(qName, "qName should not be null");
+        Preconditions.checkArgument(!"".equals(qName.getLocalName()),
+            "qName.localName cannot be empty qName = " + qName.toString());
+        Preconditions.checkArgument(qName.getNamespace() != -1, "qName.namespace should be valid");
+
+        StringBuilder sb = new StringBuilder();
+        String namespace = context.getNamespace(qName.getNamespace());
+        String revision = "";
+        String localName = context.getLocalName(qName.getLocalName());
+        if(qName.getRevision() != -1){
+            revision = context.getRevision(qName.getRevision());
+            sb.append("(").append(namespace).append("?revision=").append(
+                revision).append(")").append(
+                localName);
+        } else {
+            sb.append("(").append(namespace).append(")").append(
+                localName);
+        }
+
+        return sb.toString();
+
+    }
+
+    /**
+     * Parse a protocol buffer PathArgument and return an MD-SAL PathArgument
+     *
+     * @param pathArgument protocol buffer PathArgument
+     * @return MD-SAL PathArgument
+     */
+    private static YangInstanceIdentifier.PathArgument parsePathArgument(
+        NormalizedNodeDeSerializationContext context,
+        NormalizedNodeMessages.PathArgument pathArgument) {
+
+        Preconditions.checkArgument(pathArgument.getIntType() >= 0
+            && pathArgument.getIntType() < PathArgumentType.values().length,
+            "Illegal PathArgumentType " + pathArgument.getIntType());
+
+        switch(PathArgumentType.values()[pathArgument.getIntType()]){
+            case NODE_IDENTIFIER_WITH_VALUE : {
+
+                YangInstanceIdentifier.NodeWithValue nodeWithValue =
+                    new YangInstanceIdentifier.NodeWithValue(
+                        QNameFactory.create(qNameToString(context, pathArgument.getNodeType())),
+                        parseAttribute(context, pathArgument.getAttribute(0)));
+
+                return nodeWithValue;
+            }
+
+            case NODE_IDENTIFIER_WITH_PREDICATES : {
+
+                YangInstanceIdentifier.NodeIdentifierWithPredicates
+                    nodeIdentifierWithPredicates =
+                    new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+                        QNameFactory.create(qNameToString(context, pathArgument.getNodeType())),
+                        toAttributesMap(context, pathArgument.getAttributeList()));
+
+                return nodeIdentifierWithPredicates;
+            }
+
+            case AUGMENTATION_IDENTIFIER: {
+
+                Set<QName> qNameSet = new HashSet<>();
+
+                for(NormalizedNodeMessages.PathArgumentAttribute attribute : pathArgument.getAttributeList()){
+                    qNameSet.add(QNameFactory.create(qNameToString(context, attribute.getName())));
+                }
+
+                return new YangInstanceIdentifier.AugmentationIdentifier(qNameSet);
+
+            }
+            default: {
+                return NodeIdentifierFactory.getArgument(qNameToString(context,
+                    pathArgument.getNodeType()));
+            }
+
+        }
+    }
+
+    private static Map<QName, Object> toAttributesMap(
+        NormalizedNodeDeSerializationContext context,
+        List<NormalizedNodeMessages.PathArgumentAttribute> attributesList) {
+
+        Map<QName, Object> map = new HashMap<>();
+
+        for(NormalizedNodeMessages.PathArgumentAttribute attribute : attributesList){
+            NormalizedNodeMessages.QName name = attribute.getName();
+            Object value = parseAttribute(context, attribute);
+
+            map.put(QNameFactory.create(qNameToString(context, name)), value);
+        }
+
+        return map;
+    }
+
+    private static Object parseAttribute(NormalizedNodeDeSerializationContext context, NormalizedNodeMessages.PathArgumentAttribute attribute){
+        return ValueSerializer.deSerialize(context, attribute);
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/PathArgumentType.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/PathArgumentType.java
new file mode 100644 (file)
index 0000000..20009d8
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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.node.utils.serialization;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+public enum PathArgumentType {
+    AUGMENTATION_IDENTIFIER,
+    NODE_IDENTIFIER,
+    NODE_IDENTIFIER_WITH_VALUE,
+    NODE_IDENTIFIER_WITH_PREDICATES;
+
+    public static int getSerializablePathArgumentType(YangInstanceIdentifier.PathArgument pathArgument){
+        Preconditions.checkNotNull(pathArgument, "pathArgument should not be null");
+
+        if(pathArgument instanceof YangInstanceIdentifier.AugmentationIdentifier){
+            return AUGMENTATION_IDENTIFIER.ordinal();
+        } else if(pathArgument instanceof YangInstanceIdentifier.NodeIdentifier){
+            return NODE_IDENTIFIER.ordinal();
+        } else if(pathArgument instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates){
+            return NODE_IDENTIFIER_WITH_PREDICATES.ordinal();
+        } else if(pathArgument instanceof YangInstanceIdentifier.NodeWithValue){
+            return NODE_IDENTIFIER_WITH_VALUE.ordinal();
+        }
+        throw new IllegalArgumentException("Unknown type of PathArgument = " + pathArgument.toString());
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/ValueSerializer.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/ValueSerializer.java
new file mode 100644 (file)
index 0000000..04c95d6
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * 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.node.utils.serialization;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.cluster.datastore.node.utils.QNameFactory;
+import org.opendaylight.controller.cluster.datastore.util.InstanceIdentifierUtils;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.HashSet;
+import java.util.Set;
+
+public class ValueSerializer {
+    public static void serialize(NormalizedNodeMessages.Node.Builder builder,
+        NormalizedNodeSerializationContext context, Object value){
+        builder.setIntValueType(ValueType.getSerializableType(value).ordinal());
+
+        if(value instanceof YangInstanceIdentifier) {
+            builder.setInstanceIdentifierValue(
+                InstanceIdentifierUtils.toSerializable((YangInstanceIdentifier) value));
+        } else if(value instanceof Set) {
+            Set set = (Set) value;
+            if(!set.isEmpty()){
+                for(Object o : set){
+                    if(o instanceof String){
+                        builder.addBitsValue(o.toString());
+                    } else {
+                        throw new IllegalArgumentException("Expected value type to be Bits but was : " +
+                            value.toString());
+                    }
+                }
+            }
+        } else {
+            builder.setValue(value.toString());
+        }
+    }
+
+    public static void serialize(NormalizedNodeMessages.PathArgumentAttribute.Builder builder,
+        NormalizedNodeSerializationContext context, Object value){
+
+        builder.setType(ValueType.getSerializableType(value).ordinal());
+        builder.setValue(value.toString());
+    }
+
+    public static Object deSerialize(
+        NormalizedNodeDeSerializationContext context, NormalizedNodeMessages.Node node) {
+        if(node.getIntValueType() == ValueType.YANG_IDENTIFIER_TYPE.ordinal()){
+            return InstanceIdentifierUtils.fromSerializable(
+                node.getInstanceIdentifierValue());
+        } else if(node.getIntValueType() == ValueType.BITS_TYPE.ordinal()){
+            return new HashSet(node.getBitsValueList());
+        }
+        return deSerializeBasicTypes(node.getIntValueType(), node.getValue());
+    }
+
+    public static Object deSerialize(
+        NormalizedNodeDeSerializationContext context,
+        NormalizedNodeMessages.PathArgumentAttribute attribute) {
+        return deSerializeBasicTypes(attribute.getType(), attribute.getValue());
+    }
+
+
+    private static Object deSerializeBasicTypes(int valueType, String value) {
+        Preconditions.checkArgument(valueType >= 0 && valueType < ValueType.values().length,
+            "Illegal value type " + valueType );
+
+        switch(ValueType.values()[valueType]){
+           case SHORT_TYPE: {
+               return Short.valueOf(value);
+           }
+           case BOOL_TYPE: {
+               return Boolean.valueOf(value);
+           }
+           case BYTE_TYPE: {
+               return Byte.valueOf(value);
+           }
+           case INT_TYPE : {
+                return Integer.valueOf(value);
+           }
+           case LONG_TYPE: {
+               return Long.valueOf(value);
+           }
+           case QNAME_TYPE: {
+               return QNameFactory.create(value);
+           }
+           case BIG_INTEGER_TYPE: {
+               return new BigInteger(value);
+           }
+           case BIG_DECIMAL_TYPE: {
+               return new BigDecimal(value);
+           }
+           default: {
+               return value;
+           }
+        }
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/ValueType.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/ValueType.java
new file mode 100644 (file)
index 0000000..8724dfe
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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.node.utils.serialization;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public enum ValueType {
+    SHORT_TYPE,
+    BYTE_TYPE,
+    INT_TYPE,
+    LONG_TYPE,
+    BOOL_TYPE,
+    QNAME_TYPE,
+    BITS_TYPE,
+    YANG_IDENTIFIER_TYPE,
+    STRING_TYPE,
+    BIG_INTEGER_TYPE,
+    BIG_DECIMAL_TYPE;
+
+    private static Map<Class, ValueType> types = new HashMap<>();
+
+    static {
+        types.put(String.class, STRING_TYPE);
+        types.put(Byte.class, BYTE_TYPE);
+        types.put(Integer.class, INT_TYPE);
+        types.put(Long.class, LONG_TYPE);
+        types.put(Boolean.class, BOOL_TYPE);
+        types.put(QName.class, QNAME_TYPE);
+        types.put(Set.class, BITS_TYPE);
+        types.put(YangInstanceIdentifier.class, YANG_IDENTIFIER_TYPE);
+        types.put(Short.class,SHORT_TYPE);
+        types.put(BigInteger.class, BIG_INTEGER_TYPE);
+        types.put(BigDecimal.class, BIG_DECIMAL_TYPE);
+    }
+
+    public static final ValueType getSerializableType(Object node){
+        Preconditions.checkNotNull(node, "node should not be null");
+
+        if(types.containsKey(node.getClass())) {
+            return types.get(node.getClass());
+        } else if(node instanceof Set){
+            return BITS_TYPE;
+        }
+
+        throw new IllegalArgumentException("Unknown value type " + node.getClass().getSimpleName());
+    }
+}
index 55cb341086078b79406d574c11cec8961813e6b6..0bb0d4fe8798b8623dc433d659f6ea550096c41e 100644 (file)
@@ -11,6 +11,7 @@
 package org.opendaylight.controller.cluster.datastore.util;
 
 import org.opendaylight.controller.cluster.datastore.node.utils.NodeIdentifierFactory;
+import org.opendaylight.controller.cluster.datastore.node.utils.QNameFactory;
 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -222,7 +223,7 @@ public class InstanceIdentifierUtils {
 
             YangInstanceIdentifier.NodeWithValue nodeWithValue =
                 new YangInstanceIdentifier.NodeWithValue(
-                    QName.create(pathArgument.getNodeType().getValue()),
+                    QNameFactory.create(pathArgument.getNodeType().getValue()),
                     parseAttribute(pathArgument.getAttributes(0)));
 
             return nodeWithValue;
@@ -232,7 +233,7 @@ public class InstanceIdentifierUtils {
             YangInstanceIdentifier.NodeIdentifierWithPredicates
                 nodeIdentifierWithPredicates =
                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(
-                    QName.create(pathArgument.getNodeType().getValue()), toAttributesMap(pathArgument.getAttributesList()));
+                    QNameFactory.create(pathArgument.getNodeType().getValue()), toAttributesMap(pathArgument.getAttributesList()));
 
             return nodeIdentifierWithPredicates;
 
@@ -241,7 +242,7 @@ public class InstanceIdentifierUtils {
             Set<QName> qNameSet = new HashSet<>();
 
             for(NormalizedNodeMessages.Attribute attribute : pathArgument.getAttributesList()){
-                qNameSet.add(QName.create(attribute.getValue()));
+                qNameSet.add(QNameFactory.create(attribute.getValue()));
             }
 
             return new YangInstanceIdentifier.AugmentationIdentifier(qNameSet);
@@ -259,7 +260,7 @@ public class InstanceIdentifierUtils {
             String name = attribute.getName();
             Object value = parseAttribute(attribute);
 
-            map.put(QName.create(name), value);
+            map.put(QNameFactory.create(name), value);
         }
 
         return map;
index 646431522e3c9d4ee3b7b3703839505b38f39bfd..c6d3625ac3ca4ba2cb5e093a64a8681e5c1b4b81 100644 (file)
@@ -11,9 +11,8 @@ package org.opendaylight.controller.common.actor;
 import akka.actor.ActorPath;
 import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
-import akka.dispatch.BoundedMailbox;
+import akka.dispatch.BoundedDequeBasedMailbox;
 import akka.dispatch.MailboxType;
-import akka.dispatch.MessageQueue;
 import akka.dispatch.ProducesMessageQueue;
 import com.codahale.metrics.Gauge;
 import com.codahale.metrics.MetricRegistry;
@@ -24,7 +23,7 @@ import scala.concurrent.duration.FiniteDuration;
 
 import java.util.concurrent.TimeUnit;
 
-public class MeteredBoundedMailbox implements MailboxType, ProducesMessageQueue<BoundedMailbox.MessageQueue> {
+public class MeteredBoundedMailbox implements MailboxType, ProducesMessageQueue<MeteredBoundedMailbox.MeteredMessageQueue> {
 
     private MeteredMessageQueue queue;
     private Integer capacity;
@@ -33,16 +32,18 @@ public class MeteredBoundedMailbox implements MailboxType, ProducesMessageQueue<
     private MetricsReporter reporter;
 
     private final String QUEUE_SIZE = "queue-size";
+    private final String CAPACITY = "mailbox-capacity";
+    private final String TIMEOUT  = "mailbox-push-timeout-time";
     private final Long DEFAULT_TIMEOUT = 10L;
 
     public MeteredBoundedMailbox(ActorSystem.Settings settings, Config config) {
         Preconditions.checkArgument( config.hasPath("mailbox-capacity"), "Missing configuration [mailbox-capacity]" );
-        this.capacity = config.getInt("mailbox-capacity");
+        this.capacity = config.getInt(CAPACITY);
         Preconditions.checkArgument( this.capacity > 0, "mailbox-capacity must be > 0");
 
         Long timeout = -1L;
-        if ( config.hasPath("mailbox-push-timeout-time") ){
-            timeout = config.getDuration("mailbox-push-timeout-time", TimeUnit.NANOSECONDS);
+        if ( config.hasPath(TIMEOUT) ){
+            timeout = config.getDuration(TIMEOUT, TimeUnit.NANOSECONDS);
         } else {
             timeout = DEFAULT_TIMEOUT;
         }
@@ -54,7 +55,7 @@ public class MeteredBoundedMailbox implements MailboxType, ProducesMessageQueue<
 
 
     @Override
-    public MessageQueue create(final scala.Option<ActorRef> owner, scala.Option<ActorSystem> system) {
+    public MeteredMessageQueue create(final scala.Option<ActorRef> owner, scala.Option<ActorSystem> system) {
         this.queue = new MeteredMessageQueue(this.capacity, this.pushTimeOut);
         monitorQueueSize(owner, this.queue);
         return this.queue;
@@ -65,14 +66,15 @@ public class MeteredBoundedMailbox implements MailboxType, ProducesMessageQueue<
             return; //there's no actor to monitor
         }
         actorPath = owner.get().path();
-        MetricRegistry registry = reporter.getMetricsRegistry();
+        String actorInstanceId = Integer.toString(owner.get().hashCode());
 
-        String actorName = registry.name(actorPath.toString(), QUEUE_SIZE);
+        MetricRegistry registry = reporter.getMetricsRegistry();
+        String actorName = registry.name(actorPath.toString(), actorInstanceId, QUEUE_SIZE);
 
         if (registry.getMetrics().containsKey(actorName))
             return; //already registered
 
-        reporter.getMetricsRegistry().register(actorName,
+        registry.register(actorName,
                 new Gauge<Integer>() {
                     @Override
                     public Integer getValue() {
@@ -82,7 +84,7 @@ public class MeteredBoundedMailbox implements MailboxType, ProducesMessageQueue<
     }
 
 
-    public static class MeteredMessageQueue extends BoundedMailbox.MessageQueue {
+    public static class MeteredMessageQueue extends BoundedDequeBasedMailbox.MessageQueue {
 
         public MeteredMessageQueue(int capacity, FiniteDuration pushTimeOut) {
             super(capacity, pushTimeOut);
@@ -1,14 +1,14 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: KeyValueMessages.proto
 
-package org.opendaylight.controller.cluster.example.protobuff.messages;
+package org.opendaylight.controller.protobuff.messages.cluster.example;
 
 public final class KeyValueMessages {
   private KeyValueMessages() {}
   public static void registerAllExtensions(
       com.google.protobuf.ExtensionRegistry registry) {
-    registry.add(org.opendaylight.controller.cluster.example.protobuff.messages.KeyValueMessages.key);
-    registry.add(org.opendaylight.controller.cluster.example.protobuff.messages.KeyValueMessages.value);
+    registry.add(org.opendaylight.controller.protobuff.messages.cluster.example.KeyValueMessages.key);
+    registry.add(org.opendaylight.controller.protobuff.messages.cluster.example.KeyValueMessages.value);
   }
   public static final int KEY_FIELD_NUMBER = 2;
   /**
@@ -16,7 +16,7 @@ public final class KeyValueMessages {
    */
   public static final
     com.google.protobuf.GeneratedMessage.GeneratedExtension<
-      org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload,
+      org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload,
       java.lang.String> key = com.google.protobuf.GeneratedMessage
           .newFileScopedGeneratedExtension(
         java.lang.String.class,
@@ -27,7 +27,7 @@ public final class KeyValueMessages {
    */
   public static final
     com.google.protobuf.GeneratedMessage.GeneratedExtension<
-      org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload,
+      org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload,
       java.lang.String> value = com.google.protobuf.GeneratedMessage
           .newFileScopedGeneratedExtension(
         java.lang.String.class,
@@ -49,7 +49,7 @@ public final class KeyValueMessages {
       "e\022R.org.opendaylight.controller.cluster." +
       "raft.AppendEntries.ReplicatedLogEntry.Pa" +
       "yload\030\003 \001(\tBT\n>org.opendaylight.controll" +
-      "er.cluster.example.protobuff.messagesB\020K" +
+      "er.protobuff.messages.cluster.exampleB\020K" +
       "eyValueMessagesH\001"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
@@ -65,7 +65,7 @@ public final class KeyValueMessages {
     com.google.protobuf.Descriptors.FileDescriptor
       .internalBuildGeneratedFileFrom(descriptorData,
         new com.google.protobuf.Descriptors.FileDescriptor[] {
-          org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.getDescriptor(),
+          org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.getDescriptor(),
         }, assigner);
   }
 
@@ -1,7 +1,7 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: AppendEntriesMessages.proto
 
-package org.opendaylight.controller.cluster.raft.protobuff.messages;
+package org.opendaylight.controller.protobuff.messages.cluster.raft;
 
 public final class AppendEntriesMessages {
   private AppendEntriesMessages() {}
@@ -60,12 +60,12 @@ public final class AppendEntriesMessages {
     /**
      * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
      */
-    java.util.List<org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry> 
+    java.util.List<org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry>
         getLogEntriesList();
     /**
      * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
      */
-    org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry getLogEntries(int index);
+    org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry getLogEntries(int index);
     /**
      * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
      */
@@ -73,12 +73,12 @@ public final class AppendEntriesMessages {
     /**
      * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
      */
-    java.util.List<? extends org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder> 
+    java.util.List<? extends org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder>
         getLogEntriesOrBuilderList();
     /**
      * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
      */
-    org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder getLogEntriesOrBuilder(
+    org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder getLogEntriesOrBuilder(
         int index);
 
     // optional int64 leaderCommit = 6;
@@ -164,10 +164,10 @@ public final class AppendEntriesMessages {
             }
             case 42: {
               if (!((mutable_bitField0_ & 0x00000010) == 0x00000010)) {
-                logEntries_ = new java.util.ArrayList<org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry>();
+                logEntries_ = new java.util.ArrayList<org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry>();
                 mutable_bitField0_ |= 0x00000010;
               }
-              logEntries_.add(input.readMessage(org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.PARSER, extensionRegistry));
+              logEntries_.add(input.readMessage(org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.PARSER, extensionRegistry));
               break;
             }
             case 48: {
@@ -192,14 +192,14 @@ public final class AppendEntriesMessages {
     }
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_descriptor;
+      return org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_descriptor;
     }
 
     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_fieldAccessorTable
+      return org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.class, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.Builder.class);
+              org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.class, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.Builder.class);
     }
 
     public static com.google.protobuf.Parser<AppendEntries> PARSER =
@@ -248,11 +248,11 @@ public final class AppendEntriesMessages {
       /**
        * <code>optional .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload data = 3;</code>
        */
-      org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload getData();
+      org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload getData();
       /**
        * <code>optional .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload data = 3;</code>
        */
-      org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.PayloadOrBuilder getDataOrBuilder();
+      org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.PayloadOrBuilder getDataOrBuilder();
     }
     /**
      * Protobuf type {@code org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry}
@@ -316,11 +316,11 @@ public final class AppendEntriesMessages {
                 break;
               }
               case 26: {
-                org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.Builder subBuilder = null;
+                org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.Builder subBuilder = null;
                 if (((bitField0_ & 0x00000004) == 0x00000004)) {
                   subBuilder = data_.toBuilder();
                 }
-                data_ = input.readMessage(org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.PARSER, extensionRegistry);
+                data_ = input.readMessage(org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.PARSER, extensionRegistry);
                 if (subBuilder != null) {
                   subBuilder.mergeFrom(data_);
                   data_ = subBuilder.buildPartial();
@@ -342,14 +342,14 @@ public final class AppendEntriesMessages {
       }
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_descriptor;
+        return org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_descriptor;
       }
 
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_fieldAccessorTable
+        return org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.class, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder.class);
+                org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.class, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder.class);
       }
 
       public static com.google.protobuf.Parser<ReplicatedLogEntry> PARSER =
@@ -393,7 +393,7 @@ public final class AppendEntriesMessages {
           com.google.protobuf.GeneratedMessage.ExtendableMessage<
             Payload> implements PayloadOrBuilder {
         // Use Payload.newBuilder() to construct.
-        private Payload(com.google.protobuf.GeneratedMessage.ExtendableBuilder<org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload, ?> builder) {
+        private Payload(com.google.protobuf.GeneratedMessage.ExtendableBuilder<org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload, ?> builder) {
           super(builder);
           this.unknownFields = builder.getUnknownFields();
         }
@@ -456,14 +456,14 @@ public final class AppendEntriesMessages {
         }
         public static final com.google.protobuf.Descriptors.Descriptor
             getDescriptor() {
-          return org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_Payload_descriptor;
+          return org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_Payload_descriptor;
         }
 
         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
             internalGetFieldAccessorTable() {
-          return org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_Payload_fieldAccessorTable
+          return org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_Payload_fieldAccessorTable
               .ensureFieldAccessorsInitialized(
-                  org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.class, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.Builder.class);
+                  org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.class, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.Builder.class);
         }
 
         public static com.google.protobuf.Parser<Payload> PARSER =
@@ -499,7 +499,7 @@ public final class AppendEntriesMessages {
           if (ref instanceof java.lang.String) {
             return (java.lang.String) ref;
           } else {
-            com.google.protobuf.ByteString bs = 
+            com.google.protobuf.ByteString bs =
                 (com.google.protobuf.ByteString) ref;
             java.lang.String s = bs.toStringUtf8();
             if (bs.isValidUtf8()) {
@@ -515,7 +515,7 @@ public final class AppendEntriesMessages {
             getClientPayloadClassNameBytes() {
           java.lang.Object ref = clientPayloadClassName_;
           if (ref instanceof java.lang.String) {
-            com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString b =
                 com.google.protobuf.ByteString.copyFromUtf8(
                     (java.lang.String) ref);
             clientPayloadClassName_ = b;
@@ -545,7 +545,7 @@ public final class AppendEntriesMessages {
                             throws java.io.IOException {
           getSerializedSize();
           com.google.protobuf.GeneratedMessage
-            .ExtendableMessage<org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload>.ExtensionWriter extensionWriter =
+            .ExtendableMessage<org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload>.ExtensionWriter extensionWriter =
               newExtensionWriter();
           if (((bitField0_ & 0x00000001) == 0x00000001)) {
             output.writeBytes(1, getClientPayloadClassNameBytes());
@@ -577,53 +577,53 @@ public final class AppendEntriesMessages {
           return super.writeReplace();
         }
 
-        public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseFrom(
+        public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseFrom(
             com.google.protobuf.ByteString data)
             throws com.google.protobuf.InvalidProtocolBufferException {
           return PARSER.parseFrom(data);
         }
-        public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseFrom(
+        public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseFrom(
             com.google.protobuf.ByteString data,
             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
             throws com.google.protobuf.InvalidProtocolBufferException {
           return PARSER.parseFrom(data, extensionRegistry);
         }
-        public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseFrom(byte[] data)
+        public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseFrom(byte[] data)
             throws com.google.protobuf.InvalidProtocolBufferException {
           return PARSER.parseFrom(data);
         }
-        public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseFrom(
+        public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseFrom(
             byte[] data,
             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
             throws com.google.protobuf.InvalidProtocolBufferException {
           return PARSER.parseFrom(data, extensionRegistry);
         }
-        public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseFrom(java.io.InputStream input)
+        public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseFrom(java.io.InputStream input)
             throws java.io.IOException {
           return PARSER.parseFrom(input);
         }
-        public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseFrom(
+        public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseFrom(
             java.io.InputStream input,
             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
             throws java.io.IOException {
           return PARSER.parseFrom(input, extensionRegistry);
         }
-        public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseDelimitedFrom(java.io.InputStream input)
+        public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseDelimitedFrom(java.io.InputStream input)
             throws java.io.IOException {
           return PARSER.parseDelimitedFrom(input);
         }
-        public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseDelimitedFrom(
+        public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseDelimitedFrom(
             java.io.InputStream input,
             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
             throws java.io.IOException {
           return PARSER.parseDelimitedFrom(input, extensionRegistry);
         }
-        public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseFrom(
+        public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseFrom(
             com.google.protobuf.CodedInputStream input)
             throws java.io.IOException {
           return PARSER.parseFrom(input);
         }
-        public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseFrom(
+        public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parseFrom(
             com.google.protobuf.CodedInputStream input,
             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
             throws java.io.IOException {
@@ -632,7 +632,7 @@ public final class AppendEntriesMessages {
 
         public static Builder newBuilder() { return Builder.create(); }
         public Builder newBuilderForType() { return newBuilder(); }
-        public static Builder newBuilder(org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload prototype) {
+        public static Builder newBuilder(org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload prototype) {
           return newBuilder().mergeFrom(prototype);
         }
         public Builder toBuilder() { return newBuilder(this); }
@@ -648,20 +648,20 @@ public final class AppendEntriesMessages {
          */
         public static final class Builder extends
             com.google.protobuf.GeneratedMessage.ExtendableBuilder<
-              org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload, Builder> implements org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.PayloadOrBuilder {
+              org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload, Builder> implements org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.PayloadOrBuilder {
           public static final com.google.protobuf.Descriptors.Descriptor
               getDescriptor() {
-            return org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_Payload_descriptor;
+            return org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_Payload_descriptor;
           }
 
           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
               internalGetFieldAccessorTable() {
-            return org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_Payload_fieldAccessorTable
+            return org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_Payload_fieldAccessorTable
                 .ensureFieldAccessorsInitialized(
-                    org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.class, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.Builder.class);
+                    org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.class, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.Builder.class);
           }
 
-          // Construct using org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.newBuilder()
+          // Construct using org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.newBuilder()
           private Builder() {
             maybeForceBuilderInitialization();
           }
@@ -692,23 +692,23 @@ public final class AppendEntriesMessages {
 
           public com.google.protobuf.Descriptors.Descriptor
               getDescriptorForType() {
-            return org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_Payload_descriptor;
+            return org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_Payload_descriptor;
           }
 
-          public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload getDefaultInstanceForType() {
-            return org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.getDefaultInstance();
+          public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload getDefaultInstanceForType() {
+            return org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.getDefaultInstance();
           }
 
-          public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload build() {
-            org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload result = buildPartial();
+          public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload build() {
+            org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload result = buildPartial();
             if (!result.isInitialized()) {
               throw newUninitializedMessageException(result);
             }
             return result;
           }
 
-          public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload buildPartial() {
-            org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload result = new org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload(this);
+          public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload buildPartial() {
+            org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload result = new org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload(this);
             int from_bitField0_ = bitField0_;
             int to_bitField0_ = 0;
             if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
@@ -721,16 +721,16 @@ public final class AppendEntriesMessages {
           }
 
           public Builder mergeFrom(com.google.protobuf.Message other) {
-            if (other instanceof org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload) {
-              return mergeFrom((org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload)other);
+            if (other instanceof org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload) {
+              return mergeFrom((org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload)other);
             } else {
               super.mergeFrom(other);
               return this;
             }
           }
 
-          public Builder mergeFrom(org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload other) {
-            if (other == org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.getDefaultInstance()) return this;
+          public Builder mergeFrom(org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload other) {
+            if (other == org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.getDefaultInstance()) return this;
             if (other.hasClientPayloadClassName()) {
               bitField0_ |= 0x00000001;
               clientPayloadClassName_ = other.clientPayloadClassName_;
@@ -743,7 +743,7 @@ public final class AppendEntriesMessages {
 
           public final boolean isInitialized() {
             if (!extensionsAreInitialized()) {
-              
+
               return false;
             }
             return true;
@@ -753,11 +753,11 @@ public final class AppendEntriesMessages {
               com.google.protobuf.CodedInputStream input,
               com.google.protobuf.ExtensionRegistryLite extensionRegistry)
               throws java.io.IOException {
-            org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parsedMessage = null;
+            org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload parsedMessage = null;
             try {
               parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
             } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-              parsedMessage = (org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload) e.getUnfinishedMessage();
+              parsedMessage = (org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload) e.getUnfinishedMessage();
               throw e;
             } finally {
               if (parsedMessage != null) {
@@ -797,7 +797,7 @@ public final class AppendEntriesMessages {
               getClientPayloadClassNameBytes() {
             java.lang.Object ref = clientPayloadClassName_;
             if (ref instanceof String) {
-              com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString b =
                   com.google.protobuf.ByteString.copyFromUtf8(
                       (java.lang.String) ref);
               clientPayloadClassName_ = b;
@@ -888,7 +888,7 @@ public final class AppendEntriesMessages {
 
       // optional .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload data = 3;
       public static final int DATA_FIELD_NUMBER = 3;
-      private org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload data_;
+      private org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload data_;
       /**
        * <code>optional .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload data = 3;</code>
        */
@@ -898,20 +898,20 @@ public final class AppendEntriesMessages {
       /**
        * <code>optional .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload data = 3;</code>
        */
-      public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload getData() {
+      public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload getData() {
         return data_;
       }
       /**
        * <code>optional .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload data = 3;</code>
        */
-      public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.PayloadOrBuilder getDataOrBuilder() {
+      public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.PayloadOrBuilder getDataOrBuilder() {
         return data_;
       }
 
       private void initFields() {
         term_ = 0L;
         index_ = 0L;
-        data_ = org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.getDefaultInstance();
+        data_ = org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.getDefaultInstance();
       }
       private byte memoizedIsInitialized = -1;
       public final boolean isInitialized() {
@@ -973,53 +973,53 @@ public final class AppendEntriesMessages {
         return super.writeReplace();
       }
 
-      public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseFrom(
+      public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseFrom(
           com.google.protobuf.ByteString data)
           throws com.google.protobuf.InvalidProtocolBufferException {
         return PARSER.parseFrom(data);
       }
-      public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseFrom(
+      public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseFrom(
           com.google.protobuf.ByteString data,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
         return PARSER.parseFrom(data, extensionRegistry);
       }
-      public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseFrom(byte[] data)
+      public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseFrom(byte[] data)
           throws com.google.protobuf.InvalidProtocolBufferException {
         return PARSER.parseFrom(data);
       }
-      public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseFrom(
+      public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseFrom(
           byte[] data,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
         return PARSER.parseFrom(data, extensionRegistry);
       }
-      public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseFrom(java.io.InputStream input)
+      public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseFrom(java.io.InputStream input)
           throws java.io.IOException {
         return PARSER.parseFrom(input);
       }
-      public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseFrom(
+      public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseFrom(
           java.io.InputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
         return PARSER.parseFrom(input, extensionRegistry);
       }
-      public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseDelimitedFrom(java.io.InputStream input)
+      public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseDelimitedFrom(java.io.InputStream input)
           throws java.io.IOException {
         return PARSER.parseDelimitedFrom(input);
       }
-      public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseDelimitedFrom(
+      public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseDelimitedFrom(
           java.io.InputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
         return PARSER.parseDelimitedFrom(input, extensionRegistry);
       }
-      public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseFrom(
+      public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseFrom(
           com.google.protobuf.CodedInputStream input)
           throws java.io.IOException {
         return PARSER.parseFrom(input);
       }
-      public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseFrom(
+      public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parseFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
@@ -1028,7 +1028,7 @@ public final class AppendEntriesMessages {
 
       public static Builder newBuilder() { return Builder.create(); }
       public Builder newBuilderForType() { return newBuilder(); }
-      public static Builder newBuilder(org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry prototype) {
+      public static Builder newBuilder(org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry prototype) {
         return newBuilder().mergeFrom(prototype);
       }
       public Builder toBuilder() { return newBuilder(this); }
@@ -1044,20 +1044,20 @@ public final class AppendEntriesMessages {
        */
       public static final class Builder extends
           com.google.protobuf.GeneratedMessage.Builder<Builder>
-         implements org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder {
+         implements org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder {
         public static final com.google.protobuf.Descriptors.Descriptor
             getDescriptor() {
-          return org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_descriptor;
+          return org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_descriptor;
         }
 
         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
             internalGetFieldAccessorTable() {
-          return org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_fieldAccessorTable
+          return org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_fieldAccessorTable
               .ensureFieldAccessorsInitialized(
-                  org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.class, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder.class);
+                  org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.class, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder.class);
         }
 
-        // Construct using org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.newBuilder()
+        // Construct using org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.newBuilder()
         private Builder() {
           maybeForceBuilderInitialization();
         }
@@ -1083,7 +1083,7 @@ public final class AppendEntriesMessages {
           index_ = 0L;
           bitField0_ = (bitField0_ & ~0x00000002);
           if (dataBuilder_ == null) {
-            data_ = org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.getDefaultInstance();
+            data_ = org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.getDefaultInstance();
           } else {
             dataBuilder_.clear();
           }
@@ -1097,23 +1097,23 @@ public final class AppendEntriesMessages {
 
         public com.google.protobuf.Descriptors.Descriptor
             getDescriptorForType() {
-          return org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_descriptor;
+          return org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_ReplicatedLogEntry_descriptor;
         }
 
-        public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry getDefaultInstanceForType() {
-          return org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.getDefaultInstance();
+        public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry getDefaultInstanceForType() {
+          return org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.getDefaultInstance();
         }
 
-        public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry build() {
-          org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry result = buildPartial();
+        public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry build() {
+          org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry result = buildPartial();
           if (!result.isInitialized()) {
             throw newUninitializedMessageException(result);
           }
           return result;
         }
 
-        public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry buildPartial() {
-          org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry result = new org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry(this);
+        public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry buildPartial() {
+          org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry result = new org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry(this);
           int from_bitField0_ = bitField0_;
           int to_bitField0_ = 0;
           if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
@@ -1138,16 +1138,16 @@ public final class AppendEntriesMessages {
         }
 
         public Builder mergeFrom(com.google.protobuf.Message other) {
-          if (other instanceof org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry) {
-            return mergeFrom((org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry)other);
+          if (other instanceof org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry) {
+            return mergeFrom((org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry)other);
           } else {
             super.mergeFrom(other);
             return this;
           }
         }
 
-        public Builder mergeFrom(org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry other) {
-          if (other == org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.getDefaultInstance()) return this;
+        public Builder mergeFrom(org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry other) {
+          if (other == org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.getDefaultInstance()) return this;
           if (other.hasTerm()) {
             setTerm(other.getTerm());
           }
@@ -1164,7 +1164,7 @@ public final class AppendEntriesMessages {
         public final boolean isInitialized() {
           if (hasData()) {
             if (!getData().isInitialized()) {
-              
+
               return false;
             }
           }
@@ -1175,11 +1175,11 @@ public final class AppendEntriesMessages {
             com.google.protobuf.CodedInputStream input,
             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
             throws java.io.IOException {
-          org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parsedMessage = null;
+          org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry parsedMessage = null;
           try {
             parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
           } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-            parsedMessage = (org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry) e.getUnfinishedMessage();
+            parsedMessage = (org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry) e.getUnfinishedMessage();
             throw e;
           } finally {
             if (parsedMessage != null) {
@@ -1257,9 +1257,9 @@ public final class AppendEntriesMessages {
         }
 
         // optional .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload data = 3;
-        private org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload data_ = org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.getDefaultInstance();
+        private org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload data_ = org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.getDefaultInstance();
         private com.google.protobuf.SingleFieldBuilder<
-            org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.Builder, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.PayloadOrBuilder> dataBuilder_;
+            org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.Builder, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.PayloadOrBuilder> dataBuilder_;
         /**
          * <code>optional .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload data = 3;</code>
          */
@@ -1269,7 +1269,7 @@ public final class AppendEntriesMessages {
         /**
          * <code>optional .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload data = 3;</code>
          */
-        public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload getData() {
+        public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload getData() {
           if (dataBuilder_ == null) {
             return data_;
           } else {
@@ -1279,7 +1279,7 @@ public final class AppendEntriesMessages {
         /**
          * <code>optional .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload data = 3;</code>
          */
-        public Builder setData(org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload value) {
+        public Builder setData(org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload value) {
           if (dataBuilder_ == null) {
             if (value == null) {
               throw new NullPointerException();
@@ -1296,7 +1296,7 @@ public final class AppendEntriesMessages {
          * <code>optional .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload data = 3;</code>
          */
         public Builder setData(
-            org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.Builder builderForValue) {
+            org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.Builder builderForValue) {
           if (dataBuilder_ == null) {
             data_ = builderForValue.build();
             onChanged();
@@ -1309,12 +1309,12 @@ public final class AppendEntriesMessages {
         /**
          * <code>optional .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload data = 3;</code>
          */
-        public Builder mergeData(org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload value) {
+        public Builder mergeData(org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload value) {
           if (dataBuilder_ == null) {
             if (((bitField0_ & 0x00000004) == 0x00000004) &&
-                data_ != org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.getDefaultInstance()) {
+                data_ != org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.getDefaultInstance()) {
               data_ =
-                org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.newBuilder(data_).mergeFrom(value).buildPartial();
+                org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.newBuilder(data_).mergeFrom(value).buildPartial();
             } else {
               data_ = value;
             }
@@ -1330,7 +1330,7 @@ public final class AppendEntriesMessages {
          */
         public Builder clearData() {
           if (dataBuilder_ == null) {
-            data_ = org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.getDefaultInstance();
+            data_ = org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.getDefaultInstance();
             onChanged();
           } else {
             dataBuilder_.clear();
@@ -1341,7 +1341,7 @@ public final class AppendEntriesMessages {
         /**
          * <code>optional .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload data = 3;</code>
          */
-        public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.Builder getDataBuilder() {
+        public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.Builder getDataBuilder() {
           bitField0_ |= 0x00000004;
           onChanged();
           return getDataFieldBuilder().getBuilder();
@@ -1349,7 +1349,7 @@ public final class AppendEntriesMessages {
         /**
          * <code>optional .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload data = 3;</code>
          */
-        public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.PayloadOrBuilder getDataOrBuilder() {
+        public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.PayloadOrBuilder getDataOrBuilder() {
           if (dataBuilder_ != null) {
             return dataBuilder_.getMessageOrBuilder();
           } else {
@@ -1360,11 +1360,11 @@ public final class AppendEntriesMessages {
          * <code>optional .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload data = 3;</code>
          */
         private com.google.protobuf.SingleFieldBuilder<
-            org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.Builder, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.PayloadOrBuilder> 
+            org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.Builder, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.PayloadOrBuilder>
             getDataFieldBuilder() {
           if (dataBuilder_ == null) {
             dataBuilder_ = new com.google.protobuf.SingleFieldBuilder<
-                org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.Builder, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.PayloadOrBuilder>(
+                org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload.Builder, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.PayloadOrBuilder>(
                     data_,
                     getParentForChildren(),
                     isClean());
@@ -1418,7 +1418,7 @@ public final class AppendEntriesMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -1434,7 +1434,7 @@ public final class AppendEntriesMessages {
         getLeaderIdBytes() {
       java.lang.Object ref = leaderId_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         leaderId_ = b;
@@ -1478,17 +1478,17 @@ public final class AppendEntriesMessages {
 
     // repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;
     public static final int LOGENTRIES_FIELD_NUMBER = 5;
-    private java.util.List<org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry> logEntries_;
+    private java.util.List<org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry> logEntries_;
     /**
      * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
      */
-    public java.util.List<org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry> getLogEntriesList() {
+    public java.util.List<org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry> getLogEntriesList() {
       return logEntries_;
     }
     /**
      * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
      */
-    public java.util.List<? extends org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder> 
+    public java.util.List<? extends org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder>
         getLogEntriesOrBuilderList() {
       return logEntries_;
     }
@@ -1501,13 +1501,13 @@ public final class AppendEntriesMessages {
     /**
      * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
      */
-    public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry getLogEntries(int index) {
+    public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry getLogEntries(int index) {
       return logEntries_.get(index);
     }
     /**
      * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
      */
-    public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder getLogEntriesOrBuilder(
+    public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder getLogEntriesOrBuilder(
         int index) {
       return logEntries_.get(index);
     }
@@ -1617,53 +1617,53 @@ public final class AppendEntriesMessages {
       return super.writeReplace();
     }
 
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries parseFrom(
+    public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries parseFrom(
+    public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries parseFrom(byte[] data)
+    public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries parseFrom(
+    public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries parseFrom(java.io.InputStream input)
+    public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries parseFrom(
+    public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseFrom(input, extensionRegistry);
     }
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries parseDelimitedFrom(java.io.InputStream input)
+    public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input);
     }
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries parseDelimitedFrom(
+    public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input, extensionRegistry);
     }
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries parseFrom(
+    public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries parseFrom(
+    public static org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -1672,7 +1672,7 @@ public final class AppendEntriesMessages {
 
     public static Builder newBuilder() { return Builder.create(); }
     public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder(org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries prototype) {
+    public static Builder newBuilder(org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries prototype) {
       return newBuilder().mergeFrom(prototype);
     }
     public Builder toBuilder() { return newBuilder(this); }
@@ -1688,20 +1688,20 @@ public final class AppendEntriesMessages {
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessage.Builder<Builder>
-       implements org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntriesOrBuilder {
+       implements org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntriesOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_descriptor;
+        return org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_descriptor;
       }
 
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_fieldAccessorTable
+        return org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.class, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.Builder.class);
+                org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.class, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.Builder.class);
       }
 
-      // Construct using org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.newBuilder()
+      // Construct using org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -1747,23 +1747,23 @@ public final class AppendEntriesMessages {
 
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_descriptor;
+        return org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.internal_static_org_opendaylight_controller_cluster_raft_AppendEntries_descriptor;
       }
 
-      public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries getDefaultInstanceForType() {
-        return org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.getDefaultInstance();
+      public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries getDefaultInstanceForType() {
+        return org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.getDefaultInstance();
       }
 
-      public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries build() {
-        org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries result = buildPartial();
+      public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries build() {
+        org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
         return result;
       }
 
-      public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries buildPartial() {
-        org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries result = new org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries(this);
+      public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries buildPartial() {
+        org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries result = new org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries(this);
         int from_bitField0_ = bitField0_;
         int to_bitField0_ = 0;
         if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
@@ -1801,16 +1801,16 @@ public final class AppendEntriesMessages {
       }
 
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries) {
-          return mergeFrom((org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries)other);
+        if (other instanceof org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries) {
+          return mergeFrom((org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries other) {
-        if (other == org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.getDefaultInstance()) return this;
+      public Builder mergeFrom(org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries other) {
+        if (other == org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.getDefaultInstance()) return this;
         if (other.hasTerm()) {
           setTerm(other.getTerm());
         }
@@ -1843,7 +1843,7 @@ public final class AppendEntriesMessages {
               logEntriesBuilder_ = null;
               logEntries_ = other.logEntries_;
               bitField0_ = (bitField0_ & ~0x00000010);
-              logEntriesBuilder_ = 
+              logEntriesBuilder_ =
                 com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
                    getLogEntriesFieldBuilder() : null;
             } else {
@@ -1861,7 +1861,7 @@ public final class AppendEntriesMessages {
       public final boolean isInitialized() {
         for (int i = 0; i < getLogEntriesCount(); i++) {
           if (!getLogEntries(i).isInitialized()) {
-            
+
             return false;
           }
         }
@@ -1872,11 +1872,11 @@ public final class AppendEntriesMessages {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries parsedMessage = null;
+        org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries) e.getUnfinishedMessage();
+          parsedMessage = (org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries) e.getUnfinishedMessage();
           throw e;
         } finally {
           if (parsedMessage != null) {
@@ -1949,7 +1949,7 @@ public final class AppendEntriesMessages {
           getLeaderIdBytes() {
         java.lang.Object ref = leaderId_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           leaderId_ = b;
@@ -2061,22 +2061,22 @@ public final class AppendEntriesMessages {
       }
 
       // repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;
-      private java.util.List<org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry> logEntries_ =
+      private java.util.List<org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry> logEntries_ =
         java.util.Collections.emptyList();
       private void ensureLogEntriesIsMutable() {
         if (!((bitField0_ & 0x00000010) == 0x00000010)) {
-          logEntries_ = new java.util.ArrayList<org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry>(logEntries_);
+          logEntries_ = new java.util.ArrayList<org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry>(logEntries_);
           bitField0_ |= 0x00000010;
          }
       }
 
       private com.google.protobuf.RepeatedFieldBuilder<
-          org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder> logEntriesBuilder_;
+          org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder> logEntriesBuilder_;
 
       /**
        * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
        */
-      public java.util.List<org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry> getLogEntriesList() {
+      public java.util.List<org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry> getLogEntriesList() {
         if (logEntriesBuilder_ == null) {
           return java.util.Collections.unmodifiableList(logEntries_);
         } else {
@@ -2096,7 +2096,7 @@ public final class AppendEntriesMessages {
       /**
        * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
        */
-      public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry getLogEntries(int index) {
+      public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry getLogEntries(int index) {
         if (logEntriesBuilder_ == null) {
           return logEntries_.get(index);
         } else {
@@ -2107,7 +2107,7 @@ public final class AppendEntriesMessages {
        * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
        */
       public Builder setLogEntries(
-          int index, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry value) {
+          int index, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry value) {
         if (logEntriesBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -2124,7 +2124,7 @@ public final class AppendEntriesMessages {
        * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
        */
       public Builder setLogEntries(
-          int index, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder builderForValue) {
+          int index, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder builderForValue) {
         if (logEntriesBuilder_ == null) {
           ensureLogEntriesIsMutable();
           logEntries_.set(index, builderForValue.build());
@@ -2137,7 +2137,7 @@ public final class AppendEntriesMessages {
       /**
        * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
        */
-      public Builder addLogEntries(org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry value) {
+      public Builder addLogEntries(org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry value) {
         if (logEntriesBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -2154,7 +2154,7 @@ public final class AppendEntriesMessages {
        * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
        */
       public Builder addLogEntries(
-          int index, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry value) {
+          int index, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry value) {
         if (logEntriesBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -2171,7 +2171,7 @@ public final class AppendEntriesMessages {
        * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
        */
       public Builder addLogEntries(
-          org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder builderForValue) {
+          org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder builderForValue) {
         if (logEntriesBuilder_ == null) {
           ensureLogEntriesIsMutable();
           logEntries_.add(builderForValue.build());
@@ -2185,7 +2185,7 @@ public final class AppendEntriesMessages {
        * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
        */
       public Builder addLogEntries(
-          int index, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder builderForValue) {
+          int index, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder builderForValue) {
         if (logEntriesBuilder_ == null) {
           ensureLogEntriesIsMutable();
           logEntries_.add(index, builderForValue.build());
@@ -2199,7 +2199,7 @@ public final class AppendEntriesMessages {
        * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
        */
       public Builder addAllLogEntries(
-          java.lang.Iterable<? extends org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry> values) {
+          java.lang.Iterable<? extends org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry> values) {
         if (logEntriesBuilder_ == null) {
           ensureLogEntriesIsMutable();
           super.addAll(values, logEntries_);
@@ -2238,14 +2238,14 @@ public final class AppendEntriesMessages {
       /**
        * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
        */
-      public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder getLogEntriesBuilder(
+      public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder getLogEntriesBuilder(
           int index) {
         return getLogEntriesFieldBuilder().getBuilder(index);
       }
       /**
        * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
        */
-      public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder getLogEntriesOrBuilder(
+      public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder getLogEntriesOrBuilder(
           int index) {
         if (logEntriesBuilder_ == null) {
           return logEntries_.get(index);  } else {
@@ -2255,7 +2255,7 @@ public final class AppendEntriesMessages {
       /**
        * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
        */
-      public java.util.List<? extends org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder> 
+      public java.util.List<? extends org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder>
            getLogEntriesOrBuilderList() {
         if (logEntriesBuilder_ != null) {
           return logEntriesBuilder_.getMessageOrBuilderList();
@@ -2266,31 +2266,31 @@ public final class AppendEntriesMessages {
       /**
        * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
        */
-      public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder addLogEntriesBuilder() {
+      public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder addLogEntriesBuilder() {
         return getLogEntriesFieldBuilder().addBuilder(
-            org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.getDefaultInstance());
+            org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.getDefaultInstance());
       }
       /**
        * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
        */
-      public org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder addLogEntriesBuilder(
+      public org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder addLogEntriesBuilder(
           int index) {
         return getLogEntriesFieldBuilder().addBuilder(
-            index, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.getDefaultInstance());
+            index, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.getDefaultInstance());
       }
       /**
        * <code>repeated .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry logEntries = 5;</code>
        */
-      public java.util.List<org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder> 
+      public java.util.List<org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder>
            getLogEntriesBuilderList() {
         return getLogEntriesFieldBuilder().getBuilderList();
       }
       private com.google.protobuf.RepeatedFieldBuilder<
-          org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder>
           getLogEntriesFieldBuilder() {
         if (logEntriesBuilder_ == null) {
           logEntriesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
-              org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder, org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder>(
+              org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Builder, org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntryOrBuilder>(
                   logEntries_,
                   ((bitField0_ & 0x00000010) == 0x00000010),
                   getParentForChildren(),
@@ -2380,8 +2380,8 @@ public final class AppendEntriesMessages {
       "aylight.controller.cluster.raft.AppendEn",
       "tries.ReplicatedLogEntry.Payload\032/\n\007Payl" +
       "oad\022\036\n\026clientPayloadClassName\030\001 \001(\t*\004\010\002\020" +
-      "eBV\n;org.opendaylight.controller.cluster" +
-      ".raft.protobuff.messagesB\025AppendEntriesM" +
+      "eBV\n;org.opendaylight.controller.protobu" +
+      "ff.messages.cluster.raftB\025AppendEntriesM" +
       "essagesH\001"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
@@ -1,13 +1,13 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: MockPayload.proto
 
-package org.opendaylight.controller.cluster.raft.protobuff.messages;
+package org.opendaylight.controller.protobuff.messages.cluster.raft.test;
 
 public final class MockPayloadMessages {
   private MockPayloadMessages() {}
   public static void registerAllExtensions(
       com.google.protobuf.ExtensionRegistry registry) {
-    registry.add(org.opendaylight.controller.cluster.raft.protobuff.messages.MockPayloadMessages.value);
+    registry.add(org.opendaylight.controller.protobuff.messages.cluster.raft.test.MockPayloadMessages.value);
   }
   public static final int VALUE_FIELD_NUMBER = 2;
   /**
@@ -15,7 +15,7 @@ public final class MockPayloadMessages {
    */
   public static final
     com.google.protobuf.GeneratedMessage.GeneratedExtension<
-      org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload,
+      org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload,
       java.lang.String> value = com.google.protobuf.GeneratedMessage
           .newFileScopedGeneratedExtension(
         java.lang.String.class,
@@ -29,13 +29,14 @@ public final class MockPayloadMessages {
       descriptor;
   static {
     java.lang.String[] descriptorData = {
-      "\n\021MockPayload.proto\022(org.opendaylight.co" +
-      "ntroller.cluster.raft\032\033AppendEntriesMess" +
-      "ages.proto:a\n\005value\022R.org.opendaylight.c" +
-      "ontroller.cluster.raft.AppendEntries.Rep" +
-      "licatedLogEntry.Payload\030\002 \001(\tBR\n;org.ope" +
-      "ndaylight.controller.cluster.raft.protob" +
-      "uff.messagesB\023MockPayloadMessages"
+      "\n\021MockPayload.proto\022-org.opendaylight.co" +
+      "ntroller.cluster.raft.test\032\033AppendEntrie" +
+      "sMessages.proto:a\n\005value\022R.org.opendayli" +
+      "ght.controller.cluster.raft.AppendEntrie" +
+      "s.ReplicatedLogEntry.Payload\030\002 \001(\tBW\n@or" +
+      "g.opendaylight.controller.protobuff.mess" +
+      "ages.cluster.raft.testB\023MockPayloadMessa" +
+      "ges"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
       new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -49,7 +50,7 @@ public final class MockPayloadMessages {
     com.google.protobuf.Descriptors.FileDescriptor
       .internalBuildGeneratedFileFrom(descriptorData,
         new com.google.protobuf.Descriptors.FileDescriptor[] {
-          org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.getDescriptor(),
+          org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.getDescriptor(),
         }, assigner);
   }
 
index 35c2940be3e05aa9e03d8c922ecffde2cd0e823a..3926bc7dc347d611a67854ab14015734424d749b 100644 (file)
@@ -799,23 +799,809 @@ public final class NormalizedNodeMessages {
     // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.Attribute)
   }
 
+  public interface PathArgumentAttributeOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // optional .org.opendaylight.controller.mdsal.QName name = 1;
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.QName name = 1;</code>
+     */
+    boolean hasName();
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.QName name = 1;</code>
+     */
+    org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName getName();
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.QName name = 1;</code>
+     */
+    org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder getNameOrBuilder();
+
+    // optional string value = 2;
+    /**
+     * <code>optional string value = 2;</code>
+     */
+    boolean hasValue();
+    /**
+     * <code>optional string value = 2;</code>
+     */
+    java.lang.String getValue();
+    /**
+     * <code>optional string value = 2;</code>
+     */
+    com.google.protobuf.ByteString
+        getValueBytes();
+
+    // optional int32 type = 3;
+    /**
+     * <code>optional int32 type = 3;</code>
+     */
+    boolean hasType();
+    /**
+     * <code>optional int32 type = 3;</code>
+     */
+    int getType();
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.PathArgumentAttribute}
+   */
+  public static final class PathArgumentAttribute extends
+      com.google.protobuf.GeneratedMessage
+      implements PathArgumentAttributeOrBuilder {
+    // Use PathArgumentAttribute.newBuilder() to construct.
+    private PathArgumentAttribute(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private PathArgumentAttribute(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final PathArgumentAttribute defaultInstance;
+    public static PathArgumentAttribute getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public PathArgumentAttribute getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private PathArgumentAttribute(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.Builder subBuilder = null;
+              if (((bitField0_ & 0x00000001) == 0x00000001)) {
+                subBuilder = name_.toBuilder();
+              }
+              name_ = input.readMessage(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.PARSER, extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(name_);
+                name_ = subBuilder.buildPartial();
+              }
+              bitField0_ |= 0x00000001;
+              break;
+            }
+            case 18: {
+              bitField0_ |= 0x00000002;
+              value_ = input.readBytes();
+              break;
+            }
+            case 24: {
+              bitField0_ |= 0x00000004;
+              type_ = input.readInt32();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.internal_static_org_opendaylight_controller_mdsal_PathArgumentAttribute_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.internal_static_org_opendaylight_controller_mdsal_PathArgumentAttribute_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.class, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<PathArgumentAttribute> PARSER =
+        new com.google.protobuf.AbstractParser<PathArgumentAttribute>() {
+      public PathArgumentAttribute parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new PathArgumentAttribute(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<PathArgumentAttribute> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    // optional .org.opendaylight.controller.mdsal.QName name = 1;
+    public static final int NAME_FIELD_NUMBER = 1;
+    private org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName name_;
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.QName name = 1;</code>
+     */
+    public boolean hasName() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.QName name = 1;</code>
+     */
+    public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName getName() {
+      return name_;
+    }
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.QName name = 1;</code>
+     */
+    public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder getNameOrBuilder() {
+      return name_;
+    }
+
+    // optional string value = 2;
+    public static final int VALUE_FIELD_NUMBER = 2;
+    private java.lang.Object value_;
+    /**
+     * <code>optional string value = 2;</code>
+     */
+    public boolean hasValue() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>optional string value = 2;</code>
+     */
+    public java.lang.String getValue() {
+      java.lang.Object ref = value_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          value_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string value = 2;</code>
+     */
+    public com.google.protobuf.ByteString
+        getValueBytes() {
+      java.lang.Object ref = value_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b =
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        value_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    // optional int32 type = 3;
+    public static final int TYPE_FIELD_NUMBER = 3;
+    private int type_;
+    /**
+     * <code>optional int32 type = 3;</code>
+     */
+    public boolean hasType() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>optional int32 type = 3;</code>
+     */
+    public int getType() {
+      return type_;
+    }
+
+    private void initFields() {
+      name_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.getDefaultInstance();
+      value_ = "";
+      type_ = 0;
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeMessage(1, name_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeBytes(2, getValueBytes());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeInt32(3, type_);
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(1, name_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(2, getValueBytes());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(3, type_);
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.PathArgumentAttribute}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttributeOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.internal_static_org_opendaylight_controller_mdsal_PathArgumentAttribute_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.internal_static_org_opendaylight_controller_mdsal_PathArgumentAttribute_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.class, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+          getNameFieldBuilder();
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        if (nameBuilder_ == null) {
+          name_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.getDefaultInstance();
+        } else {
+          nameBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000001);
+        value_ = "";
+        bitField0_ = (bitField0_ & ~0x00000002);
+        type_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000004);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.internal_static_org_opendaylight_controller_mdsal_PathArgumentAttribute_descriptor;
+      }
+
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute getDefaultInstanceForType() {
+        return org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute build() {
+        org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute buildPartial() {
+        org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute result = new org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        if (nameBuilder_ == null) {
+          result.name_ = name_;
+        } else {
+          result.name_ = nameBuilder_.build();
+        }
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.value_ = value_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.type_ = type_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute) {
+          return mergeFrom((org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute other) {
+        if (other == org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.getDefaultInstance()) return this;
+        if (other.hasName()) {
+          mergeName(other.getName());
+        }
+        if (other.hasValue()) {
+          bitField0_ |= 0x00000002;
+          value_ = other.value_;
+          onChanged();
+        }
+        if (other.hasType()) {
+          setType(other.getType());
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // optional .org.opendaylight.controller.mdsal.QName name = 1;
+      private org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName name_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.getDefaultInstance();
+      private com.google.protobuf.SingleFieldBuilder<
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder> nameBuilder_;
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.QName name = 1;</code>
+       */
+      public boolean hasName() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.QName name = 1;</code>
+       */
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName getName() {
+        if (nameBuilder_ == null) {
+          return name_;
+        } else {
+          return nameBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.QName name = 1;</code>
+       */
+      public Builder setName(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName value) {
+        if (nameBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          name_ = value;
+          onChanged();
+        } else {
+          nameBuilder_.setMessage(value);
+        }
+        bitField0_ |= 0x00000001;
+        return this;
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.QName name = 1;</code>
+       */
+      public Builder setName(
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.Builder builderForValue) {
+        if (nameBuilder_ == null) {
+          name_ = builderForValue.build();
+          onChanged();
+        } else {
+          nameBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00000001;
+        return this;
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.QName name = 1;</code>
+       */
+      public Builder mergeName(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName value) {
+        if (nameBuilder_ == null) {
+          if (((bitField0_ & 0x00000001) == 0x00000001) &&
+              name_ != org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.getDefaultInstance()) {
+            name_ =
+              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.newBuilder(name_).mergeFrom(value).buildPartial();
+          } else {
+            name_ = value;
+          }
+          onChanged();
+        } else {
+          nameBuilder_.mergeFrom(value);
+        }
+        bitField0_ |= 0x00000001;
+        return this;
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.QName name = 1;</code>
+       */
+      public Builder clearName() {
+        if (nameBuilder_ == null) {
+          name_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.getDefaultInstance();
+          onChanged();
+        } else {
+          nameBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000001);
+        return this;
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.QName name = 1;</code>
+       */
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.Builder getNameBuilder() {
+        bitField0_ |= 0x00000001;
+        onChanged();
+        return getNameFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.QName name = 1;</code>
+       */
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder getNameOrBuilder() {
+        if (nameBuilder_ != null) {
+          return nameBuilder_.getMessageOrBuilder();
+        } else {
+          return name_;
+        }
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.QName name = 1;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilder<
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder>
+          getNameFieldBuilder() {
+        if (nameBuilder_ == null) {
+          nameBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder>(
+                  name_,
+                  getParentForChildren(),
+                  isClean());
+          name_ = null;
+        }
+        return nameBuilder_;
+      }
+
+      // optional string value = 2;
+      private java.lang.Object value_ = "";
+      /**
+       * <code>optional string value = 2;</code>
+       */
+      public boolean hasValue() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>optional string value = 2;</code>
+       */
+      public java.lang.String getValue() {
+        java.lang.Object ref = value_;
+        if (!(ref instanceof java.lang.String)) {
+          java.lang.String s = ((com.google.protobuf.ByteString) ref)
+              .toStringUtf8();
+          value_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string value = 2;</code>
+       */
+      public com.google.protobuf.ByteString
+          getValueBytes() {
+        java.lang.Object ref = value_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b =
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          value_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string value = 2;</code>
+       */
+      public Builder setValue(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+        value_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string value = 2;</code>
+       */
+      public Builder clearValue() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        value_ = getDefaultInstance().getValue();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string value = 2;</code>
+       */
+      public Builder setValueBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+        value_ = value;
+        onChanged();
+        return this;
+      }
+
+      // optional int32 type = 3;
+      private int type_ ;
+      /**
+       * <code>optional int32 type = 3;</code>
+       */
+      public boolean hasType() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>optional int32 type = 3;</code>
+       */
+      public int getType() {
+        return type_;
+      }
+      /**
+       * <code>optional int32 type = 3;</code>
+       */
+      public Builder setType(int value) {
+        bitField0_ |= 0x00000004;
+        type_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int32 type = 3;</code>
+       */
+      public Builder clearType() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        type_ = 0;
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.PathArgumentAttribute)
+    }
+
+    static {
+      defaultInstance = new PathArgumentAttribute(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.PathArgumentAttribute)
+  }
+
   public interface QNameOrBuilder
       extends com.google.protobuf.MessageOrBuilder {
 
-    // required string value = 1;
+    // optional string value = 1;
+    /**
+     * <code>optional string value = 1;</code>
+     *
+     * <pre>
+     * @deprecated
+     * </pre>
+     */
+    boolean hasValue();
+    /**
+     * <code>optional string value = 1;</code>
+     *
+     * <pre>
+     * @deprecated
+     * </pre>
+     */
+    java.lang.String getValue();
+    /**
+     * <code>optional string value = 1;</code>
+     *
+     * <pre>
+     * @deprecated
+     * </pre>
+     */
+    com.google.protobuf.ByteString
+        getValueBytes();
+
+    // optional int32 namespace = 2;
     /**
-     * <code>required string value = 1;</code>
+     * <code>optional int32 namespace = 2;</code>
      */
-    boolean hasValue();
+    boolean hasNamespace();
     /**
-     * <code>required string value = 1;</code>
+     * <code>optional int32 namespace = 2;</code>
      */
-    java.lang.String getValue();
+    int getNamespace();
+
+    // optional int32 revision = 3;
     /**
-     * <code>required string value = 1;</code>
+     * <code>optional int32 revision = 3;</code>
      */
-    com.google.protobuf.ByteString
-        getValueBytes();
+    boolean hasRevision();
+    /**
+     * <code>optional int32 revision = 3;</code>
+     */
+    int getRevision();
+
+    // optional int32 localName = 4;
+    /**
+     * <code>optional int32 localName = 4;</code>
+     */
+    boolean hasLocalName();
+    /**
+     * <code>optional int32 localName = 4;</code>
+     */
+    int getLocalName();
   }
   /**
    * Protobuf type {@code org.opendaylight.controller.mdsal.QName}
@@ -873,6 +1659,21 @@ public final class NormalizedNodeMessages {
               value_ = input.readBytes();
               break;
             }
+            case 16: {
+              bitField0_ |= 0x00000002;
+              namespace_ = input.readInt32();
+              break;
+            }
+            case 24: {
+              bitField0_ |= 0x00000004;
+              revision_ = input.readInt32();
+              break;
+            }
+            case 32: {
+              bitField0_ |= 0x00000008;
+              localName_ = input.readInt32();
+              break;
+            }
           }
         }
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -913,17 +1714,25 @@ public final class NormalizedNodeMessages {
     }
 
     private int bitField0_;
-    // required string value = 1;
+    // optional string value = 1;
     public static final int VALUE_FIELD_NUMBER = 1;
     private java.lang.Object value_;
     /**
-     * <code>required string value = 1;</code>
+     * <code>optional string value = 1;</code>
+     *
+     * <pre>
+     * @deprecated
+     * </pre>
      */
     public boolean hasValue() {
       return ((bitField0_ & 0x00000001) == 0x00000001);
     }
     /**
-     * <code>required string value = 1;</code>
+     * <code>optional string value = 1;</code>
+     *
+     * <pre>
+     * @deprecated
+     * </pre>
      */
     public java.lang.String getValue() {
       java.lang.Object ref = value_;
@@ -940,7 +1749,11 @@ public final class NormalizedNodeMessages {
       }
     }
     /**
-     * <code>required string value = 1;</code>
+     * <code>optional string value = 1;</code>
+     *
+     * <pre>
+     * @deprecated
+     * </pre>
      */
     public com.google.protobuf.ByteString
         getValueBytes() {
@@ -956,18 +1769,65 @@ public final class NormalizedNodeMessages {
       }
     }
 
+    // optional int32 namespace = 2;
+    public static final int NAMESPACE_FIELD_NUMBER = 2;
+    private int namespace_;
+    /**
+     * <code>optional int32 namespace = 2;</code>
+     */
+    public boolean hasNamespace() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>optional int32 namespace = 2;</code>
+     */
+    public int getNamespace() {
+      return namespace_;
+    }
+
+    // optional int32 revision = 3;
+    public static final int REVISION_FIELD_NUMBER = 3;
+    private int revision_;
+    /**
+     * <code>optional int32 revision = 3;</code>
+     */
+    public boolean hasRevision() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>optional int32 revision = 3;</code>
+     */
+    public int getRevision() {
+      return revision_;
+    }
+
+    // optional int32 localName = 4;
+    public static final int LOCALNAME_FIELD_NUMBER = 4;
+    private int localName_;
+    /**
+     * <code>optional int32 localName = 4;</code>
+     */
+    public boolean hasLocalName() {
+      return ((bitField0_ & 0x00000008) == 0x00000008);
+    }
+    /**
+     * <code>optional int32 localName = 4;</code>
+     */
+    public int getLocalName() {
+      return localName_;
+    }
+
     private void initFields() {
       value_ = "";
+      namespace_ = 0;
+      revision_ = 0;
+      localName_ = 0;
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
       byte isInitialized = memoizedIsInitialized;
       if (isInitialized != -1) return isInitialized == 1;
 
-      if (!hasValue()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
       memoizedIsInitialized = 1;
       return true;
     }
@@ -978,6 +1838,15 @@ public final class NormalizedNodeMessages {
       if (((bitField0_ & 0x00000001) == 0x00000001)) {
         output.writeBytes(1, getValueBytes());
       }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeInt32(2, namespace_);
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeInt32(3, revision_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        output.writeInt32(4, localName_);
+      }
       getUnknownFields().writeTo(output);
     }
 
@@ -991,6 +1860,18 @@ public final class NormalizedNodeMessages {
         size += com.google.protobuf.CodedOutputStream
           .computeBytesSize(1, getValueBytes());
       }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(2, namespace_);
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(3, revision_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(4, localName_);
+      }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
       return size;
@@ -1109,6 +1990,12 @@ public final class NormalizedNodeMessages {
         super.clear();
         value_ = "";
         bitField0_ = (bitField0_ & ~0x00000001);
+        namespace_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000002);
+        revision_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000004);
+        localName_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000008);
         return this;
       }
 
@@ -1141,6 +2028,18 @@ public final class NormalizedNodeMessages {
           to_bitField0_ |= 0x00000001;
         }
         result.value_ = value_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.namespace_ = namespace_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.revision_ = revision_;
+        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+          to_bitField0_ |= 0x00000008;
+        }
+        result.localName_ = localName_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
@@ -1162,15 +2061,20 @@ public final class NormalizedNodeMessages {
           value_ = other.value_;
           onChanged();
         }
+        if (other.hasNamespace()) {
+          setNamespace(other.getNamespace());
+        }
+        if (other.hasRevision()) {
+          setRevision(other.getRevision());
+        }
+        if (other.hasLocalName()) {
+          setLocalName(other.getLocalName());
+        }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
 
       public final boolean isInitialized() {
-        if (!hasValue()) {
-
-          return false;
-        }
         return true;
       }
 
@@ -1193,16 +2097,24 @@ public final class NormalizedNodeMessages {
       }
       private int bitField0_;
 
-      // required string value = 1;
+      // optional string value = 1;
       private java.lang.Object value_ = "";
       /**
-       * <code>required string value = 1;</code>
+       * <code>optional string value = 1;</code>
+       *
+       * <pre>
+       * @deprecated
+       * </pre>
        */
       public boolean hasValue() {
         return ((bitField0_ & 0x00000001) == 0x00000001);
       }
       /**
-       * <code>required string value = 1;</code>
+       * <code>optional string value = 1;</code>
+       *
+       * <pre>
+       * @deprecated
+       * </pre>
        */
       public java.lang.String getValue() {
         java.lang.Object ref = value_;
@@ -1216,7 +2128,11 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>required string value = 1;</code>
+       * <code>optional string value = 1;</code>
+       *
+       * <pre>
+       * @deprecated
+       * </pre>
        */
       public com.google.protobuf.ByteString
           getValueBytes() {
@@ -1232,7 +2148,11 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>required string value = 1;</code>
+       * <code>optional string value = 1;</code>
+       *
+       * <pre>
+       * @deprecated
+       * </pre>
        */
       public Builder setValue(
           java.lang.String value) {
@@ -1245,7 +2165,11 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>required string value = 1;</code>
+       * <code>optional string value = 1;</code>
+       *
+       * <pre>
+       * @deprecated
+       * </pre>
        */
       public Builder clearValue() {
         bitField0_ = (bitField0_ & ~0x00000001);
@@ -1254,7 +2178,11 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>required string value = 1;</code>
+       * <code>optional string value = 1;</code>
+       *
+       * <pre>
+       * @deprecated
+       * </pre>
        */
       public Builder setValueBytes(
           com.google.protobuf.ByteString value) {
@@ -1267,6 +2195,105 @@ public final class NormalizedNodeMessages {
         return this;
       }
 
+      // optional int32 namespace = 2;
+      private int namespace_ ;
+      /**
+       * <code>optional int32 namespace = 2;</code>
+       */
+      public boolean hasNamespace() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>optional int32 namespace = 2;</code>
+       */
+      public int getNamespace() {
+        return namespace_;
+      }
+      /**
+       * <code>optional int32 namespace = 2;</code>
+       */
+      public Builder setNamespace(int value) {
+        bitField0_ |= 0x00000002;
+        namespace_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int32 namespace = 2;</code>
+       */
+      public Builder clearNamespace() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        namespace_ = 0;
+        onChanged();
+        return this;
+      }
+
+      // optional int32 revision = 3;
+      private int revision_ ;
+      /**
+       * <code>optional int32 revision = 3;</code>
+       */
+      public boolean hasRevision() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>optional int32 revision = 3;</code>
+       */
+      public int getRevision() {
+        return revision_;
+      }
+      /**
+       * <code>optional int32 revision = 3;</code>
+       */
+      public Builder setRevision(int value) {
+        bitField0_ |= 0x00000004;
+        revision_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int32 revision = 3;</code>
+       */
+      public Builder clearRevision() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        revision_ = 0;
+        onChanged();
+        return this;
+      }
+
+      // optional int32 localName = 4;
+      private int localName_ ;
+      /**
+       * <code>optional int32 localName = 4;</code>
+       */
+      public boolean hasLocalName() {
+        return ((bitField0_ & 0x00000008) == 0x00000008);
+      }
+      /**
+       * <code>optional int32 localName = 4;</code>
+       */
+      public int getLocalName() {
+        return localName_;
+      }
+      /**
+       * <code>optional int32 localName = 4;</code>
+       */
+      public Builder setLocalName(int value) {
+        bitField0_ |= 0x00000008;
+        localName_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int32 localName = 4;</code>
+       */
+      public Builder clearLocalName() {
+        bitField0_ = (bitField0_ & ~0x00000008);
+        localName_ = 0;
+        onChanged();
+        return this;
+      }
+
       // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.QName)
     }
 
@@ -1281,17 +2308,29 @@ public final class NormalizedNodeMessages {
   public interface PathArgumentOrBuilder
       extends com.google.protobuf.MessageOrBuilder {
 
-    // required string value = 1;
+    // optional string value = 1;
     /**
-     * <code>required string value = 1;</code>
+     * <code>optional string value = 1;</code>
+     *
+     * <pre>
+     * @deprecated
+     * </pre>
      */
     boolean hasValue();
     /**
-     * <code>required string value = 1;</code>
+     * <code>optional string value = 1;</code>
+     *
+     * <pre>
+     * @deprecated
+     * </pre>
      */
     java.lang.String getValue();
     /**
-     * <code>required string value = 1;</code>
+     * <code>optional string value = 1;</code>
+     *
+     * <pre>
+     * @deprecated
+     * </pre>
      */
     com.google.protobuf.ByteString
         getValueBytes();
@@ -1301,7 +2340,7 @@ public final class NormalizedNodeMessages {
      * <code>optional string type = 2;</code>
      *
      * <pre>
-     *NodeIdentifier, NodeWithValue, NodeIdentifierWithPredicates
+     * @deprecated
      * </pre>
      */
     boolean hasType();
@@ -1309,7 +2348,7 @@ public final class NormalizedNodeMessages {
      * <code>optional string type = 2;</code>
      *
      * <pre>
-     *NodeIdentifier, NodeWithValue, NodeIdentifierWithPredicates
+     * @deprecated
      * </pre>
      */
     java.lang.String getType();
@@ -1317,7 +2356,7 @@ public final class NormalizedNodeMessages {
      * <code>optional string type = 2;</code>
      *
      * <pre>
-     *NodeIdentifier, NodeWithValue, NodeIdentifierWithPredicates
+     * @deprecated
      * </pre>
      */
     com.google.protobuf.ByteString
@@ -1337,30 +2376,85 @@ public final class NormalizedNodeMessages {
      */
     org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder getNodeTypeOrBuilder();
 
-    // repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;
+    // repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;
+    /**
+     * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+     */
+    java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute>
+        getAttributeList();
+    /**
+     * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+     */
+    org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute getAttribute(int index);
+    /**
+     * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+     */
+    int getAttributeCount();
+    /**
+     * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+     */
+    java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttributeOrBuilder>
+        getAttributeOrBuilderList();
+    /**
+     * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+     */
+    org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttributeOrBuilder getAttributeOrBuilder(
+        int index);
+
+    // repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+     *
+     * <pre>
+     * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+     * </pre>
      */
     java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute>
         getAttributesList();
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+     *
+     * <pre>
+     * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+     * </pre>
      */
     org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute getAttributes(int index);
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+     *
+     * <pre>
+     * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+     * </pre>
      */
     int getAttributesCount();
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+     *
+     * <pre>
+     * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+     * </pre>
      */
     java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
         getAttributesOrBuilderList();
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+     *
+     * <pre>
+     * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+     * </pre>
      */
     org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder getAttributesOrBuilder(
         int index);
+
+    // optional int32 intType = 6;
+    /**
+     * <code>optional int32 intType = 6;</code>
+     */
+    boolean hasIntType();
+    /**
+     * <code>optional int32 intType = 6;</code>
+     */
+    int getIntType();
   }
   /**
    * Protobuf type {@code org.opendaylight.controller.mdsal.PathArgument}
@@ -1438,12 +2532,25 @@ public final class NormalizedNodeMessages {
             }
             case 34: {
               if (!((mutable_bitField0_ & 0x00000008) == 0x00000008)) {
-                attributes_ = new java.util.ArrayList<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute>();
+                attribute_ = new java.util.ArrayList<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute>();
                 mutable_bitField0_ |= 0x00000008;
               }
+              attribute_.add(input.readMessage(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.PARSER, extensionRegistry));
+              break;
+            }
+            case 42: {
+              if (!((mutable_bitField0_ & 0x00000010) == 0x00000010)) {
+                attributes_ = new java.util.ArrayList<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute>();
+                mutable_bitField0_ |= 0x00000010;
+              }
               attributes_.add(input.readMessage(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.PARSER, extensionRegistry));
               break;
             }
+            case 48: {
+              bitField0_ |= 0x00000008;
+              intType_ = input.readInt32();
+              break;
+            }
           }
         }
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -1453,6 +2560,9 @@ public final class NormalizedNodeMessages {
             e.getMessage()).setUnfinishedMessage(this);
       } finally {
         if (((mutable_bitField0_ & 0x00000008) == 0x00000008)) {
+          attribute_ = java.util.Collections.unmodifiableList(attribute_);
+        }
+        if (((mutable_bitField0_ & 0x00000010) == 0x00000010)) {
           attributes_ = java.util.Collections.unmodifiableList(attributes_);
         }
         this.unknownFields = unknownFields.build();
@@ -1487,17 +2597,25 @@ public final class NormalizedNodeMessages {
     }
 
     private int bitField0_;
-    // required string value = 1;
+    // optional string value = 1;
     public static final int VALUE_FIELD_NUMBER = 1;
     private java.lang.Object value_;
     /**
-     * <code>required string value = 1;</code>
+     * <code>optional string value = 1;</code>
+     *
+     * <pre>
+     * @deprecated
+     * </pre>
      */
     public boolean hasValue() {
       return ((bitField0_ & 0x00000001) == 0x00000001);
     }
     /**
-     * <code>required string value = 1;</code>
+     * <code>optional string value = 1;</code>
+     *
+     * <pre>
+     * @deprecated
+     * </pre>
      */
     public java.lang.String getValue() {
       java.lang.Object ref = value_;
@@ -1514,7 +2632,11 @@ public final class NormalizedNodeMessages {
       }
     }
     /**
-     * <code>required string value = 1;</code>
+     * <code>optional string value = 1;</code>
+     *
+     * <pre>
+     * @deprecated
+     * </pre>
      */
     public com.google.protobuf.ByteString
         getValueBytes() {
@@ -1537,7 +2659,7 @@ public final class NormalizedNodeMessages {
      * <code>optional string type = 2;</code>
      *
      * <pre>
-     *NodeIdentifier, NodeWithValue, NodeIdentifierWithPredicates
+     * @deprecated
      * </pre>
      */
     public boolean hasType() {
@@ -1547,7 +2669,7 @@ public final class NormalizedNodeMessages {
      * <code>optional string type = 2;</code>
      *
      * <pre>
-     *NodeIdentifier, NodeWithValue, NodeIdentifierWithPredicates
+     * @deprecated
      * </pre>
      */
     public java.lang.String getType() {
@@ -1568,7 +2690,7 @@ public final class NormalizedNodeMessages {
      * <code>optional string type = 2;</code>
      *
      * <pre>
-     *NodeIdentifier, NodeWithValue, NodeIdentifierWithPredicates
+     * @deprecated
      * </pre>
      */
     public com.google.protobuf.ByteString
@@ -1584,86 +2706,150 @@ public final class NormalizedNodeMessages {
         return (com.google.protobuf.ByteString) ref;
       }
     }
-
-    // optional .org.opendaylight.controller.mdsal.QName nodeType = 3;
-    public static final int NODETYPE_FIELD_NUMBER = 3;
-    private org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName nodeType_;
+
+    // optional .org.opendaylight.controller.mdsal.QName nodeType = 3;
+    public static final int NODETYPE_FIELD_NUMBER = 3;
+    private org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName nodeType_;
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.QName nodeType = 3;</code>
+     */
+    public boolean hasNodeType() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.QName nodeType = 3;</code>
+     */
+    public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName getNodeType() {
+      return nodeType_;
+    }
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.QName nodeType = 3;</code>
+     */
+    public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder getNodeTypeOrBuilder() {
+      return nodeType_;
+    }
+
+    // repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;
+    public static final int ATTRIBUTE_FIELD_NUMBER = 4;
+    private java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute> attribute_;
+    /**
+     * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+     */
+    public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute> getAttributeList() {
+      return attribute_;
+    }
+    /**
+     * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+     */
+    public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttributeOrBuilder>
+        getAttributeOrBuilderList() {
+      return attribute_;
+    }
     /**
-     * <code>optional .org.opendaylight.controller.mdsal.QName nodeType = 3;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
      */
-    public boolean hasNodeType() {
-      return ((bitField0_ & 0x00000004) == 0x00000004);
+    public int getAttributeCount() {
+      return attribute_.size();
     }
     /**
-     * <code>optional .org.opendaylight.controller.mdsal.QName nodeType = 3;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
      */
-    public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName getNodeType() {
-      return nodeType_;
+    public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute getAttribute(int index) {
+      return attribute_.get(index);
     }
     /**
-     * <code>optional .org.opendaylight.controller.mdsal.QName nodeType = 3;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
      */
-    public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder getNodeTypeOrBuilder() {
-      return nodeType_;
+    public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttributeOrBuilder getAttributeOrBuilder(
+        int index) {
+      return attribute_.get(index);
     }
 
-    // repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;
-    public static final int ATTRIBUTES_FIELD_NUMBER = 4;
+    // repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;
+    public static final int ATTRIBUTES_FIELD_NUMBER = 5;
     private java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute> attributes_;
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+     *
+     * <pre>
+     * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+     * </pre>
      */
     public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute> getAttributesList() {
       return attributes_;
     }
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+     *
+     * <pre>
+     * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+     * </pre>
      */
     public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
         getAttributesOrBuilderList() {
       return attributes_;
     }
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+     *
+     * <pre>
+     * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+     * </pre>
      */
     public int getAttributesCount() {
       return attributes_.size();
     }
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+     *
+     * <pre>
+     * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+     * </pre>
      */
     public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute getAttributes(int index) {
       return attributes_.get(index);
     }
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+     *
+     * <pre>
+     * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+     * </pre>
      */
     public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder getAttributesOrBuilder(
         int index) {
       return attributes_.get(index);
     }
 
+    // optional int32 intType = 6;
+    public static final int INTTYPE_FIELD_NUMBER = 6;
+    private int intType_;
+    /**
+     * <code>optional int32 intType = 6;</code>
+     */
+    public boolean hasIntType() {
+      return ((bitField0_ & 0x00000008) == 0x00000008);
+    }
+    /**
+     * <code>optional int32 intType = 6;</code>
+     */
+    public int getIntType() {
+      return intType_;
+    }
+
     private void initFields() {
       value_ = "";
       type_ = "";
       nodeType_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.getDefaultInstance();
+      attribute_ = java.util.Collections.emptyList();
       attributes_ = java.util.Collections.emptyList();
+      intType_ = 0;
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
       byte isInitialized = memoizedIsInitialized;
       if (isInitialized != -1) return isInitialized == 1;
 
-      if (!hasValue()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      if (hasNodeType()) {
-        if (!getNodeType().isInitialized()) {
-          memoizedIsInitialized = 0;
-          return false;
-        }
-      }
       for (int i = 0; i < getAttributesCount(); i++) {
         if (!getAttributes(i).isInitialized()) {
           memoizedIsInitialized = 0;
@@ -1686,8 +2872,14 @@ public final class NormalizedNodeMessages {
       if (((bitField0_ & 0x00000004) == 0x00000004)) {
         output.writeMessage(3, nodeType_);
       }
+      for (int i = 0; i < attribute_.size(); i++) {
+        output.writeMessage(4, attribute_.get(i));
+      }
       for (int i = 0; i < attributes_.size(); i++) {
-        output.writeMessage(4, attributes_.get(i));
+        output.writeMessage(5, attributes_.get(i));
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        output.writeInt32(6, intType_);
       }
       getUnknownFields().writeTo(output);
     }
@@ -1710,9 +2902,17 @@ public final class NormalizedNodeMessages {
         size += com.google.protobuf.CodedOutputStream
           .computeMessageSize(3, nodeType_);
       }
+      for (int i = 0; i < attribute_.size(); i++) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(4, attribute_.get(i));
+      }
       for (int i = 0; i < attributes_.size(); i++) {
         size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(4, attributes_.get(i));
+          .computeMessageSize(5, attributes_.get(i));
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(6, intType_);
       }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
@@ -1823,6 +3023,7 @@ public final class NormalizedNodeMessages {
       private void maybeForceBuilderInitialization() {
         if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
           getNodeTypeFieldBuilder();
+          getAttributeFieldBuilder();
           getAttributesFieldBuilder();
         }
       }
@@ -1842,12 +3043,20 @@ public final class NormalizedNodeMessages {
           nodeTypeBuilder_.clear();
         }
         bitField0_ = (bitField0_ & ~0x00000004);
+        if (attributeBuilder_ == null) {
+          attribute_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000008);
+        } else {
+          attributeBuilder_.clear();
+        }
         if (attributesBuilder_ == null) {
           attributes_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000008);
+          bitField0_ = (bitField0_ & ~0x00000010);
         } else {
           attributesBuilder_.clear();
         }
+        intType_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000020);
         return this;
       }
 
@@ -1892,15 +3101,28 @@ public final class NormalizedNodeMessages {
         } else {
           result.nodeType_ = nodeTypeBuilder_.build();
         }
-        if (attributesBuilder_ == null) {
+        if (attributeBuilder_ == null) {
           if (((bitField0_ & 0x00000008) == 0x00000008)) {
-            attributes_ = java.util.Collections.unmodifiableList(attributes_);
+            attribute_ = java.util.Collections.unmodifiableList(attribute_);
             bitField0_ = (bitField0_ & ~0x00000008);
           }
+          result.attribute_ = attribute_;
+        } else {
+          result.attribute_ = attributeBuilder_.build();
+        }
+        if (attributesBuilder_ == null) {
+          if (((bitField0_ & 0x00000010) == 0x00000010)) {
+            attributes_ = java.util.Collections.unmodifiableList(attributes_);
+            bitField0_ = (bitField0_ & ~0x00000010);
+          }
           result.attributes_ = attributes_;
         } else {
           result.attributes_ = attributesBuilder_.build();
         }
+        if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
+          to_bitField0_ |= 0x00000008;
+        }
+        result.intType_ = intType_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
@@ -1930,11 +3152,37 @@ public final class NormalizedNodeMessages {
         if (other.hasNodeType()) {
           mergeNodeType(other.getNodeType());
         }
+        if (attributeBuilder_ == null) {
+          if (!other.attribute_.isEmpty()) {
+            if (attribute_.isEmpty()) {
+              attribute_ = other.attribute_;
+              bitField0_ = (bitField0_ & ~0x00000008);
+            } else {
+              ensureAttributeIsMutable();
+              attribute_.addAll(other.attribute_);
+            }
+            onChanged();
+          }
+        } else {
+          if (!other.attribute_.isEmpty()) {
+            if (attributeBuilder_.isEmpty()) {
+              attributeBuilder_.dispose();
+              attributeBuilder_ = null;
+              attribute_ = other.attribute_;
+              bitField0_ = (bitField0_ & ~0x00000008);
+              attributeBuilder_ =
+                com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
+                   getAttributeFieldBuilder() : null;
+            } else {
+              attributeBuilder_.addAllMessages(other.attribute_);
+            }
+          }
+        }
         if (attributesBuilder_ == null) {
           if (!other.attributes_.isEmpty()) {
             if (attributes_.isEmpty()) {
               attributes_ = other.attributes_;
-              bitField0_ = (bitField0_ & ~0x00000008);
+              bitField0_ = (bitField0_ & ~0x00000010);
             } else {
               ensureAttributesIsMutable();
               attributes_.addAll(other.attributes_);
@@ -1947,7 +3195,7 @@ public final class NormalizedNodeMessages {
               attributesBuilder_.dispose();
               attributesBuilder_ = null;
               attributes_ = other.attributes_;
-              bitField0_ = (bitField0_ & ~0x00000008);
+              bitField0_ = (bitField0_ & ~0x00000010);
               attributesBuilder_ =
                 com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
                    getAttributesFieldBuilder() : null;
@@ -1956,21 +3204,14 @@ public final class NormalizedNodeMessages {
             }
           }
         }
+        if (other.hasIntType()) {
+          setIntType(other.getIntType());
+        }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
 
       public final boolean isInitialized() {
-        if (!hasValue()) {
-
-          return false;
-        }
-        if (hasNodeType()) {
-          if (!getNodeType().isInitialized()) {
-
-            return false;
-          }
-        }
         for (int i = 0; i < getAttributesCount(); i++) {
           if (!getAttributes(i).isInitialized()) {
 
@@ -1999,16 +3240,24 @@ public final class NormalizedNodeMessages {
       }
       private int bitField0_;
 
-      // required string value = 1;
+      // optional string value = 1;
       private java.lang.Object value_ = "";
       /**
-       * <code>required string value = 1;</code>
+       * <code>optional string value = 1;</code>
+       *
+       * <pre>
+       * @deprecated
+       * </pre>
        */
       public boolean hasValue() {
         return ((bitField0_ & 0x00000001) == 0x00000001);
       }
       /**
-       * <code>required string value = 1;</code>
+       * <code>optional string value = 1;</code>
+       *
+       * <pre>
+       * @deprecated
+       * </pre>
        */
       public java.lang.String getValue() {
         java.lang.Object ref = value_;
@@ -2022,7 +3271,11 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>required string value = 1;</code>
+       * <code>optional string value = 1;</code>
+       *
+       * <pre>
+       * @deprecated
+       * </pre>
        */
       public com.google.protobuf.ByteString
           getValueBytes() {
@@ -2038,7 +3291,11 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>required string value = 1;</code>
+       * <code>optional string value = 1;</code>
+       *
+       * <pre>
+       * @deprecated
+       * </pre>
        */
       public Builder setValue(
           java.lang.String value) {
@@ -2051,7 +3308,11 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>required string value = 1;</code>
+       * <code>optional string value = 1;</code>
+       *
+       * <pre>
+       * @deprecated
+       * </pre>
        */
       public Builder clearValue() {
         bitField0_ = (bitField0_ & ~0x00000001);
@@ -2060,7 +3321,11 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>required string value = 1;</code>
+       * <code>optional string value = 1;</code>
+       *
+       * <pre>
+       * @deprecated
+       * </pre>
        */
       public Builder setValueBytes(
           com.google.protobuf.ByteString value) {
@@ -2079,7 +3344,7 @@ public final class NormalizedNodeMessages {
        * <code>optional string type = 2;</code>
        *
        * <pre>
-       *NodeIdentifier, NodeWithValue, NodeIdentifierWithPredicates
+       * @deprecated
        * </pre>
        */
       public boolean hasType() {
@@ -2089,7 +3354,7 @@ public final class NormalizedNodeMessages {
        * <code>optional string type = 2;</code>
        *
        * <pre>
-       *NodeIdentifier, NodeWithValue, NodeIdentifierWithPredicates
+       * @deprecated
        * </pre>
        */
       public java.lang.String getType() {
@@ -2107,7 +3372,7 @@ public final class NormalizedNodeMessages {
        * <code>optional string type = 2;</code>
        *
        * <pre>
-       *NodeIdentifier, NodeWithValue, NodeIdentifierWithPredicates
+       * @deprecated
        * </pre>
        */
       public com.google.protobuf.ByteString
@@ -2127,7 +3392,7 @@ public final class NormalizedNodeMessages {
        * <code>optional string type = 2;</code>
        *
        * <pre>
-       *NodeIdentifier, NodeWithValue, NodeIdentifierWithPredicates
+       * @deprecated
        * </pre>
        */
       public Builder setType(
@@ -2144,7 +3409,7 @@ public final class NormalizedNodeMessages {
        * <code>optional string type = 2;</code>
        *
        * <pre>
-       *NodeIdentifier, NodeWithValue, NodeIdentifierWithPredicates
+       * @deprecated
        * </pre>
        */
       public Builder clearType() {
@@ -2157,7 +3422,7 @@ public final class NormalizedNodeMessages {
        * <code>optional string type = 2;</code>
        *
        * <pre>
-       *NodeIdentifier, NodeWithValue, NodeIdentifierWithPredicates
+       * @deprecated
        * </pre>
        */
       public Builder setTypeBytes(
@@ -2216,85 +3481,325 @@ public final class NormalizedNodeMessages {
           nodeType_ = builderForValue.build();
           onChanged();
         } else {
-          nodeTypeBuilder_.setMessage(builderForValue.build());
+          nodeTypeBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00000004;
+        return this;
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.QName nodeType = 3;</code>
+       */
+      public Builder mergeNodeType(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName value) {
+        if (nodeTypeBuilder_ == null) {
+          if (((bitField0_ & 0x00000004) == 0x00000004) &&
+              nodeType_ != org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.getDefaultInstance()) {
+            nodeType_ =
+              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.newBuilder(nodeType_).mergeFrom(value).buildPartial();
+          } else {
+            nodeType_ = value;
+          }
+          onChanged();
+        } else {
+          nodeTypeBuilder_.mergeFrom(value);
+        }
+        bitField0_ |= 0x00000004;
+        return this;
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.QName nodeType = 3;</code>
+       */
+      public Builder clearNodeType() {
+        if (nodeTypeBuilder_ == null) {
+          nodeType_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.getDefaultInstance();
+          onChanged();
+        } else {
+          nodeTypeBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000004);
+        return this;
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.QName nodeType = 3;</code>
+       */
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.Builder getNodeTypeBuilder() {
+        bitField0_ |= 0x00000004;
+        onChanged();
+        return getNodeTypeFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.QName nodeType = 3;</code>
+       */
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder getNodeTypeOrBuilder() {
+        if (nodeTypeBuilder_ != null) {
+          return nodeTypeBuilder_.getMessageOrBuilder();
+        } else {
+          return nodeType_;
+        }
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.QName nodeType = 3;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilder<
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder>
+          getNodeTypeFieldBuilder() {
+        if (nodeTypeBuilder_ == null) {
+          nodeTypeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder>(
+                  nodeType_,
+                  getParentForChildren(),
+                  isClean());
+          nodeType_ = null;
+        }
+        return nodeTypeBuilder_;
+      }
+
+      // repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;
+      private java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute> attribute_ =
+        java.util.Collections.emptyList();
+      private void ensureAttributeIsMutable() {
+        if (!((bitField0_ & 0x00000008) == 0x00000008)) {
+          attribute_ = new java.util.ArrayList<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute>(attribute_);
+          bitField0_ |= 0x00000008;
+         }
+      }
+
+      private com.google.protobuf.RepeatedFieldBuilder<
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttributeOrBuilder> attributeBuilder_;
+
+      /**
+       * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+       */
+      public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute> getAttributeList() {
+        if (attributeBuilder_ == null) {
+          return java.util.Collections.unmodifiableList(attribute_);
+        } else {
+          return attributeBuilder_.getMessageList();
+        }
+      }
+      /**
+       * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+       */
+      public int getAttributeCount() {
+        if (attributeBuilder_ == null) {
+          return attribute_.size();
+        } else {
+          return attributeBuilder_.getCount();
+        }
+      }
+      /**
+       * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+       */
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute getAttribute(int index) {
+        if (attributeBuilder_ == null) {
+          return attribute_.get(index);
+        } else {
+          return attributeBuilder_.getMessage(index);
+        }
+      }
+      /**
+       * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+       */
+      public Builder setAttribute(
+          int index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute value) {
+        if (attributeBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureAttributeIsMutable();
+          attribute_.set(index, value);
+          onChanged();
+        } else {
+          attributeBuilder_.setMessage(index, value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+       */
+      public Builder setAttribute(
+          int index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.Builder builderForValue) {
+        if (attributeBuilder_ == null) {
+          ensureAttributeIsMutable();
+          attribute_.set(index, builderForValue.build());
+          onChanged();
+        } else {
+          attributeBuilder_.setMessage(index, builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+       */
+      public Builder addAttribute(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute value) {
+        if (attributeBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureAttributeIsMutable();
+          attribute_.add(value);
+          onChanged();
+        } else {
+          attributeBuilder_.addMessage(value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+       */
+      public Builder addAttribute(
+          int index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute value) {
+        if (attributeBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureAttributeIsMutable();
+          attribute_.add(index, value);
+          onChanged();
+        } else {
+          attributeBuilder_.addMessage(index, value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+       */
+      public Builder addAttribute(
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.Builder builderForValue) {
+        if (attributeBuilder_ == null) {
+          ensureAttributeIsMutable();
+          attribute_.add(builderForValue.build());
+          onChanged();
+        } else {
+          attributeBuilder_.addMessage(builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+       */
+      public Builder addAttribute(
+          int index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.Builder builderForValue) {
+        if (attributeBuilder_ == null) {
+          ensureAttributeIsMutable();
+          attribute_.add(index, builderForValue.build());
+          onChanged();
+        } else {
+          attributeBuilder_.addMessage(index, builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+       */
+      public Builder addAllAttribute(
+          java.lang.Iterable<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute> values) {
+        if (attributeBuilder_ == null) {
+          ensureAttributeIsMutable();
+          super.addAll(values, attribute_);
+          onChanged();
+        } else {
+          attributeBuilder_.addAllMessages(values);
         }
-        bitField0_ |= 0x00000004;
         return this;
       }
       /**
-       * <code>optional .org.opendaylight.controller.mdsal.QName nodeType = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
        */
-      public Builder mergeNodeType(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName value) {
-        if (nodeTypeBuilder_ == null) {
-          if (((bitField0_ & 0x00000004) == 0x00000004) &&
-              nodeType_ != org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.getDefaultInstance()) {
-            nodeType_ =
-              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.newBuilder(nodeType_).mergeFrom(value).buildPartial();
-          } else {
-            nodeType_ = value;
-          }
+      public Builder clearAttribute() {
+        if (attributeBuilder_ == null) {
+          attribute_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000008);
           onChanged();
         } else {
-          nodeTypeBuilder_.mergeFrom(value);
+          attributeBuilder_.clear();
         }
-        bitField0_ |= 0x00000004;
         return this;
       }
       /**
-       * <code>optional .org.opendaylight.controller.mdsal.QName nodeType = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
        */
-      public Builder clearNodeType() {
-        if (nodeTypeBuilder_ == null) {
-          nodeType_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.getDefaultInstance();
+      public Builder removeAttribute(int index) {
+        if (attributeBuilder_ == null) {
+          ensureAttributeIsMutable();
+          attribute_.remove(index);
           onChanged();
         } else {
-          nodeTypeBuilder_.clear();
+          attributeBuilder_.remove(index);
         }
-        bitField0_ = (bitField0_ & ~0x00000004);
         return this;
       }
       /**
-       * <code>optional .org.opendaylight.controller.mdsal.QName nodeType = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
        */
-      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.Builder getNodeTypeBuilder() {
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return getNodeTypeFieldBuilder().getBuilder();
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.Builder getAttributeBuilder(
+          int index) {
+        return getAttributeFieldBuilder().getBuilder(index);
       }
       /**
-       * <code>optional .org.opendaylight.controller.mdsal.QName nodeType = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
        */
-      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder getNodeTypeOrBuilder() {
-        if (nodeTypeBuilder_ != null) {
-          return nodeTypeBuilder_.getMessageOrBuilder();
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttributeOrBuilder getAttributeOrBuilder(
+          int index) {
+        if (attributeBuilder_ == null) {
+          return attribute_.get(index);  } else {
+          return attributeBuilder_.getMessageOrBuilder(index);
+        }
+      }
+      /**
+       * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+       */
+      public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttributeOrBuilder>
+           getAttributeOrBuilderList() {
+        if (attributeBuilder_ != null) {
+          return attributeBuilder_.getMessageOrBuilderList();
         } else {
-          return nodeType_;
+          return java.util.Collections.unmodifiableList(attribute_);
         }
       }
       /**
-       * <code>optional .org.opendaylight.controller.mdsal.QName nodeType = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
        */
-      private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder>
-          getNodeTypeFieldBuilder() {
-        if (nodeTypeBuilder_ == null) {
-          nodeTypeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
-              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder>(
-                  nodeType_,
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.Builder addAttributeBuilder() {
+        return getAttributeFieldBuilder().addBuilder(
+            org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+       */
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.Builder addAttributeBuilder(
+          int index) {
+        return getAttributeFieldBuilder().addBuilder(
+            index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .org.opendaylight.controller.mdsal.PathArgumentAttribute attribute = 4;</code>
+       */
+      public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.Builder>
+           getAttributeBuilderList() {
+        return getAttributeFieldBuilder().getBuilderList();
+      }
+      private com.google.protobuf.RepeatedFieldBuilder<
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttributeOrBuilder>
+          getAttributeFieldBuilder() {
+        if (attributeBuilder_ == null) {
+          attributeBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
+              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttribute.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentAttributeOrBuilder>(
+                  attribute_,
+                  ((bitField0_ & 0x00000008) == 0x00000008),
                   getParentForChildren(),
                   isClean());
-          nodeType_ = null;
+          attribute_ = null;
         }
-        return nodeTypeBuilder_;
+        return attributeBuilder_;
       }
 
-      // repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;
+      // repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;
       private java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute> attributes_ =
         java.util.Collections.emptyList();
       private void ensureAttributesIsMutable() {
-        if (!((bitField0_ & 0x00000008) == 0x00000008)) {
+        if (!((bitField0_ & 0x00000010) == 0x00000010)) {
           attributes_ = new java.util.ArrayList<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute>(attributes_);
-          bitField0_ |= 0x00000008;
+          bitField0_ |= 0x00000010;
          }
       }
 
@@ -2302,7 +3807,11 @@ public final class NormalizedNodeMessages {
           org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder> attributesBuilder_;
 
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+       *
+       * <pre>
+       * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+       * </pre>
        */
       public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute> getAttributesList() {
         if (attributesBuilder_ == null) {
@@ -2312,7 +3821,11 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+       *
+       * <pre>
+       * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+       * </pre>
        */
       public int getAttributesCount() {
         if (attributesBuilder_ == null) {
@@ -2322,7 +3835,11 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+       *
+       * <pre>
+       * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+       * </pre>
        */
       public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute getAttributes(int index) {
         if (attributesBuilder_ == null) {
@@ -2332,7 +3849,11 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+       *
+       * <pre>
+       * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+       * </pre>
        */
       public Builder setAttributes(
           int index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute value) {
@@ -2349,7 +3870,11 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+       *
+       * <pre>
+       * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+       * </pre>
        */
       public Builder setAttributes(
           int index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder builderForValue) {
@@ -2363,7 +3888,11 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+       *
+       * <pre>
+       * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+       * </pre>
        */
       public Builder addAttributes(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute value) {
         if (attributesBuilder_ == null) {
@@ -2379,7 +3908,11 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+       *
+       * <pre>
+       * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+       * </pre>
        */
       public Builder addAttributes(
           int index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute value) {
@@ -2396,7 +3929,11 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+       *
+       * <pre>
+       * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+       * </pre>
        */
       public Builder addAttributes(
           org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder builderForValue) {
@@ -2410,7 +3947,11 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+       *
+       * <pre>
+       * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+       * </pre>
        */
       public Builder addAttributes(
           int index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder builderForValue) {
@@ -2424,7 +3965,11 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+       *
+       * <pre>
+       * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+       * </pre>
        */
       public Builder addAllAttributes(
           java.lang.Iterable<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute> values) {
@@ -2438,12 +3983,16 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+       *
+       * <pre>
+       * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+       * </pre>
        */
       public Builder clearAttributes() {
         if (attributesBuilder_ == null) {
           attributes_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000008);
+          bitField0_ = (bitField0_ & ~0x00000010);
           onChanged();
         } else {
           attributesBuilder_.clear();
@@ -2451,7 +4000,11 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+       *
+       * <pre>
+       * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+       * </pre>
        */
       public Builder removeAttributes(int index) {
         if (attributesBuilder_ == null) {
@@ -2464,14 +4017,22 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+       *
+       * <pre>
+       * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+       * </pre>
        */
       public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder getAttributesBuilder(
           int index) {
         return getAttributesFieldBuilder().getBuilder(index);
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+       *
+       * <pre>
+       * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+       * </pre>
        */
       public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder getAttributesOrBuilder(
           int index) {
@@ -2481,7 +4042,11 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+       *
+       * <pre>
+       * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+       * </pre>
        */
       public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
            getAttributesOrBuilderList() {
@@ -2492,14 +4057,22 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+       *
+       * <pre>
+       * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+       * </pre>
        */
       public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder addAttributesBuilder() {
         return getAttributesFieldBuilder().addBuilder(
             org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.getDefaultInstance());
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+       *
+       * <pre>
+       * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+       * </pre>
        */
       public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder addAttributesBuilder(
           int index) {
@@ -2507,7 +4080,11 @@ public final class NormalizedNodeMessages {
             index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.getDefaultInstance());
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
+       *
+       * <pre>
+       * @deprecated For backward compatibility (see InstanceIdentifierUtils)
+       * </pre>
        */
       public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder>
            getAttributesBuilderList() {
@@ -2520,7 +4097,7 @@ public final class NormalizedNodeMessages {
           attributesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
               org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>(
                   attributes_,
-                  ((bitField0_ & 0x00000008) == 0x00000008),
+                  ((bitField0_ & 0x00000010) == 0x00000010),
                   getParentForChildren(),
                   isClean());
           attributes_ = null;
@@ -2528,6 +4105,39 @@ public final class NormalizedNodeMessages {
         return attributesBuilder_;
       }
 
+      // optional int32 intType = 6;
+      private int intType_ ;
+      /**
+       * <code>optional int32 intType = 6;</code>
+       */
+      public boolean hasIntType() {
+        return ((bitField0_ & 0x00000020) == 0x00000020);
+      }
+      /**
+       * <code>optional int32 intType = 6;</code>
+       */
+      public int getIntType() {
+        return intType_;
+      }
+      /**
+       * <code>optional int32 intType = 6;</code>
+       */
+      public Builder setIntType(int value) {
+        bitField0_ |= 0x00000020;
+        intType_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int32 intType = 6;</code>
+       */
+      public Builder clearIntType() {
+        bitField0_ = (bitField0_ & ~0x00000020);
+        intType_ = 0;
+        onChanged();
+        return this;
+      }
+
       // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.PathArgument)
     }
 
@@ -3231,14 +4841,26 @@ public final class NormalizedNodeMessages {
     // optional string path = 1;
     /**
      * <code>optional string path = 1;</code>
+     *
+     * <pre>
+     * @deprecated(use pathArgument)
+     * </pre>
      */
     boolean hasPath();
     /**
      * <code>optional string path = 1;</code>
+     *
+     * <pre>
+     * @deprecated(use pathArgument)
+     * </pre>
      */
     java.lang.String getPath();
     /**
      * <code>optional string path = 1;</code>
+     *
+     * <pre>
+     * @deprecated(use pathArgument)
+     * </pre>
      */
     com.google.protobuf.ByteString
         getPathBytes();
@@ -3246,131 +4868,261 @@ public final class NormalizedNodeMessages {
     // optional string type = 2;
     /**
      * <code>optional string type = 2;</code>
+     *
+     * <pre>
+     * @deprecated(use intType)
+     * </pre>
      */
     boolean hasType();
     /**
      * <code>optional string type = 2;</code>
+     *
+     * <pre>
+     * @deprecated(use intType)
+     * </pre>
      */
     java.lang.String getType();
     /**
      * <code>optional string type = 2;</code>
+     *
+     * <pre>
+     * @deprecated(use intType)
+     * </pre>
      */
     com.google.protobuf.ByteString
         getTypeBytes();
 
-    // repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;
+    // optional .org.opendaylight.controller.mdsal.PathArgument pathArgument = 3;
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.PathArgument pathArgument = 3;</code>
+     */
+    boolean hasPathArgument();
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.PathArgument pathArgument = 3;</code>
+     */
+    org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument getPathArgument();
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.PathArgument pathArgument = 3;</code>
+     */
+    org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder getPathArgumentOrBuilder();
+
+    // optional int32 intType = 4;
+    /**
+     * <code>optional int32 intType = 4;</code>
+     */
+    boolean hasIntType();
+    /**
+     * <code>optional int32 intType = 4;</code>
+     */
+    int getIntType();
+
+    // repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
      */
     java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute>
         getAttributesList();
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
      */
     org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute getAttributes(int index);
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
      */
     int getAttributesCount();
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
      */
     java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
         getAttributesOrBuilderList();
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
      */
     org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder getAttributesOrBuilder(
         int index);
 
-    // repeated .org.opendaylight.controller.mdsal.Node child = 4;
+    // repeated .org.opendaylight.controller.mdsal.Node child = 6;
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
      */
     java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node>
         getChildList();
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
      */
     org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node getChild(int index);
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
      */
     int getChildCount();
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
      */
     java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
         getChildOrBuilderList();
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
      */
     org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder getChildOrBuilder(
         int index);
 
-    // optional string value = 5;
+    // optional string value = 7;
     /**
-     * <code>optional string value = 5;</code>
+     * <code>optional string value = 7;</code>
      */
     boolean hasValue();
     /**
-     * <code>optional string value = 5;</code>
+     * <code>optional string value = 7;</code>
      */
     java.lang.String getValue();
     /**
-     * <code>optional string value = 5;</code>
+     * <code>optional string value = 7;</code>
      */
     com.google.protobuf.ByteString
         getValueBytes();
 
-    // optional string valueType = 6;
+    // optional string valueType = 8;
     /**
-     * <code>optional string valueType = 6;</code>
+     * <code>optional string valueType = 8;</code>
+     *
+     * <pre>
+     * @deprecated(use intValueType)
+     * </pre>
      */
     boolean hasValueType();
     /**
-     * <code>optional string valueType = 6;</code>
+     * <code>optional string valueType = 8;</code>
+     *
+     * <pre>
+     * @deprecated(use intValueType)
+     * </pre>
      */
     java.lang.String getValueType();
     /**
-     * <code>optional string valueType = 6;</code>
+     * <code>optional string valueType = 8;</code>
+     *
+     * <pre>
+     * @deprecated(use intValueType)
+     * </pre>
      */
     com.google.protobuf.ByteString
         getValueTypeBytes();
 
-    // repeated string bitsValue = 7;
+    // optional int32 intValueType = 9;
+    /**
+     * <code>optional int32 intValueType = 9;</code>
+     *
+     * <pre>
+     * instead of valueType
+     * </pre>
+     */
+    boolean hasIntValueType();
+    /**
+     * <code>optional int32 intValueType = 9;</code>
+     *
+     * <pre>
+     * instead of valueType
+     * </pre>
+     */
+    int getIntValueType();
+
+    // optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 10;
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 10;</code>
+     *
+     * <pre>
+     * Specific values
+     * </pre>
+     */
+    boolean hasInstanceIdentifierValue();
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 10;</code>
+     *
+     * <pre>
+     * Specific values
+     * </pre>
+     */
+    org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier getInstanceIdentifierValue();
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 10;</code>
+     *
+     * <pre>
+     * Specific values
+     * </pre>
+     */
+    org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder getInstanceIdentifierValueOrBuilder();
+
+    // repeated string bitsValue = 11;
     /**
-     * <code>repeated string bitsValue = 7;</code>
+     * <code>repeated string bitsValue = 11;</code>
+     *
+     * <pre>
+     * intValueType = Bits
+     * </pre>
      */
     java.util.List<java.lang.String>
     getBitsValueList();
     /**
-     * <code>repeated string bitsValue = 7;</code>
+     * <code>repeated string bitsValue = 11;</code>
+     *
+     * <pre>
+     * intValueType = Bits
+     * </pre>
      */
     int getBitsValueCount();
     /**
-     * <code>repeated string bitsValue = 7;</code>
+     * <code>repeated string bitsValue = 11;</code>
+     *
+     * <pre>
+     * intValueType = Bits
+     * </pre>
      */
     java.lang.String getBitsValue(int index);
     /**
-     * <code>repeated string bitsValue = 7;</code>
+     * <code>repeated string bitsValue = 11;</code>
+     *
+     * <pre>
+     * intValueType = Bits
+     * </pre>
      */
     com.google.protobuf.ByteString
         getBitsValueBytes(int index);
 
-    // optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;
+    // repeated string code = 12;
     /**
-     * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;</code>
+     * <code>repeated string code = 12;</code>
+     *
+     * <pre>
+     * A list of string codes which can be used for any repeated strings in the NormalizedNode
+     * </pre>
      */
-    boolean hasInstanceIdentifierValue();
+    java.util.List<java.lang.String>
+    getCodeList();
     /**
-     * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;</code>
+     * <code>repeated string code = 12;</code>
+     *
+     * <pre>
+     * A list of string codes which can be used for any repeated strings in the NormalizedNode
+     * </pre>
      */
-    org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier getInstanceIdentifierValue();
+    int getCodeCount();
     /**
-     * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;</code>
+     * <code>repeated string code = 12;</code>
+     *
+     * <pre>
+     * A list of string codes which can be used for any repeated strings in the NormalizedNode
+     * </pre>
      */
-    org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder getInstanceIdentifierValueOrBuilder();
+    java.lang.String getCode(int index);
+    /**
+     * <code>repeated string code = 12;</code>
+     *
+     * <pre>
+     * A list of string codes which can be used for any repeated strings in the NormalizedNode
+     * </pre>
+     */
+    com.google.protobuf.ByteString
+        getCodeBytes(int index);
   }
   /**
    * Protobuf type {@code org.opendaylight.controller.mdsal.Node}
@@ -3434,42 +5186,57 @@ public final class NormalizedNodeMessages {
               break;
             }
             case 26: {
-              if (!((mutable_bitField0_ & 0x00000004) == 0x00000004)) {
+              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.Builder subBuilder = null;
+              if (((bitField0_ & 0x00000004) == 0x00000004)) {
+                subBuilder = pathArgument_.toBuilder();
+              }
+              pathArgument_ = input.readMessage(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.PARSER, extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(pathArgument_);
+                pathArgument_ = subBuilder.buildPartial();
+              }
+              bitField0_ |= 0x00000004;
+              break;
+            }
+            case 32: {
+              bitField0_ |= 0x00000008;
+              intType_ = input.readInt32();
+              break;
+            }
+            case 42: {
+              if (!((mutable_bitField0_ & 0x00000010) == 0x00000010)) {
                 attributes_ = new java.util.ArrayList<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute>();
-                mutable_bitField0_ |= 0x00000004;
+                mutable_bitField0_ |= 0x00000010;
               }
               attributes_.add(input.readMessage(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.PARSER, extensionRegistry));
               break;
             }
-            case 34: {
-              if (!((mutable_bitField0_ & 0x00000008) == 0x00000008)) {
+            case 50: {
+              if (!((mutable_bitField0_ & 0x00000020) == 0x00000020)) {
                 child_ = new java.util.ArrayList<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node>();
-                mutable_bitField0_ |= 0x00000008;
+                mutable_bitField0_ |= 0x00000020;
               }
               child_.add(input.readMessage(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.PARSER, extensionRegistry));
               break;
             }
-            case 42: {
-              bitField0_ |= 0x00000004;
+            case 58: {
+              bitField0_ |= 0x00000010;
               value_ = input.readBytes();
               break;
             }
-            case 50: {
-              bitField0_ |= 0x00000008;
+            case 66: {
+              bitField0_ |= 0x00000020;
               valueType_ = input.readBytes();
               break;
             }
-            case 58: {
-              if (!((mutable_bitField0_ & 0x00000040) == 0x00000040)) {
-                bitsValue_ = new com.google.protobuf.LazyStringArrayList();
-                mutable_bitField0_ |= 0x00000040;
-              }
-              bitsValue_.add(input.readBytes());
+            case 72: {
+              bitField0_ |= 0x00000040;
+              intValueType_ = input.readInt32();
               break;
             }
-            case 66: {
+            case 82: {
               org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder subBuilder = null;
-              if (((bitField0_ & 0x00000010) == 0x00000010)) {
+              if (((bitField0_ & 0x00000080) == 0x00000080)) {
                 subBuilder = instanceIdentifierValue_.toBuilder();
               }
               instanceIdentifierValue_ = input.readMessage(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.PARSER, extensionRegistry);
@@ -3477,7 +5244,23 @@ public final class NormalizedNodeMessages {
                 subBuilder.mergeFrom(instanceIdentifierValue_);
                 instanceIdentifierValue_ = subBuilder.buildPartial();
               }
-              bitField0_ |= 0x00000010;
+              bitField0_ |= 0x00000080;
+              break;
+            }
+            case 90: {
+              if (!((mutable_bitField0_ & 0x00000400) == 0x00000400)) {
+                bitsValue_ = new com.google.protobuf.LazyStringArrayList();
+                mutable_bitField0_ |= 0x00000400;
+              }
+              bitsValue_.add(input.readBytes());
+              break;
+            }
+            case 98: {
+              if (!((mutable_bitField0_ & 0x00000800) == 0x00000800)) {
+                code_ = new com.google.protobuf.LazyStringArrayList();
+                mutable_bitField0_ |= 0x00000800;
+              }
+              code_.add(input.readBytes());
               break;
             }
           }
@@ -3488,15 +5271,18 @@ public final class NormalizedNodeMessages {
         throw new com.google.protobuf.InvalidProtocolBufferException(
             e.getMessage()).setUnfinishedMessage(this);
       } finally {
-        if (((mutable_bitField0_ & 0x00000004) == 0x00000004)) {
+        if (((mutable_bitField0_ & 0x00000010) == 0x00000010)) {
           attributes_ = java.util.Collections.unmodifiableList(attributes_);
         }
-        if (((mutable_bitField0_ & 0x00000008) == 0x00000008)) {
+        if (((mutable_bitField0_ & 0x00000020) == 0x00000020)) {
           child_ = java.util.Collections.unmodifiableList(child_);
         }
-        if (((mutable_bitField0_ & 0x00000040) == 0x00000040)) {
+        if (((mutable_bitField0_ & 0x00000400) == 0x00000400)) {
           bitsValue_ = new com.google.protobuf.UnmodifiableLazyStringList(bitsValue_);
         }
+        if (((mutable_bitField0_ & 0x00000800) == 0x00000800)) {
+          code_ = new com.google.protobuf.UnmodifiableLazyStringList(code_);
+        }
         this.unknownFields = unknownFields.build();
         makeExtensionsImmutable();
       }
@@ -3534,12 +5320,20 @@ public final class NormalizedNodeMessages {
     private java.lang.Object path_;
     /**
      * <code>optional string path = 1;</code>
+     *
+     * <pre>
+     * @deprecated(use pathArgument)
+     * </pre>
      */
     public boolean hasPath() {
       return ((bitField0_ & 0x00000001) == 0x00000001);
     }
     /**
      * <code>optional string path = 1;</code>
+     *
+     * <pre>
+     * @deprecated(use pathArgument)
+     * </pre>
      */
     public java.lang.String getPath() {
       java.lang.Object ref = path_;
@@ -3557,6 +5351,10 @@ public final class NormalizedNodeMessages {
     }
     /**
      * <code>optional string path = 1;</code>
+     *
+     * <pre>
+     * @deprecated(use pathArgument)
+     * </pre>
      */
     public com.google.protobuf.ByteString
         getPathBytes() {
@@ -3577,12 +5375,20 @@ public final class NormalizedNodeMessages {
     private java.lang.Object type_;
     /**
      * <code>optional string type = 2;</code>
+     *
+     * <pre>
+     * @deprecated(use intType)
+     * </pre>
      */
     public boolean hasType() {
       return ((bitField0_ & 0x00000002) == 0x00000002);
     }
     /**
      * <code>optional string type = 2;</code>
+     *
+     * <pre>
+     * @deprecated(use intType)
+     * </pre>
      */
     public java.lang.String getType() {
       java.lang.Object ref = type_;
@@ -3600,6 +5406,10 @@ public final class NormalizedNodeMessages {
     }
     /**
      * <code>optional string type = 2;</code>
+     *
+     * <pre>
+     * @deprecated(use intType)
+     * </pre>
      */
     public com.google.protobuf.ByteString
         getTypeBytes() {
@@ -3615,89 +5425,127 @@ public final class NormalizedNodeMessages {
       }
     }
 
-    // repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;
-    public static final int ATTRIBUTES_FIELD_NUMBER = 3;
+    // optional .org.opendaylight.controller.mdsal.PathArgument pathArgument = 3;
+    public static final int PATHARGUMENT_FIELD_NUMBER = 3;
+    private org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument pathArgument_;
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.PathArgument pathArgument = 3;</code>
+     */
+    public boolean hasPathArgument() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.PathArgument pathArgument = 3;</code>
+     */
+    public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument getPathArgument() {
+      return pathArgument_;
+    }
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.PathArgument pathArgument = 3;</code>
+     */
+    public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder getPathArgumentOrBuilder() {
+      return pathArgument_;
+    }
+
+    // optional int32 intType = 4;
+    public static final int INTTYPE_FIELD_NUMBER = 4;
+    private int intType_;
+    /**
+     * <code>optional int32 intType = 4;</code>
+     */
+    public boolean hasIntType() {
+      return ((bitField0_ & 0x00000008) == 0x00000008);
+    }
+    /**
+     * <code>optional int32 intType = 4;</code>
+     */
+    public int getIntType() {
+      return intType_;
+    }
+
+    // repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;
+    public static final int ATTRIBUTES_FIELD_NUMBER = 5;
     private java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute> attributes_;
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
      */
     public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute> getAttributesList() {
       return attributes_;
     }
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
      */
     public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
         getAttributesOrBuilderList() {
       return attributes_;
     }
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
      */
     public int getAttributesCount() {
       return attributes_.size();
     }
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
      */
     public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute getAttributes(int index) {
       return attributes_.get(index);
     }
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
      */
     public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder getAttributesOrBuilder(
         int index) {
       return attributes_.get(index);
     }
 
-    // repeated .org.opendaylight.controller.mdsal.Node child = 4;
-    public static final int CHILD_FIELD_NUMBER = 4;
+    // repeated .org.opendaylight.controller.mdsal.Node child = 6;
+    public static final int CHILD_FIELD_NUMBER = 6;
     private java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node> child_;
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
      */
     public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node> getChildList() {
       return child_;
     }
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
      */
     public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
         getChildOrBuilderList() {
       return child_;
     }
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
      */
     public int getChildCount() {
       return child_.size();
     }
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
      */
     public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node getChild(int index) {
       return child_.get(index);
     }
     /**
-     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+     * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
      */
     public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder getChildOrBuilder(
         int index) {
       return child_.get(index);
     }
 
-    // optional string value = 5;
-    public static final int VALUE_FIELD_NUMBER = 5;
+    // optional string value = 7;
+    public static final int VALUE_FIELD_NUMBER = 7;
     private java.lang.Object value_;
     /**
-     * <code>optional string value = 5;</code>
+     * <code>optional string value = 7;</code>
      */
     public boolean hasValue() {
-      return ((bitField0_ & 0x00000004) == 0x00000004);
+      return ((bitField0_ & 0x00000010) == 0x00000010);
     }
     /**
-     * <code>optional string value = 5;</code>
+     * <code>optional string value = 7;</code>
      */
     public java.lang.String getValue() {
       java.lang.Object ref = value_;
@@ -3714,7 +5562,7 @@ public final class NormalizedNodeMessages {
       }
     }
     /**
-     * <code>optional string value = 5;</code>
+     * <code>optional string value = 7;</code>
      */
     public com.google.protobuf.ByteString
         getValueBytes() {
@@ -3730,17 +5578,25 @@ public final class NormalizedNodeMessages {
       }
     }
 
-    // optional string valueType = 6;
-    public static final int VALUETYPE_FIELD_NUMBER = 6;
+    // optional string valueType = 8;
+    public static final int VALUETYPE_FIELD_NUMBER = 8;
     private java.lang.Object valueType_;
     /**
-     * <code>optional string valueType = 6;</code>
+     * <code>optional string valueType = 8;</code>
+     *
+     * <pre>
+     * @deprecated(use intValueType)
+     * </pre>
      */
     public boolean hasValueType() {
-      return ((bitField0_ & 0x00000008) == 0x00000008);
+      return ((bitField0_ & 0x00000020) == 0x00000020);
     }
     /**
-     * <code>optional string valueType = 6;</code>
+     * <code>optional string valueType = 8;</code>
+     *
+     * <pre>
+     * @deprecated(use intValueType)
+     * </pre>
      */
     public java.lang.String getValueType() {
       java.lang.Object ref = valueType_;
@@ -3757,7 +5613,11 @@ public final class NormalizedNodeMessages {
       }
     }
     /**
-     * <code>optional string valueType = 6;</code>
+     * <code>optional string valueType = 8;</code>
+     *
+     * <pre>
+     * @deprecated(use intValueType)
+     * </pre>
      */
     public com.google.protobuf.ByteString
         getValueTypeBytes() {
@@ -3773,73 +5633,181 @@ public final class NormalizedNodeMessages {
       }
     }
 
-    // repeated string bitsValue = 7;
-    public static final int BITSVALUE_FIELD_NUMBER = 7;
+    // optional int32 intValueType = 9;
+    public static final int INTVALUETYPE_FIELD_NUMBER = 9;
+    private int intValueType_;
+    /**
+     * <code>optional int32 intValueType = 9;</code>
+     *
+     * <pre>
+     * instead of valueType
+     * </pre>
+     */
+    public boolean hasIntValueType() {
+      return ((bitField0_ & 0x00000040) == 0x00000040);
+    }
+    /**
+     * <code>optional int32 intValueType = 9;</code>
+     *
+     * <pre>
+     * instead of valueType
+     * </pre>
+     */
+    public int getIntValueType() {
+      return intValueType_;
+    }
+
+    // optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 10;
+    public static final int INSTANCEIDENTIFIERVALUE_FIELD_NUMBER = 10;
+    private org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier instanceIdentifierValue_;
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 10;</code>
+     *
+     * <pre>
+     * Specific values
+     * </pre>
+     */
+    public boolean hasInstanceIdentifierValue() {
+      return ((bitField0_ & 0x00000080) == 0x00000080);
+    }
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 10;</code>
+     *
+     * <pre>
+     * Specific values
+     * </pre>
+     */
+    public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier getInstanceIdentifierValue() {
+      return instanceIdentifierValue_;
+    }
+    /**
+     * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 10;</code>
+     *
+     * <pre>
+     * Specific values
+     * </pre>
+     */
+    public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder getInstanceIdentifierValueOrBuilder() {
+      return instanceIdentifierValue_;
+    }
+
+    // repeated string bitsValue = 11;
+    public static final int BITSVALUE_FIELD_NUMBER = 11;
     private com.google.protobuf.LazyStringList bitsValue_;
     /**
-     * <code>repeated string bitsValue = 7;</code>
+     * <code>repeated string bitsValue = 11;</code>
+     *
+     * <pre>
+     * intValueType = Bits
+     * </pre>
      */
     public java.util.List<java.lang.String>
         getBitsValueList() {
       return bitsValue_;
     }
     /**
-     * <code>repeated string bitsValue = 7;</code>
+     * <code>repeated string bitsValue = 11;</code>
+     *
+     * <pre>
+     * intValueType = Bits
+     * </pre>
      */
     public int getBitsValueCount() {
       return bitsValue_.size();
     }
     /**
-     * <code>repeated string bitsValue = 7;</code>
+     * <code>repeated string bitsValue = 11;</code>
+     *
+     * <pre>
+     * intValueType = Bits
+     * </pre>
      */
     public java.lang.String getBitsValue(int index) {
       return bitsValue_.get(index);
     }
     /**
-     * <code>repeated string bitsValue = 7;</code>
+     * <code>repeated string bitsValue = 11;</code>
+     *
+     * <pre>
+     * intValueType = Bits
+     * </pre>
      */
     public com.google.protobuf.ByteString
         getBitsValueBytes(int index) {
       return bitsValue_.getByteString(index);
     }
 
-    // optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;
-    public static final int INSTANCEIDENTIFIERVALUE_FIELD_NUMBER = 8;
-    private org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier instanceIdentifierValue_;
+    // repeated string code = 12;
+    public static final int CODE_FIELD_NUMBER = 12;
+    private com.google.protobuf.LazyStringList code_;
     /**
-     * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;</code>
+     * <code>repeated string code = 12;</code>
+     *
+     * <pre>
+     * A list of string codes which can be used for any repeated strings in the NormalizedNode
+     * </pre>
      */
-    public boolean hasInstanceIdentifierValue() {
-      return ((bitField0_ & 0x00000010) == 0x00000010);
+    public java.util.List<java.lang.String>
+        getCodeList() {
+      return code_;
+    }
+    /**
+     * <code>repeated string code = 12;</code>
+     *
+     * <pre>
+     * A list of string codes which can be used for any repeated strings in the NormalizedNode
+     * </pre>
+     */
+    public int getCodeCount() {
+      return code_.size();
     }
     /**
-     * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;</code>
+     * <code>repeated string code = 12;</code>
+     *
+     * <pre>
+     * A list of string codes which can be used for any repeated strings in the NormalizedNode
+     * </pre>
      */
-    public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier getInstanceIdentifierValue() {
-      return instanceIdentifierValue_;
+    public java.lang.String getCode(int index) {
+      return code_.get(index);
     }
     /**
-     * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;</code>
+     * <code>repeated string code = 12;</code>
+     *
+     * <pre>
+     * A list of string codes which can be used for any repeated strings in the NormalizedNode
+     * </pre>
      */
-    public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder getInstanceIdentifierValueOrBuilder() {
-      return instanceIdentifierValue_;
+    public com.google.protobuf.ByteString
+        getCodeBytes(int index) {
+      return code_.getByteString(index);
     }
 
     private void initFields() {
       path_ = "";
       type_ = "";
+      pathArgument_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.getDefaultInstance();
+      intType_ = 0;
       attributes_ = java.util.Collections.emptyList();
       child_ = java.util.Collections.emptyList();
       value_ = "";
       valueType_ = "";
-      bitsValue_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+      intValueType_ = 0;
       instanceIdentifierValue_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.getDefaultInstance();
+      bitsValue_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+      code_ = com.google.protobuf.LazyStringArrayList.EMPTY;
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
       byte isInitialized = memoizedIsInitialized;
       if (isInitialized != -1) return isInitialized == 1;
 
+      if (hasPathArgument()) {
+        if (!getPathArgument().isInitialized()) {
+          memoizedIsInitialized = 0;
+          return false;
+        }
+      }
       for (int i = 0; i < getAttributesCount(); i++) {
         if (!getAttributes(i).isInitialized()) {
           memoizedIsInitialized = 0;
@@ -3871,23 +5839,35 @@ public final class NormalizedNodeMessages {
       if (((bitField0_ & 0x00000002) == 0x00000002)) {
         output.writeBytes(2, getTypeBytes());
       }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeMessage(3, pathArgument_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        output.writeInt32(4, intType_);
+      }
       for (int i = 0; i < attributes_.size(); i++) {
-        output.writeMessage(3, attributes_.get(i));
+        output.writeMessage(5, attributes_.get(i));
       }
       for (int i = 0; i < child_.size(); i++) {
-        output.writeMessage(4, child_.get(i));
+        output.writeMessage(6, child_.get(i));
       }
-      if (((bitField0_ & 0x00000004) == 0x00000004)) {
-        output.writeBytes(5, getValueBytes());
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        output.writeBytes(7, getValueBytes());
       }
-      if (((bitField0_ & 0x00000008) == 0x00000008)) {
-        output.writeBytes(6, getValueTypeBytes());
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        output.writeBytes(8, getValueTypeBytes());
+      }
+      if (((bitField0_ & 0x00000040) == 0x00000040)) {
+        output.writeInt32(9, intValueType_);
+      }
+      if (((bitField0_ & 0x00000080) == 0x00000080)) {
+        output.writeMessage(10, instanceIdentifierValue_);
       }
       for (int i = 0; i < bitsValue_.size(); i++) {
-        output.writeBytes(7, bitsValue_.getByteString(i));
+        output.writeBytes(11, bitsValue_.getByteString(i));
       }
-      if (((bitField0_ & 0x00000010) == 0x00000010)) {
-        output.writeMessage(8, instanceIdentifierValue_);
+      for (int i = 0; i < code_.size(); i++) {
+        output.writeBytes(12, code_.getByteString(i));
       }
       getUnknownFields().writeTo(output);
     }
@@ -3906,21 +5886,37 @@ public final class NormalizedNodeMessages {
         size += com.google.protobuf.CodedOutputStream
           .computeBytesSize(2, getTypeBytes());
       }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(3, pathArgument_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(4, intType_);
+      }
       for (int i = 0; i < attributes_.size(); i++) {
         size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(3, attributes_.get(i));
+          .computeMessageSize(5, attributes_.get(i));
       }
       for (int i = 0; i < child_.size(); i++) {
         size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(4, child_.get(i));
+          .computeMessageSize(6, child_.get(i));
       }
-      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
         size += com.google.protobuf.CodedOutputStream
-          .computeBytesSize(5, getValueBytes());
+          .computeBytesSize(7, getValueBytes());
       }
-      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
         size += com.google.protobuf.CodedOutputStream
-          .computeBytesSize(6, getValueTypeBytes());
+          .computeBytesSize(8, getValueTypeBytes());
+      }
+      if (((bitField0_ & 0x00000040) == 0x00000040)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(9, intValueType_);
+      }
+      if (((bitField0_ & 0x00000080) == 0x00000080)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(10, instanceIdentifierValue_);
       }
       {
         int dataSize = 0;
@@ -3931,9 +5927,14 @@ public final class NormalizedNodeMessages {
         size += dataSize;
         size += 1 * getBitsValueList().size();
       }
-      if (((bitField0_ & 0x00000010) == 0x00000010)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(8, instanceIdentifierValue_);
+      {
+        int dataSize = 0;
+        for (int i = 0; i < code_.size(); i++) {
+          dataSize += com.google.protobuf.CodedOutputStream
+            .computeBytesSizeNoTag(code_.getByteString(i));
+        }
+        size += dataSize;
+        size += 1 * getCodeList().size();
       }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
@@ -4043,6 +6044,7 @@ public final class NormalizedNodeMessages {
       }
       private void maybeForceBuilderInitialization() {
         if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+          getPathArgumentFieldBuilder();
           getAttributesFieldBuilder();
           getChildFieldBuilder();
           getInstanceIdentifierValueFieldBuilder();
@@ -4058,30 +6060,42 @@ public final class NormalizedNodeMessages {
         bitField0_ = (bitField0_ & ~0x00000001);
         type_ = "";
         bitField0_ = (bitField0_ & ~0x00000002);
+        if (pathArgumentBuilder_ == null) {
+          pathArgument_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.getDefaultInstance();
+        } else {
+          pathArgumentBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000004);
+        intType_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000008);
         if (attributesBuilder_ == null) {
           attributes_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000004);
+          bitField0_ = (bitField0_ & ~0x00000010);
         } else {
           attributesBuilder_.clear();
         }
         if (childBuilder_ == null) {
           child_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000008);
+          bitField0_ = (bitField0_ & ~0x00000020);
         } else {
           childBuilder_.clear();
         }
         value_ = "";
-        bitField0_ = (bitField0_ & ~0x00000010);
-        valueType_ = "";
-        bitField0_ = (bitField0_ & ~0x00000020);
-        bitsValue_ = com.google.protobuf.LazyStringArrayList.EMPTY;
         bitField0_ = (bitField0_ & ~0x00000040);
+        valueType_ = "";
+        bitField0_ = (bitField0_ & ~0x00000080);
+        intValueType_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000100);
         if (instanceIdentifierValueBuilder_ == null) {
           instanceIdentifierValue_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.getDefaultInstance();
         } else {
           instanceIdentifierValueBuilder_.clear();
         }
-        bitField0_ = (bitField0_ & ~0x00000080);
+        bitField0_ = (bitField0_ & ~0x00000200);
+        bitsValue_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000400);
+        code_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000800);
         return this;
       }
 
@@ -4118,46 +6132,68 @@ public final class NormalizedNodeMessages {
           to_bitField0_ |= 0x00000002;
         }
         result.type_ = type_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        if (pathArgumentBuilder_ == null) {
+          result.pathArgument_ = pathArgument_;
+        } else {
+          result.pathArgument_ = pathArgumentBuilder_.build();
+        }
+        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+          to_bitField0_ |= 0x00000008;
+        }
+        result.intType_ = intType_;
         if (attributesBuilder_ == null) {
-          if (((bitField0_ & 0x00000004) == 0x00000004)) {
+          if (((bitField0_ & 0x00000010) == 0x00000010)) {
             attributes_ = java.util.Collections.unmodifiableList(attributes_);
-            bitField0_ = (bitField0_ & ~0x00000004);
+            bitField0_ = (bitField0_ & ~0x00000010);
           }
           result.attributes_ = attributes_;
         } else {
           result.attributes_ = attributesBuilder_.build();
         }
         if (childBuilder_ == null) {
-          if (((bitField0_ & 0x00000008) == 0x00000008)) {
+          if (((bitField0_ & 0x00000020) == 0x00000020)) {
             child_ = java.util.Collections.unmodifiableList(child_);
-            bitField0_ = (bitField0_ & ~0x00000008);
+            bitField0_ = (bitField0_ & ~0x00000020);
           }
           result.child_ = child_;
         } else {
           result.child_ = childBuilder_.build();
         }
-        if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
-          to_bitField0_ |= 0x00000004;
+        if (((from_bitField0_ & 0x00000040) == 0x00000040)) {
+          to_bitField0_ |= 0x00000010;
         }
         result.value_ = value_;
-        if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
-          to_bitField0_ |= 0x00000008;
+        if (((from_bitField0_ & 0x00000080) == 0x00000080)) {
+          to_bitField0_ |= 0x00000020;
         }
         result.valueType_ = valueType_;
-        if (((bitField0_ & 0x00000040) == 0x00000040)) {
-          bitsValue_ = new com.google.protobuf.UnmodifiableLazyStringList(
-              bitsValue_);
-          bitField0_ = (bitField0_ & ~0x00000040);
+        if (((from_bitField0_ & 0x00000100) == 0x00000100)) {
+          to_bitField0_ |= 0x00000040;
         }
-        result.bitsValue_ = bitsValue_;
-        if (((from_bitField0_ & 0x00000080) == 0x00000080)) {
-          to_bitField0_ |= 0x00000010;
+        result.intValueType_ = intValueType_;
+        if (((from_bitField0_ & 0x00000200) == 0x00000200)) {
+          to_bitField0_ |= 0x00000080;
         }
         if (instanceIdentifierValueBuilder_ == null) {
           result.instanceIdentifierValue_ = instanceIdentifierValue_;
         } else {
           result.instanceIdentifierValue_ = instanceIdentifierValueBuilder_.build();
         }
+        if (((bitField0_ & 0x00000400) == 0x00000400)) {
+          bitsValue_ = new com.google.protobuf.UnmodifiableLazyStringList(
+              bitsValue_);
+          bitField0_ = (bitField0_ & ~0x00000400);
+        }
+        result.bitsValue_ = bitsValue_;
+        if (((bitField0_ & 0x00000800) == 0x00000800)) {
+          code_ = new com.google.protobuf.UnmodifiableLazyStringList(
+              code_);
+          bitField0_ = (bitField0_ & ~0x00000800);
+        }
+        result.code_ = code_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
@@ -4184,11 +6220,17 @@ public final class NormalizedNodeMessages {
           type_ = other.type_;
           onChanged();
         }
+        if (other.hasPathArgument()) {
+          mergePathArgument(other.getPathArgument());
+        }
+        if (other.hasIntType()) {
+          setIntType(other.getIntType());
+        }
         if (attributesBuilder_ == null) {
           if (!other.attributes_.isEmpty()) {
             if (attributes_.isEmpty()) {
               attributes_ = other.attributes_;
-              bitField0_ = (bitField0_ & ~0x00000004);
+              bitField0_ = (bitField0_ & ~0x00000010);
             } else {
               ensureAttributesIsMutable();
               attributes_.addAll(other.attributes_);
@@ -4201,7 +6243,7 @@ public final class NormalizedNodeMessages {
               attributesBuilder_.dispose();
               attributesBuilder_ = null;
               attributes_ = other.attributes_;
-              bitField0_ = (bitField0_ & ~0x00000004);
+              bitField0_ = (bitField0_ & ~0x00000010);
               attributesBuilder_ =
                 com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
                    getAttributesFieldBuilder() : null;
@@ -4214,7 +6256,7 @@ public final class NormalizedNodeMessages {
           if (!other.child_.isEmpty()) {
             if (child_.isEmpty()) {
               child_ = other.child_;
-              bitField0_ = (bitField0_ & ~0x00000008);
+              bitField0_ = (bitField0_ & ~0x00000020);
             } else {
               ensureChildIsMutable();
               child_.addAll(other.child_);
@@ -4227,7 +6269,7 @@ public final class NormalizedNodeMessages {
               childBuilder_.dispose();
               childBuilder_ = null;
               child_ = other.child_;
-              bitField0_ = (bitField0_ & ~0x00000008);
+              bitField0_ = (bitField0_ & ~0x00000020);
               childBuilder_ =
                 com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
                    getChildFieldBuilder() : null;
@@ -4237,33 +6279,52 @@ public final class NormalizedNodeMessages {
           }
         }
         if (other.hasValue()) {
-          bitField0_ |= 0x00000010;
+          bitField0_ |= 0x00000040;
           value_ = other.value_;
           onChanged();
         }
         if (other.hasValueType()) {
-          bitField0_ |= 0x00000020;
+          bitField0_ |= 0x00000080;
           valueType_ = other.valueType_;
           onChanged();
         }
+        if (other.hasIntValueType()) {
+          setIntValueType(other.getIntValueType());
+        }
+        if (other.hasInstanceIdentifierValue()) {
+          mergeInstanceIdentifierValue(other.getInstanceIdentifierValue());
+        }
         if (!other.bitsValue_.isEmpty()) {
           if (bitsValue_.isEmpty()) {
             bitsValue_ = other.bitsValue_;
-            bitField0_ = (bitField0_ & ~0x00000040);
+            bitField0_ = (bitField0_ & ~0x00000400);
           } else {
             ensureBitsValueIsMutable();
             bitsValue_.addAll(other.bitsValue_);
           }
           onChanged();
         }
-        if (other.hasInstanceIdentifierValue()) {
-          mergeInstanceIdentifierValue(other.getInstanceIdentifierValue());
+        if (!other.code_.isEmpty()) {
+          if (code_.isEmpty()) {
+            code_ = other.code_;
+            bitField0_ = (bitField0_ & ~0x00000800);
+          } else {
+            ensureCodeIsMutable();
+            code_.addAll(other.code_);
+          }
+          onChanged();
         }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
 
       public final boolean isInitialized() {
+        if (hasPathArgument()) {
+          if (!getPathArgument().isInitialized()) {
+
+            return false;
+          }
+        }
         for (int i = 0; i < getAttributesCount(); i++) {
           if (!getAttributes(i).isInitialized()) {
 
@@ -4308,12 +6369,20 @@ public final class NormalizedNodeMessages {
       private java.lang.Object path_ = "";
       /**
        * <code>optional string path = 1;</code>
+       *
+       * <pre>
+       * @deprecated(use pathArgument)
+       * </pre>
        */
       public boolean hasPath() {
         return ((bitField0_ & 0x00000001) == 0x00000001);
       }
       /**
        * <code>optional string path = 1;</code>
+       *
+       * <pre>
+       * @deprecated(use pathArgument)
+       * </pre>
        */
       public java.lang.String getPath() {
         java.lang.Object ref = path_;
@@ -4328,6 +6397,10 @@ public final class NormalizedNodeMessages {
       }
       /**
        * <code>optional string path = 1;</code>
+       *
+       * <pre>
+       * @deprecated(use pathArgument)
+       * </pre>
        */
       public com.google.protobuf.ByteString
           getPathBytes() {
@@ -4344,6 +6417,10 @@ public final class NormalizedNodeMessages {
       }
       /**
        * <code>optional string path = 1;</code>
+       *
+       * <pre>
+       * @deprecated(use pathArgument)
+       * </pre>
        */
       public Builder setPath(
           java.lang.String value) {
@@ -4357,6 +6434,10 @@ public final class NormalizedNodeMessages {
       }
       /**
        * <code>optional string path = 1;</code>
+       *
+       * <pre>
+       * @deprecated(use pathArgument)
+       * </pre>
        */
       public Builder clearPath() {
         bitField0_ = (bitField0_ & ~0x00000001);
@@ -4366,6 +6447,10 @@ public final class NormalizedNodeMessages {
       }
       /**
        * <code>optional string path = 1;</code>
+       *
+       * <pre>
+       * @deprecated(use pathArgument)
+       * </pre>
        */
       public Builder setPathBytes(
           com.google.protobuf.ByteString value) {
@@ -4382,12 +6467,20 @@ public final class NormalizedNodeMessages {
       private java.lang.Object type_ = "";
       /**
        * <code>optional string type = 2;</code>
+       *
+       * <pre>
+       * @deprecated(use intType)
+       * </pre>
        */
       public boolean hasType() {
         return ((bitField0_ & 0x00000002) == 0x00000002);
       }
       /**
        * <code>optional string type = 2;</code>
+       *
+       * <pre>
+       * @deprecated(use intType)
+       * </pre>
        */
       public java.lang.String getType() {
         java.lang.Object ref = type_;
@@ -4402,6 +6495,10 @@ public final class NormalizedNodeMessages {
       }
       /**
        * <code>optional string type = 2;</code>
+       *
+       * <pre>
+       * @deprecated(use intType)
+       * </pre>
        */
       public com.google.protobuf.ByteString
           getTypeBytes() {
@@ -4418,6 +6515,10 @@ public final class NormalizedNodeMessages {
       }
       /**
        * <code>optional string type = 2;</code>
+       *
+       * <pre>
+       * @deprecated(use intType)
+       * </pre>
        */
       public Builder setType(
           java.lang.String value) {
@@ -4431,6 +6532,10 @@ public final class NormalizedNodeMessages {
       }
       /**
        * <code>optional string type = 2;</code>
+       *
+       * <pre>
+       * @deprecated(use intType)
+       * </pre>
        */
       public Builder clearType() {
         bitField0_ = (bitField0_ & ~0x00000002);
@@ -4440,6 +6545,10 @@ public final class NormalizedNodeMessages {
       }
       /**
        * <code>optional string type = 2;</code>
+       *
+       * <pre>
+       * @deprecated(use intType)
+       * </pre>
        */
       public Builder setTypeBytes(
           com.google.protobuf.ByteString value) {
@@ -4452,13 +6561,163 @@ public final class NormalizedNodeMessages {
         return this;
       }
 
-      // repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;
+      // optional .org.opendaylight.controller.mdsal.PathArgument pathArgument = 3;
+      private org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument pathArgument_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.getDefaultInstance();
+      private com.google.protobuf.SingleFieldBuilder<
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder> pathArgumentBuilder_;
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.PathArgument pathArgument = 3;</code>
+       */
+      public boolean hasPathArgument() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.PathArgument pathArgument = 3;</code>
+       */
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument getPathArgument() {
+        if (pathArgumentBuilder_ == null) {
+          return pathArgument_;
+        } else {
+          return pathArgumentBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.PathArgument pathArgument = 3;</code>
+       */
+      public Builder setPathArgument(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument value) {
+        if (pathArgumentBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          pathArgument_ = value;
+          onChanged();
+        } else {
+          pathArgumentBuilder_.setMessage(value);
+        }
+        bitField0_ |= 0x00000004;
+        return this;
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.PathArgument pathArgument = 3;</code>
+       */
+      public Builder setPathArgument(
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.Builder builderForValue) {
+        if (pathArgumentBuilder_ == null) {
+          pathArgument_ = builderForValue.build();
+          onChanged();
+        } else {
+          pathArgumentBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00000004;
+        return this;
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.PathArgument pathArgument = 3;</code>
+       */
+      public Builder mergePathArgument(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument value) {
+        if (pathArgumentBuilder_ == null) {
+          if (((bitField0_ & 0x00000004) == 0x00000004) &&
+              pathArgument_ != org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.getDefaultInstance()) {
+            pathArgument_ =
+              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.newBuilder(pathArgument_).mergeFrom(value).buildPartial();
+          } else {
+            pathArgument_ = value;
+          }
+          onChanged();
+        } else {
+          pathArgumentBuilder_.mergeFrom(value);
+        }
+        bitField0_ |= 0x00000004;
+        return this;
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.PathArgument pathArgument = 3;</code>
+       */
+      public Builder clearPathArgument() {
+        if (pathArgumentBuilder_ == null) {
+          pathArgument_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.getDefaultInstance();
+          onChanged();
+        } else {
+          pathArgumentBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000004);
+        return this;
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.PathArgument pathArgument = 3;</code>
+       */
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.Builder getPathArgumentBuilder() {
+        bitField0_ |= 0x00000004;
+        onChanged();
+        return getPathArgumentFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.PathArgument pathArgument = 3;</code>
+       */
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder getPathArgumentOrBuilder() {
+        if (pathArgumentBuilder_ != null) {
+          return pathArgumentBuilder_.getMessageOrBuilder();
+        } else {
+          return pathArgument_;
+        }
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.PathArgument pathArgument = 3;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilder<
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder>
+          getPathArgumentFieldBuilder() {
+        if (pathArgumentBuilder_ == null) {
+          pathArgumentBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder>(
+                  pathArgument_,
+                  getParentForChildren(),
+                  isClean());
+          pathArgument_ = null;
+        }
+        return pathArgumentBuilder_;
+      }
+
+      // optional int32 intType = 4;
+      private int intType_ ;
+      /**
+       * <code>optional int32 intType = 4;</code>
+       */
+      public boolean hasIntType() {
+        return ((bitField0_ & 0x00000008) == 0x00000008);
+      }
+      /**
+       * <code>optional int32 intType = 4;</code>
+       */
+      public int getIntType() {
+        return intType_;
+      }
+      /**
+       * <code>optional int32 intType = 4;</code>
+       */
+      public Builder setIntType(int value) {
+        bitField0_ |= 0x00000008;
+        intType_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int32 intType = 4;</code>
+       */
+      public Builder clearIntType() {
+        bitField0_ = (bitField0_ & ~0x00000008);
+        intType_ = 0;
+        onChanged();
+        return this;
+      }
+
+      // repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;
       private java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute> attributes_ =
         java.util.Collections.emptyList();
       private void ensureAttributesIsMutable() {
-        if (!((bitField0_ & 0x00000004) == 0x00000004)) {
+        if (!((bitField0_ & 0x00000010) == 0x00000010)) {
           attributes_ = new java.util.ArrayList<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute>(attributes_);
-          bitField0_ |= 0x00000004;
+          bitField0_ |= 0x00000010;
          }
       }
 
@@ -4466,7 +6725,7 @@ public final class NormalizedNodeMessages {
           org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder> attributesBuilder_;
 
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
        */
       public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute> getAttributesList() {
         if (attributesBuilder_ == null) {
@@ -4476,7 +6735,7 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
        */
       public int getAttributesCount() {
         if (attributesBuilder_ == null) {
@@ -4486,7 +6745,7 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
        */
       public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute getAttributes(int index) {
         if (attributesBuilder_ == null) {
@@ -4496,7 +6755,7 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
        */
       public Builder setAttributes(
           int index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute value) {
@@ -4513,7 +6772,7 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
        */
       public Builder setAttributes(
           int index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder builderForValue) {
@@ -4527,7 +6786,7 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
        */
       public Builder addAttributes(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute value) {
         if (attributesBuilder_ == null) {
@@ -4543,7 +6802,7 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
        */
       public Builder addAttributes(
           int index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute value) {
@@ -4560,7 +6819,7 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
        */
       public Builder addAttributes(
           org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder builderForValue) {
@@ -4574,7 +6833,7 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
        */
       public Builder addAttributes(
           int index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder builderForValue) {
@@ -4588,7 +6847,7 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
        */
       public Builder addAllAttributes(
           java.lang.Iterable<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute> values) {
@@ -4602,12 +6861,12 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
        */
       public Builder clearAttributes() {
         if (attributesBuilder_ == null) {
           attributes_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000004);
+          bitField0_ = (bitField0_ & ~0x00000010);
           onChanged();
         } else {
           attributesBuilder_.clear();
@@ -4615,7 +6874,7 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
        */
       public Builder removeAttributes(int index) {
         if (attributesBuilder_ == null) {
@@ -4628,14 +6887,14 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
        */
       public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder getAttributesBuilder(
           int index) {
         return getAttributesFieldBuilder().getBuilder(index);
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
        */
       public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder getAttributesOrBuilder(
           int index) {
@@ -4645,7 +6904,7 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
        */
       public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
            getAttributesOrBuilderList() {
@@ -4656,14 +6915,14 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
        */
       public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder addAttributesBuilder() {
         return getAttributesFieldBuilder().addBuilder(
             org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.getDefaultInstance());
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
        */
       public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder addAttributesBuilder(
           int index) {
@@ -4671,7 +6930,7 @@ public final class NormalizedNodeMessages {
             index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.getDefaultInstance());
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 5;</code>
        */
       public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder>
            getAttributesBuilderList() {
@@ -4684,7 +6943,7 @@ public final class NormalizedNodeMessages {
           attributesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
               org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>(
                   attributes_,
-                  ((bitField0_ & 0x00000004) == 0x00000004),
+                  ((bitField0_ & 0x00000010) == 0x00000010),
                   getParentForChildren(),
                   isClean());
           attributes_ = null;
@@ -4692,13 +6951,13 @@ public final class NormalizedNodeMessages {
         return attributesBuilder_;
       }
 
-      // repeated .org.opendaylight.controller.mdsal.Node child = 4;
+      // repeated .org.opendaylight.controller.mdsal.Node child = 6;
       private java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node> child_ =
         java.util.Collections.emptyList();
       private void ensureChildIsMutable() {
-        if (!((bitField0_ & 0x00000008) == 0x00000008)) {
+        if (!((bitField0_ & 0x00000020) == 0x00000020)) {
           child_ = new java.util.ArrayList<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node>(child_);
-          bitField0_ |= 0x00000008;
+          bitField0_ |= 0x00000020;
          }
       }
 
@@ -4706,7 +6965,7 @@ public final class NormalizedNodeMessages {
           org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder> childBuilder_;
 
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
        */
       public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node> getChildList() {
         if (childBuilder_ == null) {
@@ -4716,7 +6975,7 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
        */
       public int getChildCount() {
         if (childBuilder_ == null) {
@@ -4726,7 +6985,7 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
        */
       public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node getChild(int index) {
         if (childBuilder_ == null) {
@@ -4736,7 +6995,7 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
        */
       public Builder setChild(
           int index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node value) {
@@ -4753,7 +7012,7 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
        */
       public Builder setChild(
           int index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder builderForValue) {
@@ -4767,7 +7026,7 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
        */
       public Builder addChild(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node value) {
         if (childBuilder_ == null) {
@@ -4783,7 +7042,7 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
        */
       public Builder addChild(
           int index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node value) {
@@ -4800,7 +7059,7 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
        */
       public Builder addChild(
           org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder builderForValue) {
@@ -4814,7 +7073,7 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
        */
       public Builder addChild(
           int index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder builderForValue) {
@@ -4828,7 +7087,7 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
        */
       public Builder addAllChild(
           java.lang.Iterable<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node> values) {
@@ -4842,12 +7101,12 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
        */
       public Builder clearChild() {
         if (childBuilder_ == null) {
           child_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000008);
+          bitField0_ = (bitField0_ & ~0x00000020);
           onChanged();
         } else {
           childBuilder_.clear();
@@ -4855,7 +7114,7 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
        */
       public Builder removeChild(int index) {
         if (childBuilder_ == null) {
@@ -4868,14 +7127,14 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
        */
       public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder getChildBuilder(
           int index) {
         return getChildFieldBuilder().getBuilder(index);
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
        */
       public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder getChildOrBuilder(
           int index) {
@@ -4885,7 +7144,7 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
        */
       public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
            getChildOrBuilderList() {
@@ -4896,14 +7155,14 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
        */
       public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder addChildBuilder() {
         return getChildFieldBuilder().addBuilder(
             org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.getDefaultInstance());
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
        */
       public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder addChildBuilder(
           int index) {
@@ -4911,7 +7170,7 @@ public final class NormalizedNodeMessages {
             index, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.getDefaultInstance());
       }
       /**
-       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
+       * <code>repeated .org.opendaylight.controller.mdsal.Node child = 6;</code>
        */
       public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder>
            getChildBuilderList() {
@@ -4924,7 +7183,7 @@ public final class NormalizedNodeMessages {
           childBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
               org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>(
                   child_,
-                  ((bitField0_ & 0x00000008) == 0x00000008),
+                  ((bitField0_ & 0x00000020) == 0x00000020),
                   getParentForChildren(),
                   isClean());
           child_ = null;
@@ -4932,16 +7191,16 @@ public final class NormalizedNodeMessages {
         return childBuilder_;
       }
 
-      // optional string value = 5;
+      // optional string value = 7;
       private java.lang.Object value_ = "";
       /**
-       * <code>optional string value = 5;</code>
+       * <code>optional string value = 7;</code>
        */
       public boolean hasValue() {
-        return ((bitField0_ & 0x00000010) == 0x00000010);
+        return ((bitField0_ & 0x00000040) == 0x00000040);
       }
       /**
-       * <code>optional string value = 5;</code>
+       * <code>optional string value = 7;</code>
        */
       public java.lang.String getValue() {
         java.lang.Object ref = value_;
@@ -4955,7 +7214,7 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>optional string value = 5;</code>
+       * <code>optional string value = 7;</code>
        */
       public com.google.protobuf.ByteString
           getValueBytes() {
@@ -4971,51 +7230,59 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>optional string value = 5;</code>
+       * <code>optional string value = 7;</code>
        */
       public Builder setValue(
           java.lang.String value) {
         if (value == null) {
     throw new NullPointerException();
   }
-  bitField0_ |= 0x00000010;
+  bitField0_ |= 0x00000040;
         value_ = value;
         onChanged();
         return this;
       }
       /**
-       * <code>optional string value = 5;</code>
+       * <code>optional string value = 7;</code>
        */
       public Builder clearValue() {
-        bitField0_ = (bitField0_ & ~0x00000010);
+        bitField0_ = (bitField0_ & ~0x00000040);
         value_ = getDefaultInstance().getValue();
         onChanged();
         return this;
       }
       /**
-       * <code>optional string value = 5;</code>
+       * <code>optional string value = 7;</code>
        */
       public Builder setValueBytes(
           com.google.protobuf.ByteString value) {
         if (value == null) {
     throw new NullPointerException();
   }
-  bitField0_ |= 0x00000010;
+  bitField0_ |= 0x00000040;
         value_ = value;
         onChanged();
         return this;
       }
 
-      // optional string valueType = 6;
+      // optional string valueType = 8;
       private java.lang.Object valueType_ = "";
       /**
-       * <code>optional string valueType = 6;</code>
+       * <code>optional string valueType = 8;</code>
+       *
+       * <pre>
+       * @deprecated(use intValueType)
+       * </pre>
        */
       public boolean hasValueType() {
-        return ((bitField0_ & 0x00000020) == 0x00000020);
+        return ((bitField0_ & 0x00000080) == 0x00000080);
       }
       /**
-       * <code>optional string valueType = 6;</code>
+       * <code>optional string valueType = 8;</code>
+       *
+       * <pre>
+       * @deprecated(use intValueType)
+       * </pre>
        */
       public java.lang.String getValueType() {
         java.lang.Object ref = valueType_;
@@ -5029,93 +7296,331 @@ public final class NormalizedNodeMessages {
         }
       }
       /**
-       * <code>optional string valueType = 6;</code>
+       * <code>optional string valueType = 8;</code>
+       *
+       * <pre>
+       * @deprecated(use intValueType)
+       * </pre>
+       */
+      public com.google.protobuf.ByteString
+          getValueTypeBytes() {
+        java.lang.Object ref = valueType_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b =
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          valueType_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string valueType = 8;</code>
+       *
+       * <pre>
+       * @deprecated(use intValueType)
+       * </pre>
+       */
+      public Builder setValueType(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000080;
+        valueType_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string valueType = 8;</code>
+       *
+       * <pre>
+       * @deprecated(use intValueType)
+       * </pre>
+       */
+      public Builder clearValueType() {
+        bitField0_ = (bitField0_ & ~0x00000080);
+        valueType_ = getDefaultInstance().getValueType();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string valueType = 8;</code>
+       *
+       * <pre>
+       * @deprecated(use intValueType)
+       * </pre>
+       */
+      public Builder setValueTypeBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000080;
+        valueType_ = value;
+        onChanged();
+        return this;
+      }
+
+      // optional int32 intValueType = 9;
+      private int intValueType_ ;
+      /**
+       * <code>optional int32 intValueType = 9;</code>
+       *
+       * <pre>
+       * instead of valueType
+       * </pre>
+       */
+      public boolean hasIntValueType() {
+        return ((bitField0_ & 0x00000100) == 0x00000100);
+      }
+      /**
+       * <code>optional int32 intValueType = 9;</code>
+       *
+       * <pre>
+       * instead of valueType
+       * </pre>
+       */
+      public int getIntValueType() {
+        return intValueType_;
+      }
+      /**
+       * <code>optional int32 intValueType = 9;</code>
+       *
+       * <pre>
+       * instead of valueType
+       * </pre>
+       */
+      public Builder setIntValueType(int value) {
+        bitField0_ |= 0x00000100;
+        intValueType_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int32 intValueType = 9;</code>
+       *
+       * <pre>
+       * instead of valueType
+       * </pre>
+       */
+      public Builder clearIntValueType() {
+        bitField0_ = (bitField0_ & ~0x00000100);
+        intValueType_ = 0;
+        onChanged();
+        return this;
+      }
+
+      // optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 10;
+      private org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier instanceIdentifierValue_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.getDefaultInstance();
+      private com.google.protobuf.SingleFieldBuilder<
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> instanceIdentifierValueBuilder_;
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 10;</code>
+       *
+       * <pre>
+       * Specific values
+       * </pre>
+       */
+      public boolean hasInstanceIdentifierValue() {
+        return ((bitField0_ & 0x00000200) == 0x00000200);
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 10;</code>
+       *
+       * <pre>
+       * Specific values
+       * </pre>
+       */
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier getInstanceIdentifierValue() {
+        if (instanceIdentifierValueBuilder_ == null) {
+          return instanceIdentifierValue_;
+        } else {
+          return instanceIdentifierValueBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 10;</code>
+       *
+       * <pre>
+       * Specific values
+       * </pre>
+       */
+      public Builder setInstanceIdentifierValue(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier value) {
+        if (instanceIdentifierValueBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          instanceIdentifierValue_ = value;
+          onChanged();
+        } else {
+          instanceIdentifierValueBuilder_.setMessage(value);
+        }
+        bitField0_ |= 0x00000200;
+        return this;
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 10;</code>
+       *
+       * <pre>
+       * Specific values
+       * </pre>
+       */
+      public Builder setInstanceIdentifierValue(
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder builderForValue) {
+        if (instanceIdentifierValueBuilder_ == null) {
+          instanceIdentifierValue_ = builderForValue.build();
+          onChanged();
+        } else {
+          instanceIdentifierValueBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00000200;
+        return this;
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 10;</code>
+       *
+       * <pre>
+       * Specific values
+       * </pre>
        */
-      public com.google.protobuf.ByteString
-          getValueTypeBytes() {
-        java.lang.Object ref = valueType_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b =
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          valueType_ = b;
-          return b;
+      public Builder mergeInstanceIdentifierValue(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier value) {
+        if (instanceIdentifierValueBuilder_ == null) {
+          if (((bitField0_ & 0x00000200) == 0x00000200) &&
+              instanceIdentifierValue_ != org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.getDefaultInstance()) {
+            instanceIdentifierValue_ =
+              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.newBuilder(instanceIdentifierValue_).mergeFrom(value).buildPartial();
+          } else {
+            instanceIdentifierValue_ = value;
+          }
+          onChanged();
         } else {
-          return (com.google.protobuf.ByteString) ref;
+          instanceIdentifierValueBuilder_.mergeFrom(value);
         }
+        bitField0_ |= 0x00000200;
+        return this;
       }
       /**
-       * <code>optional string valueType = 6;</code>
+       * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 10;</code>
+       *
+       * <pre>
+       * Specific values
+       * </pre>
        */
-      public Builder setValueType(
-          java.lang.String value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000020;
-        valueType_ = value;
-        onChanged();
+      public Builder clearInstanceIdentifierValue() {
+        if (instanceIdentifierValueBuilder_ == null) {
+          instanceIdentifierValue_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.getDefaultInstance();
+          onChanged();
+        } else {
+          instanceIdentifierValueBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000200);
         return this;
       }
       /**
-       * <code>optional string valueType = 6;</code>
+       * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 10;</code>
+       *
+       * <pre>
+       * Specific values
+       * </pre>
        */
-      public Builder clearValueType() {
-        bitField0_ = (bitField0_ & ~0x00000020);
-        valueType_ = getDefaultInstance().getValueType();
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder getInstanceIdentifierValueBuilder() {
+        bitField0_ |= 0x00000200;
         onChanged();
-        return this;
+        return getInstanceIdentifierValueFieldBuilder().getBuilder();
       }
       /**
-       * <code>optional string valueType = 6;</code>
+       * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 10;</code>
+       *
+       * <pre>
+       * Specific values
+       * </pre>
        */
-      public Builder setValueTypeBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000020;
-        valueType_ = value;
-        onChanged();
-        return this;
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder getInstanceIdentifierValueOrBuilder() {
+        if (instanceIdentifierValueBuilder_ != null) {
+          return instanceIdentifierValueBuilder_.getMessageOrBuilder();
+        } else {
+          return instanceIdentifierValue_;
+        }
+      }
+      /**
+       * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 10;</code>
+       *
+       * <pre>
+       * Specific values
+       * </pre>
+       */
+      private com.google.protobuf.SingleFieldBuilder<
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
+          getInstanceIdentifierValueFieldBuilder() {
+        if (instanceIdentifierValueBuilder_ == null) {
+          instanceIdentifierValueBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>(
+                  instanceIdentifierValue_,
+                  getParentForChildren(),
+                  isClean());
+          instanceIdentifierValue_ = null;
+        }
+        return instanceIdentifierValueBuilder_;
       }
 
-      // repeated string bitsValue = 7;
+      // repeated string bitsValue = 11;
       private com.google.protobuf.LazyStringList bitsValue_ = com.google.protobuf.LazyStringArrayList.EMPTY;
       private void ensureBitsValueIsMutable() {
-        if (!((bitField0_ & 0x00000040) == 0x00000040)) {
+        if (!((bitField0_ & 0x00000400) == 0x00000400)) {
           bitsValue_ = new com.google.protobuf.LazyStringArrayList(bitsValue_);
-          bitField0_ |= 0x00000040;
+          bitField0_ |= 0x00000400;
          }
       }
       /**
-       * <code>repeated string bitsValue = 7;</code>
+       * <code>repeated string bitsValue = 11;</code>
+       *
+       * <pre>
+       * intValueType = Bits
+       * </pre>
        */
       public java.util.List<java.lang.String>
           getBitsValueList() {
         return java.util.Collections.unmodifiableList(bitsValue_);
       }
       /**
-       * <code>repeated string bitsValue = 7;</code>
+       * <code>repeated string bitsValue = 11;</code>
+       *
+       * <pre>
+       * intValueType = Bits
+       * </pre>
        */
       public int getBitsValueCount() {
         return bitsValue_.size();
       }
       /**
-       * <code>repeated string bitsValue = 7;</code>
+       * <code>repeated string bitsValue = 11;</code>
+       *
+       * <pre>
+       * intValueType = Bits
+       * </pre>
        */
       public java.lang.String getBitsValue(int index) {
         return bitsValue_.get(index);
       }
       /**
-       * <code>repeated string bitsValue = 7;</code>
+       * <code>repeated string bitsValue = 11;</code>
+       *
+       * <pre>
+       * intValueType = Bits
+       * </pre>
        */
       public com.google.protobuf.ByteString
           getBitsValueBytes(int index) {
         return bitsValue_.getByteString(index);
       }
       /**
-       * <code>repeated string bitsValue = 7;</code>
+       * <code>repeated string bitsValue = 11;</code>
+       *
+       * <pre>
+       * intValueType = Bits
+       * </pre>
        */
       public Builder setBitsValue(
           int index, java.lang.String value) {
@@ -5128,7 +7633,11 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated string bitsValue = 7;</code>
+       * <code>repeated string bitsValue = 11;</code>
+       *
+       * <pre>
+       * intValueType = Bits
+       * </pre>
        */
       public Builder addBitsValue(
           java.lang.String value) {
@@ -5141,7 +7650,11 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated string bitsValue = 7;</code>
+       * <code>repeated string bitsValue = 11;</code>
+       *
+       * <pre>
+       * intValueType = Bits
+       * </pre>
        */
       public Builder addAllBitsValue(
           java.lang.Iterable<java.lang.String> values) {
@@ -5151,16 +7664,24 @@ public final class NormalizedNodeMessages {
         return this;
       }
       /**
-       * <code>repeated string bitsValue = 7;</code>
+       * <code>repeated string bitsValue = 11;</code>
+       *
+       * <pre>
+       * intValueType = Bits
+       * </pre>
        */
       public Builder clearBitsValue() {
         bitsValue_ = com.google.protobuf.LazyStringArrayList.EMPTY;
-        bitField0_ = (bitField0_ & ~0x00000040);
+        bitField0_ = (bitField0_ & ~0x00000400);
         onChanged();
         return this;
       }
       /**
-       * <code>repeated string bitsValue = 7;</code>
+       * <code>repeated string bitsValue = 11;</code>
+       *
+       * <pre>
+       * intValueType = Bits
+       * </pre>
        */
       public Builder addBitsValueBytes(
           com.google.protobuf.ByteString value) {
@@ -5173,121 +7694,133 @@ public final class NormalizedNodeMessages {
         return this;
       }
 
-      // optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;
-      private org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier instanceIdentifierValue_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.getDefaultInstance();
-      private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> instanceIdentifierValueBuilder_;
+      // repeated string code = 12;
+      private com.google.protobuf.LazyStringList code_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+      private void ensureCodeIsMutable() {
+        if (!((bitField0_ & 0x00000800) == 0x00000800)) {
+          code_ = new com.google.protobuf.LazyStringArrayList(code_);
+          bitField0_ |= 0x00000800;
+         }
+      }
       /**
-       * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;</code>
+       * <code>repeated string code = 12;</code>
+       *
+       * <pre>
+       * A list of string codes which can be used for any repeated strings in the NormalizedNode
+       * </pre>
        */
-      public boolean hasInstanceIdentifierValue() {
-        return ((bitField0_ & 0x00000080) == 0x00000080);
+      public java.util.List<java.lang.String>
+          getCodeList() {
+        return java.util.Collections.unmodifiableList(code_);
       }
       /**
-       * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;</code>
+       * <code>repeated string code = 12;</code>
+       *
+       * <pre>
+       * A list of string codes which can be used for any repeated strings in the NormalizedNode
+       * </pre>
        */
-      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier getInstanceIdentifierValue() {
-        if (instanceIdentifierValueBuilder_ == null) {
-          return instanceIdentifierValue_;
-        } else {
-          return instanceIdentifierValueBuilder_.getMessage();
-        }
+      public int getCodeCount() {
+        return code_.size();
       }
       /**
-       * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;</code>
+       * <code>repeated string code = 12;</code>
+       *
+       * <pre>
+       * A list of string codes which can be used for any repeated strings in the NormalizedNode
+       * </pre>
        */
-      public Builder setInstanceIdentifierValue(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier value) {
-        if (instanceIdentifierValueBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          instanceIdentifierValue_ = value;
-          onChanged();
-        } else {
-          instanceIdentifierValueBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000080;
-        return this;
+      public java.lang.String getCode(int index) {
+        return code_.get(index);
       }
       /**
-       * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;</code>
+       * <code>repeated string code = 12;</code>
+       *
+       * <pre>
+       * A list of string codes which can be used for any repeated strings in the NormalizedNode
+       * </pre>
        */
-      public Builder setInstanceIdentifierValue(
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder builderForValue) {
-        if (instanceIdentifierValueBuilder_ == null) {
-          instanceIdentifierValue_ = builderForValue.build();
-          onChanged();
-        } else {
-          instanceIdentifierValueBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000080;
-        return this;
+      public com.google.protobuf.ByteString
+          getCodeBytes(int index) {
+        return code_.getByteString(index);
       }
       /**
-       * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;</code>
+       * <code>repeated string code = 12;</code>
+       *
+       * <pre>
+       * A list of string codes which can be used for any repeated strings in the NormalizedNode
+       * </pre>
        */
-      public Builder mergeInstanceIdentifierValue(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier value) {
-        if (instanceIdentifierValueBuilder_ == null) {
-          if (((bitField0_ & 0x00000080) == 0x00000080) &&
-              instanceIdentifierValue_ != org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.getDefaultInstance()) {
-            instanceIdentifierValue_ =
-              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.newBuilder(instanceIdentifierValue_).mergeFrom(value).buildPartial();
-          } else {
-            instanceIdentifierValue_ = value;
-          }
-          onChanged();
-        } else {
-          instanceIdentifierValueBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000080;
+      public Builder setCode(
+          int index, java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  ensureCodeIsMutable();
+        code_.set(index, value);
+        onChanged();
         return this;
       }
       /**
-       * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;</code>
+       * <code>repeated string code = 12;</code>
+       *
+       * <pre>
+       * A list of string codes which can be used for any repeated strings in the NormalizedNode
+       * </pre>
        */
-      public Builder clearInstanceIdentifierValue() {
-        if (instanceIdentifierValueBuilder_ == null) {
-          instanceIdentifierValue_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.getDefaultInstance();
-          onChanged();
-        } else {
-          instanceIdentifierValueBuilder_.clear();
-        }
-        bitField0_ = (bitField0_ & ~0x00000080);
+      public Builder addCode(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  ensureCodeIsMutable();
+        code_.add(value);
+        onChanged();
         return this;
       }
       /**
-       * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;</code>
+       * <code>repeated string code = 12;</code>
+       *
+       * <pre>
+       * A list of string codes which can be used for any repeated strings in the NormalizedNode
+       * </pre>
        */
-      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder getInstanceIdentifierValueBuilder() {
-        bitField0_ |= 0x00000080;
+      public Builder addAllCode(
+          java.lang.Iterable<java.lang.String> values) {
+        ensureCodeIsMutable();
+        super.addAll(values, code_);
         onChanged();
-        return getInstanceIdentifierValueFieldBuilder().getBuilder();
+        return this;
       }
       /**
-       * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;</code>
+       * <code>repeated string code = 12;</code>
+       *
+       * <pre>
+       * A list of string codes which can be used for any repeated strings in the NormalizedNode
+       * </pre>
        */
-      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder getInstanceIdentifierValueOrBuilder() {
-        if (instanceIdentifierValueBuilder_ != null) {
-          return instanceIdentifierValueBuilder_.getMessageOrBuilder();
-        } else {
-          return instanceIdentifierValue_;
-        }
+      public Builder clearCode() {
+        code_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000800);
+        onChanged();
+        return this;
       }
       /**
-       * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;</code>
+       * <code>repeated string code = 12;</code>
+       *
+       * <pre>
+       * A list of string codes which can be used for any repeated strings in the NormalizedNode
+       * </pre>
        */
-      private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
-          getInstanceIdentifierValueFieldBuilder() {
-        if (instanceIdentifierValueBuilder_ == null) {
-          instanceIdentifierValueBuilder_ = new com.google.protobuf.SingleFieldBuilder<
-              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>(
-                  instanceIdentifierValue_,
-                  getParentForChildren(),
-                  isClean());
-          instanceIdentifierValue_ = null;
-        }
-        return instanceIdentifierValueBuilder_;
+      public Builder addCodeBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  ensureCodeIsMutable();
+        code_.add(value);
+        onChanged();
+        return this;
       }
 
       // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.Node)
@@ -7402,6 +9935,11 @@ public final class NormalizedNodeMessages {
   private static
     com.google.protobuf.GeneratedMessage.FieldAccessorTable
       internal_static_org_opendaylight_controller_mdsal_Attribute_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_PathArgumentAttribute_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_PathArgumentAttribute_fieldAccessorTable;
   private static com.google.protobuf.Descriptors.Descriptor
     internal_static_org_opendaylight_controller_mdsal_QName_descriptor;
   private static
@@ -7448,32 +9986,42 @@ public final class NormalizedNodeMessages {
     java.lang.String[] descriptorData = {
       "\n\014Common.proto\022!org.opendaylight.control" +
       "ler.mdsal\"6\n\tAttribute\022\014\n\004name\030\001 \002(\t\022\r\n\005" +
-      "value\030\002 \001(\t\022\014\n\004type\030\003 \001(\t\"\026\n\005QName\022\r\n\005va" +
-      "lue\030\001 \002(\t\"\251\001\n\014PathArgument\022\r\n\005value\030\001 \002(" +
-      "\t\022\014\n\004type\030\002 \001(\t\022:\n\010nodeType\030\003 \001(\0132(.org." +
-      "opendaylight.controller.mdsal.QName\022@\n\na" +
-      "ttributes\030\004 \003(\0132,.org.opendaylight.contr" +
-      "oller.mdsal.Attribute\"X\n\022InstanceIdentif" +
-      "ier\022B\n\targuments\030\001 \003(\0132/.org.opendayligh" +
-      "t.controller.mdsal.PathArgument\"\251\002\n\004Node",
-      "\022\014\n\004path\030\001 \001(\t\022\014\n\004type\030\002 \001(\t\022@\n\nattribut" +
-      "es\030\003 \003(\0132,.org.opendaylight.controller.m" +
-      "dsal.Attribute\0226\n\005child\030\004 \003(\0132\'.org.open" +
-      "daylight.controller.mdsal.Node\022\r\n\005value\030" +
-      "\005 \001(\t\022\021\n\tvalueType\030\006 \001(\t\022\021\n\tbitsValue\030\007 " +
-      "\003(\t\022V\n\027instanceIdentifierValue\030\010 \001(\01325.o" +
-      "rg.opendaylight.controller.mdsal.Instanc" +
-      "eIdentifier\"`\n\tContainer\022\022\n\nparentPath\030\001" +
-      " \002(\t\022?\n\016normalizedNode\030\002 \001(\0132\'.org.opend" +
-      "aylight.controller.mdsal.Node\"\246\001\n\014NodeMa",
-      "pEntry\022U\n\026instanceIdentifierPath\030\001 \002(\01325" +
-      ".org.opendaylight.controller.mdsal.Insta" +
-      "nceIdentifier\022?\n\016normalizedNode\030\002 \001(\0132\'." +
-      "org.opendaylight.controller.mdsal.Node\"N" +
-      "\n\007NodeMap\022C\n\nmapEntries\030\001 \003(\0132/.org.open" +
-      "daylight.controller.mdsal.NodeMapEntryBO" +
-      "\n5org.opendaylight.controller.protobuff." +
-      "messages.commonB\026NormalizedNodeMessages"
+      "value\030\002 \001(\t\022\014\n\004type\030\003 \001(\t\"l\n\025PathArgumen" +
+      "tAttribute\0226\n\004name\030\001 \001(\0132(.org.opendayli" +
+      "ght.controller.mdsal.QName\022\r\n\005value\030\002 \001(" +
+      "\t\022\014\n\004type\030\003 \001(\005\"N\n\005QName\022\r\n\005value\030\001 \001(\t\022" +
+      "\021\n\tnamespace\030\002 \001(\005\022\020\n\010revision\030\003 \001(\005\022\021\n\t" +
+      "localName\030\004 \001(\005\"\207\002\n\014PathArgument\022\r\n\005valu" +
+      "e\030\001 \001(\t\022\014\n\004type\030\002 \001(\t\022:\n\010nodeType\030\003 \001(\0132" +
+      "(.org.opendaylight.controller.mdsal.QNam",
+      "e\022K\n\tattribute\030\004 \003(\01328.org.opendaylight." +
+      "controller.mdsal.PathArgumentAttribute\022@" +
+      "\n\nattributes\030\005 \003(\0132,.org.opendaylight.co" +
+      "ntroller.mdsal.Attribute\022\017\n\007intType\030\006 \001(" +
+      "\005\"X\n\022InstanceIdentifier\022B\n\targuments\030\001 \003" +
+      "(\0132/.org.opendaylight.controller.mdsal.P" +
+      "athArgument\"\245\003\n\004Node\022\014\n\004path\030\001 \001(\t\022\014\n\004ty" +
+      "pe\030\002 \001(\t\022E\n\014pathArgument\030\003 \001(\0132/.org.ope" +
+      "ndaylight.controller.mdsal.PathArgument\022" +
+      "\017\n\007intType\030\004 \001(\005\022@\n\nattributes\030\005 \003(\0132,.o",
+      "rg.opendaylight.controller.mdsal.Attribu" +
+      "te\0226\n\005child\030\006 \003(\0132\'.org.opendaylight.con" +
+      "troller.mdsal.Node\022\r\n\005value\030\007 \001(\t\022\021\n\tval" +
+      "ueType\030\010 \001(\t\022\024\n\014intValueType\030\t \001(\005\022V\n\027in" +
+      "stanceIdentifierValue\030\n \001(\01325.org.openda" +
+      "ylight.controller.mdsal.InstanceIdentifi" +
+      "er\022\021\n\tbitsValue\030\013 \003(\t\022\014\n\004code\030\014 \003(\t\"`\n\tC" +
+      "ontainer\022\022\n\nparentPath\030\001 \002(\t\022?\n\016normaliz" +
+      "edNode\030\002 \001(\0132\'.org.opendaylight.controll" +
+      "er.mdsal.Node\"\246\001\n\014NodeMapEntry\022U\n\026instan",
+      "ceIdentifierPath\030\001 \002(\01325.org.opendayligh" +
+      "t.controller.mdsal.InstanceIdentifier\022?\n" +
+      "\016normalizedNode\030\002 \001(\0132\'.org.opendaylight" +
+      ".controller.mdsal.Node\"N\n\007NodeMap\022C\n\nmap" +
+      "Entries\030\001 \003(\0132/.org.opendaylight.control" +
+      "ler.mdsal.NodeMapEntryBO\n5org.opendaylig" +
+      "ht.controller.protobuff.messages.commonB" +
+      "\026NormalizedNodeMessages"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
       new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -7486,44 +10034,50 @@ public final class NormalizedNodeMessages {
             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
               internal_static_org_opendaylight_controller_mdsal_Attribute_descriptor,
               new java.lang.String[] { "Name", "Value", "Type", });
-          internal_static_org_opendaylight_controller_mdsal_QName_descriptor =
+          internal_static_org_opendaylight_controller_mdsal_PathArgumentAttribute_descriptor =
             getDescriptor().getMessageTypes().get(1);
+          internal_static_org_opendaylight_controller_mdsal_PathArgumentAttribute_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_PathArgumentAttribute_descriptor,
+              new java.lang.String[] { "Name", "Value", "Type", });
+          internal_static_org_opendaylight_controller_mdsal_QName_descriptor =
+            getDescriptor().getMessageTypes().get(2);
           internal_static_org_opendaylight_controller_mdsal_QName_fieldAccessorTable = new
             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
               internal_static_org_opendaylight_controller_mdsal_QName_descriptor,
-              new java.lang.String[] { "Value", });
+              new java.lang.String[] { "Value", "Namespace", "Revision", "LocalName", });
           internal_static_org_opendaylight_controller_mdsal_PathArgument_descriptor =
-            getDescriptor().getMessageTypes().get(2);
+            getDescriptor().getMessageTypes().get(3);
           internal_static_org_opendaylight_controller_mdsal_PathArgument_fieldAccessorTable = new
             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
               internal_static_org_opendaylight_controller_mdsal_PathArgument_descriptor,
-              new java.lang.String[] { "Value", "Type", "NodeType", "Attributes", });
+              new java.lang.String[] { "Value", "Type", "NodeType", "Attribute", "Attributes", "IntType", });
           internal_static_org_opendaylight_controller_mdsal_InstanceIdentifier_descriptor =
-            getDescriptor().getMessageTypes().get(3);
+            getDescriptor().getMessageTypes().get(4);
           internal_static_org_opendaylight_controller_mdsal_InstanceIdentifier_fieldAccessorTable = new
             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
               internal_static_org_opendaylight_controller_mdsal_InstanceIdentifier_descriptor,
               new java.lang.String[] { "Arguments", });
           internal_static_org_opendaylight_controller_mdsal_Node_descriptor =
-            getDescriptor().getMessageTypes().get(4);
+            getDescriptor().getMessageTypes().get(5);
           internal_static_org_opendaylight_controller_mdsal_Node_fieldAccessorTable = new
             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
               internal_static_org_opendaylight_controller_mdsal_Node_descriptor,
-              new java.lang.String[] { "Path", "Type", "Attributes", "Child", "Value", "ValueType", "BitsValue", "InstanceIdentifierValue", });
+              new java.lang.String[] { "Path", "Type", "PathArgument", "IntType", "Attributes", "Child", "Value", "ValueType", "IntValueType", "InstanceIdentifierValue", "BitsValue", "Code", });
           internal_static_org_opendaylight_controller_mdsal_Container_descriptor =
-            getDescriptor().getMessageTypes().get(5);
+            getDescriptor().getMessageTypes().get(6);
           internal_static_org_opendaylight_controller_mdsal_Container_fieldAccessorTable = new
             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
               internal_static_org_opendaylight_controller_mdsal_Container_descriptor,
               new java.lang.String[] { "ParentPath", "NormalizedNode", });
           internal_static_org_opendaylight_controller_mdsal_NodeMapEntry_descriptor =
-            getDescriptor().getMessageTypes().get(6);
+            getDescriptor().getMessageTypes().get(7);
           internal_static_org_opendaylight_controller_mdsal_NodeMapEntry_fieldAccessorTable = new
             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
               internal_static_org_opendaylight_controller_mdsal_NodeMapEntry_descriptor,
               new java.lang.String[] { "InstanceIdentifierPath", "NormalizedNode", });
           internal_static_org_opendaylight_controller_mdsal_NodeMap_descriptor =
-            getDescriptor().getMessageTypes().get(7);
+            getDescriptor().getMessageTypes().get(8);
           internal_static_org_opendaylight_controller_mdsal_NodeMap_fieldAccessorTable = new
             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
               internal_static_org_opendaylight_controller_mdsal_NodeMap_descriptor,
index d354348da8fb3ade21939c7be442d859479640f0..fcf1f45bc26d5216ab8e06c4105e38d312bd1a73 100644 (file)
@@ -1640,7 +1640,7 @@ public final class PersistentMessages {
       .internalBuildGeneratedFileFrom(descriptorData,
         new com.google.protobuf.Descriptors.FileDescriptor[] {
           org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.getDescriptor(),
-          org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.getDescriptor(),
+          org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.getDescriptor(),
         }, assigner);
   }
 
index ca578a88aad2ae6c0155a98bd949de2e09d1fa44..5a9cb9d3245f6de808a9db0596810706cb2604e0 100644 (file)
@@ -15,7 +15,7 @@ public final class CompositeModificationPayload {
    */
   public static final
     com.google.protobuf.GeneratedMessage.GeneratedExtension<
-      org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload,
+      org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload,
       org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.CompositeModification> modification = com.google.protobuf.GeneratedMessage
           .newFileScopedGeneratedExtension(
         org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.CompositeModification.class,
@@ -51,7 +51,7 @@ public final class CompositeModificationPayload {
     com.google.protobuf.Descriptors.FileDescriptor
       .internalBuildGeneratedFileFrom(descriptorData,
         new com.google.protobuf.Descriptors.FileDescriptor[] {
-          org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.getDescriptor(),
+          org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages.getDescriptor(),
           org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.getDescriptor(),
           org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.getDescriptor(),
         }, assigner);
index bdd66d3aba25e4766960ed0611362cf813d5360c..ded80713fb3feba577065da17410d3408786046e 100644 (file)
@@ -6945,11 +6945,11 @@ public final class ShardTransactionMessages {
 
       public final boolean isInitialized() {
         if (!hasInstanceIdentifierPathArguments()) {
-          
+
           return false;
         }
         if (!getInstanceIdentifierPathArguments().isInitialized()) {
-          
+
           return false;
         }
         return true;
@@ -7078,7 +7078,7 @@ public final class ShardTransactionMessages {
        * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
           getInstanceIdentifierPathArgumentsFieldBuilder() {
         if (instanceIdentifierPathArgumentsBuilder_ == null) {
           instanceIdentifierPathArgumentsBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -7437,7 +7437,7 @@ public final class ShardTransactionMessages {
 
       public final boolean isInitialized() {
         if (!hasExists()) {
-          
+
           return false;
         }
         return true;
similarity index 88%
rename from opendaylight/md-sal/sal-akka-raft/src/main/resources/AppendEntriesMessages.proto
rename to opendaylight/md-sal/sal-clustering-commons/src/main/resources/AppendEntriesMessages.proto
index ab591ea0797fdd92e94c435562a4aecc40179856..4df56ff79dcf1791abc9838d828eaa62f7932861 100644 (file)
@@ -1,6 +1,6 @@
 package org.opendaylight.controller.cluster.raft;
 
-option java_package = "org.opendaylight.controller.cluster.raft.protobuff.messages";
+option java_package = "org.opendaylight.controller.protobuff.messages.cluster.raft";
 option java_outer_classname = "AppendEntriesMessages";
 option optimize_for = SPEED;
 
index 59d78dd04d483c8157d142a7bc7a04958e55db25..0b3ff21eb78737aa58450db900f5877b217718b1 100644 (file)
@@ -10,16 +10,29 @@ message Attribute{
   optional string type=3;
 }
 
+message PathArgumentAttribute{
+    optional QName name =1;
+    optional string value=2;
+    optional int32 type=3;
+}
+
+
 message QName {
-    required string value=1;
+    optional string value=1; // @deprecated
+    optional int32 namespace=2;
+    optional int32 revision=3;
+    optional int32 localName=4;
 }
 
 message PathArgument {
-  required string value=1;
-  optional string type=2; //NodeIdentifier, NodeWithValue, NodeIdentifierWithPredicates
+  optional string value=1; // @deprecated
+  optional string type=2; // @deprecated
+
   optional QName nodeType=3;
-  repeated Attribute attributes=4;
 
+  repeated PathArgumentAttribute attribute=4;
+  repeated Attribute attributes=5; // @deprecated For backward compatibility (see InstanceIdentifierUtils)
+  optional int32 intType = 6;
 }
 
 message InstanceIdentifier {
@@ -27,14 +40,24 @@ message InstanceIdentifier {
 }
 
 message Node{
-  optional string path = 1;
-  optional string type = 2;
-  repeated Attribute attributes = 3;
-  repeated Node child=4;
-  optional string value = 5;
-  optional string valueType = 6;
-  repeated string bitsValue = 7;
-  optional InstanceIdentifier instanceIdentifierValue = 8;
+  optional string path = 1; // @deprecated(use pathArgument)
+  optional string type = 2; // @deprecated(use intType)
+  optional PathArgument pathArgument = 3;
+  optional int32 intType = 4;
+
+  repeated Attribute attributes = 5;
+
+  repeated Node child = 6;
+
+  optional string value = 7;
+  optional string valueType = 8; // @deprecated(use intValueType)
+  optional int32 intValueType = 9; // instead of valueType
+
+  // Specific values
+  optional InstanceIdentifier instanceIdentifierValue = 10; // intValueType = YangInstanceIdentifier
+  repeated string bitsValue = 11; // intValueType = Bits
+
+  repeated string code = 12; // A list of string codes which can be used for any repeated strings in the NormalizedNode
 }
 
 message Container{
similarity index 79%
rename from opendaylight/md-sal/sal-akka-raft/src/main/resources/KeyValueMessages.proto
rename to opendaylight/md-sal/sal-clustering-commons/src/main/resources/KeyValueMessages.proto
index 7ee0b215eeb1a0ac2b3bee44b46c2dd24ca89e05..8dc790b3dd3a9e331a83b01ba87bfd8c5d00e3fb 100644 (file)
@@ -2,7 +2,7 @@ package org.opendaylight.controller.cluster.raft;
 
 import "AppendEntriesMessages.proto";
 
-option java_package = "org.opendaylight.controller.cluster.example.protobuff.messages";
+option java_package = "org.opendaylight.controller.protobuff.messages.cluster.example";
 option java_outer_classname = "KeyValueMessages";
 option optimize_for = SPEED;
 
similarity index 54%
rename from opendaylight/md-sal/sal-akka-raft/src/test/resources/MockPayload.proto
rename to opendaylight/md-sal/sal-clustering-commons/src/main/resources/MockPayload.proto
index 0e0c6044891e931f541b917480f90e3920f957f1..ce29db4e3f28a2f302890099dde1a8a2a486a3ff 100644 (file)
@@ -1,8 +1,8 @@
 import "AppendEntriesMessages.proto";
 
-package org.opendaylight.controller.cluster.raft;
+package org.opendaylight.controller.cluster.raft.test;
 
-option java_package = "org.opendaylight.controller.cluster.raft.protobuff.messages";
+option java_package = "org.opendaylight.controller.protobuff.messages.cluster.raft.test";
 option java_outer_classname = "MockPayloadMessages";
 
 extend AppendEntries.ReplicatedLogEntry.Payload {
index bdad86ddc1e8fb5521607fbb91a575a99e677d38..a9f9c722deefd942f3259fea3f05a929d42aa827 100644 (file)
 
 package org.opendaylight.controller.cluster.datastore.node;
 
-import junit.framework.Assert;
 import org.junit.Before;
 import org.junit.Test;
-import org.opendaylight.controller.cluster.datastore.node.utils.NodeIdentifierFactory;
 import org.opendaylight.controller.cluster.datastore.node.utils.NormalizedNodeGetter;
 import org.opendaylight.controller.cluster.datastore.node.utils.NormalizedNodeNavigator;
+import org.opendaylight.controller.cluster.datastore.node.utils.PathUtils;
+import org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeSerializer;
 import org.opendaylight.controller.cluster.datastore.util.TestModel;
 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Container;
 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node;
@@ -24,11 +24,11 @@ import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
-import java.util.ArrayList;
 import java.util.List;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 public class NormalizedNodeToNodeCodecTest {
 
@@ -43,21 +43,9 @@ public class NormalizedNodeToNodeCodecTest {
   }
 
   private YangInstanceIdentifier instanceIdentifierFromString(String s) {
-
-    String[] ids = s.split("/");
-
-    List<YangInstanceIdentifier.PathArgument> pathArguments = new ArrayList<>();
-    for (String nodeId : ids) {
-      if (!"".equals(nodeId)) {
-        pathArguments.add(NodeIdentifierFactory.getArgument(nodeId));
-      }
-    }
-    final YangInstanceIdentifier instanceIdentifier =
-        YangInstanceIdentifier.create(pathArguments);
-    return instanceIdentifier;
+      return PathUtils.toYangInstanceIdentifier(s);
   }
 
-
   @Test
   public void testNormalizeNodeAttributesToProtoBuffNode() {
     final NormalizedNode<?, ?> documentOne = TestModel.createTestContainer();
@@ -69,7 +57,7 @@ public class NormalizedNodeToNodeCodecTest {
 
     NormalizedNodeGetter normalizedNodeGetter = new NormalizedNodeGetter(id);
     new NormalizedNodeNavigator(normalizedNodeGetter).navigate(
-        YangInstanceIdentifier.builder().build().toString(), documentOne);
+        PathUtils.toString(YangInstanceIdentifier.builder().build()), documentOne);
 
     // Validate the value of id can be retrieved from the normalized node
     NormalizedNode output = normalizedNodeGetter.getOutput();
@@ -87,7 +75,8 @@ public class NormalizedNodeToNodeCodecTest {
 
     assertNotNull(container);
     assertEquals(id, container.getParentPath() + "/"
-        + container.getNormalizedNode().getPath());
+        + NormalizedNodeSerializer.deSerialize(container.getNormalizedNode(),
+        container.getNormalizedNode().getPathArgument()));
 
     // Decode the normalized node from the ProtocolBuffer form
     // first get the node representation of normalized node
@@ -122,7 +111,7 @@ public class NormalizedNodeToNodeCodecTest {
             .decode(
                 instanceIdentifierFromString("/(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test"),
                 container.getNormalizedNode());
-    assertNotNull(decode != null);
+    assertNotNull(decode);
 
     // let us ensure that the return decode normalized node encode returns same container
     Container containerResult =
@@ -130,10 +119,8 @@ public class NormalizedNodeToNodeCodecTest {
             .build(), decode);
 
     assertEquals(container.getParentPath(), containerResult.getParentPath());
-    assertEquals(container.getNormalizedNode().getChildCount(), container
-        .getNormalizedNode().getChildCount());
 
-    Assert.assertEquals(containerResult.getNormalizedNode().getChildCount(),
+    assertEquals(containerResult.getNormalizedNode().getChildCount(),
         container.getNormalizedNode().getChildCount());
 
     // check first level children are proper
@@ -153,13 +140,22 @@ public class NormalizedNodeToNodeCodecTest {
     for (Node resultChild : childrenResult) {
       bFound = false;
       for (Node originalChild : childrenOriginal) {
-        if (originalChild.getPath().equals(resultChild.getPath())
-            && resultChild.getType().equals(resultChild.getType())) {
+
+        YangInstanceIdentifier.PathArgument result = NormalizedNodeSerializer.deSerialize(
+              containerResult.getNormalizedNode(),
+              resultChild.getPathArgument());
+
+          YangInstanceIdentifier.PathArgument original = NormalizedNodeSerializer.deSerialize(
+              container.getNormalizedNode(),
+              originalChild.getPathArgument());
+
+        if (original.equals(result)
+            && resultChild.getIntType() == resultChild.getIntType()) {
           bFound = true;
           break;
         }
       }
-      Assert.assertTrue(bFound);
+      assertTrue(bFound);
     }
 
   }
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/PathUtilsTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/PathUtilsTest.java
new file mode 100644 (file)
index 0000000..ffa8a10
--- /dev/null
@@ -0,0 +1,121 @@
+package org.opendaylight.controller.cluster.datastore.node.utils;
+
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.util.TestModel;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class PathUtilsTest {
+
+    @Test
+    public void getParentPath(){
+        assertEquals("", PathUtils.getParentPath("foobar"));
+        assertEquals("", PathUtils.getParentPath("/a"));
+        assertEquals("/a", PathUtils.getParentPath("/a/b"));
+        assertEquals("/a/b", PathUtils.getParentPath("/a/b/c"));
+        assertEquals("/a/b", PathUtils.getParentPath("a/b/c"));
+    }
+
+    @Test
+    public void toStringNodeIdentifier(){
+        YangInstanceIdentifier.PathArgument pathArgument = nodeIdentifier();
+
+        String expected = "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test";
+
+        assertEquals(expected , PathUtils.toString(pathArgument));
+    }
+
+    @Test
+    public void toStringAugmentationIdentifier(){
+        String expected = "AugmentationIdentifier{childNames=[(urn:opendaylight:flow:table:statistics?revision=2013-12-15)flow-table-statistics]}";
+
+        YangInstanceIdentifier.PathArgument pathArgument = augmentationIdentifier();
+
+        assertEquals(expected, PathUtils.toString(pathArgument));
+    }
+
+    @Test
+    public void toStringNodeWithValue(){
+
+        YangInstanceIdentifier.PathArgument pathArgument = nodeWithValue();
+
+        String expected = "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test[100]";
+
+        assertEquals(expected, PathUtils.toString(pathArgument));
+    }
+
+
+    @Test
+    public void toStringNodeIdentifierWithPredicates(){
+
+        YangInstanceIdentifier.PathArgument pathArgument = nodeIdentifierWithPredicates();
+
+        String expected = "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test[{(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)id=100}]";
+
+        assertEquals(expected, PathUtils.toString(pathArgument));
+    }
+
+    @Test
+    public void toStringYangInstanceIdentifier(){
+
+        YangInstanceIdentifier path =
+            YangInstanceIdentifier.create(nodeIdentifier())
+                .node(nodeIdentifierWithPredicates())
+                .node(augmentationIdentifier()).node(nodeWithValue());
+
+
+        String expected = "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test/" +
+            "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test[{(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)id=100}]/" +
+            "AugmentationIdentifier{childNames=[(urn:opendaylight:flow:table:statistics?revision=2013-12-15)flow-table-statistics]}/" +
+            "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test[100]";
+
+        assertEquals(expected, PathUtils.toString(path));
+
+    }
+
+    @Test
+    public void toYangInstanceIdentifier(){
+        String expected = "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test/" +
+            "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test[{(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)id=100}]/" +
+            "AugmentationIdentifier{childNames=[(urn:opendaylight:flow:table:statistics?revision=2013-12-15)flow-table-statistics]}/" +
+            "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test[100]";
+
+        YangInstanceIdentifier yangInstanceIdentifier =
+            PathUtils.toYangInstanceIdentifier(expected);
+
+        String actual = PathUtils.toString(yangInstanceIdentifier);
+
+        assertEquals(expected, actual);
+
+    }
+
+    private YangInstanceIdentifier.NodeIdentifier nodeIdentifier(){
+        return new YangInstanceIdentifier.NodeIdentifier(TestModel.TEST_QNAME);
+    }
+
+    private YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifier(){
+        Set<QName> childNames = new HashSet();
+        childNames.add(QNameFactory.create("(urn:opendaylight:flow:table:statistics?revision=2013-12-15)flow-table-statistics"));
+
+        return new YangInstanceIdentifier.AugmentationIdentifier(childNames);
+    }
+
+    private YangInstanceIdentifier.NodeWithValue nodeWithValue(){
+        return new YangInstanceIdentifier.NodeWithValue(TestModel.TEST_QNAME, Integer.valueOf(100));
+    }
+
+    private YangInstanceIdentifier.NodeIdentifierWithPredicates nodeIdentifierWithPredicates(){
+        Map<QName, Object> keys = new HashMap<>();
+
+        keys.put(TestModel.ID_QNAME, Integer.valueOf(100));
+
+        return new YangInstanceIdentifier.NodeIdentifierWithPredicates(TestModel.TEST_QNAME, keys);
+    }
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/QNameFactoryTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/QNameFactoryTest.java
new file mode 100644 (file)
index 0000000..76d4ceb
--- /dev/null
@@ -0,0 +1,29 @@
+package org.opendaylight.controller.cluster.datastore.node.utils;
+
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.util.TestModel;
+import org.opendaylight.yangtools.yang.common.QName;
+
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.TestCase.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+public class QNameFactoryTest {
+
+    @Test
+    public void testBasic(){
+        QName expected = TestModel.AUG_NAME_QNAME;
+        QName created = QNameFactory.create(expected.toString());
+
+        assertFalse( expected == created);
+
+        assertEquals(expected, created);
+
+        QName cached = QNameFactory.create(expected.toString());
+
+        assertEquals(expected, cached);
+
+        assertTrue( cached == created );
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/NormalizedNodeSerializerTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/NormalizedNodeSerializerTest.java
new file mode 100644 (file)
index 0000000..cdb2e69
--- /dev/null
@@ -0,0 +1,127 @@
+package org.opendaylight.controller.cluster.datastore.node.utils.serialization;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.opendaylight.controller.cluster.datastore.util.TestModel;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class NormalizedNodeSerializerTest {
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
+    @Test
+    public void testSerializeDeSerialize(){
+
+        // This test basically serializes and deSerializes a largish document
+        // which contains most of the types of nodes that go into a normalized
+        // node and uses several value types as well. It is in general a good
+        // sanity test which could be augmented with specific unit tests.
+
+        long start = System.nanoTime();
+
+        NormalizedNode<?, ?> expectedNode =
+            TestModel.createDocumentOne(TestModel.createTestContext());
+
+        NormalizedNodeMessages.Node expected = NormalizedNodeSerializer
+            .serialize(expectedNode);
+
+        System.out.println("Serialize Time = " + (System.nanoTime() - start)/1000000);
+
+        System.out.println("Serialized Size = " + expected.getSerializedSize());
+
+        System.out.println(expected.toString());
+
+        start = System.nanoTime();
+
+        NormalizedNode actualNode =
+            NormalizedNodeSerializer.deSerialize(expected);
+
+        System.out.println("DeSerialize Time = " + (System.nanoTime() - start)/1000000);
+
+        // Compare the original normalized node to the normalized node that was
+        // created by serializing the original node and deSerializing it back.
+        assertEquals(expectedNode, actualNode);
+
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testSerializeNullNormalizedNode(){
+        assertNotNull(NormalizedNodeSerializer.serialize(null));
+    }
+
+    @Test
+    public void testDeSerializeNullProtocolBufferNode(){
+        expectedException.expect(NullPointerException.class);
+        expectedException.expectMessage("node should not be null");
+
+        NormalizedNodeSerializer.deSerialize(null);
+    }
+
+    @Test
+    public void testDeSerializePathArgumentNullNode(){
+        expectedException.expect(NullPointerException.class);
+        expectedException.expectMessage("node should not be null");
+
+        NormalizedNodeSerializer
+            .deSerialize(null, NormalizedNodeMessages.PathArgument.getDefaultInstance());
+    }
+
+    @Test
+    public void testDeSerializePathArgumentNullPathArgument(){
+        expectedException.expect(NullPointerException.class);
+        expectedException.expectMessage("pathArgument should not be null");
+
+        NormalizedNodeSerializer.deSerialize(NormalizedNodeMessages.Node.getDefaultInstance() , null);
+    }
+
+    @Test
+    public void testDeSerializePathArgument(){
+
+        NormalizedNodeMessages.Node.Builder nodeBuilder = NormalizedNodeMessages.Node.newBuilder();
+
+        nodeBuilder.addCode("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test1");
+        nodeBuilder.addCode("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test");
+
+
+        nodeBuilder.addCode("2014-04-13");
+        nodeBuilder.addCode("2014-05-13");
+        nodeBuilder.addCode("2014-03-13");
+
+        nodeBuilder.addCode("dummy1");
+        nodeBuilder.addCode("dummy2");
+        nodeBuilder.addCode("dummy3");
+        nodeBuilder.addCode("capability");
+
+
+
+        NormalizedNodeMessages.PathArgument.Builder pathBuilder = NormalizedNodeMessages.PathArgument.newBuilder();
+
+        pathBuilder.setIntType(PathArgumentType.NODE_IDENTIFIER.ordinal());
+
+        NormalizedNodeMessages.QName.Builder qNameBuilder = NormalizedNodeMessages.QName.newBuilder();
+        qNameBuilder.setNamespace(1);
+        qNameBuilder.setRevision(4);
+        qNameBuilder.setLocalName(8);
+
+        pathBuilder.setNodeType(qNameBuilder);
+
+        YangInstanceIdentifier.PathArgument pathArgument =
+            NormalizedNodeSerializer
+                .deSerialize(nodeBuilder.build(), pathBuilder.build());
+
+        assertNotNull(pathArgument);
+
+        assertEquals("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test", pathArgument.getNodeType().getNamespace().toString());
+        assertEquals("2014-03-13", pathArgument.getNodeType().getFormattedRevision());
+        assertEquals("capability", pathArgument.getNodeType().getLocalName());
+    }
+
+
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/PathArgumentSerializerTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/PathArgumentSerializerTest.java
new file mode 100644 (file)
index 0000000..d1f21ee
--- /dev/null
@@ -0,0 +1,280 @@
+package org.opendaylight.controller.cluster.datastore.node.utils.serialization;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.opendaylight.controller.cluster.datastore.util.TestModel;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import java.net.URI;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class PathArgumentSerializerTest{
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
+    @Test
+    public void testSerializeNullContext(){
+        expectedException.expect(NullPointerException.class);
+        expectedException.expectMessage("context should not be null");
+
+        PathArgumentSerializer.serialize(null, mock(
+            YangInstanceIdentifier.PathArgument.class));
+    }
+
+    @Test
+    public void testSerializeNullPathArgument(){
+        expectedException.expect(NullPointerException.class);
+        expectedException.expectMessage("pathArgument should not be null");
+
+        PathArgumentSerializer.serialize(mock(
+            NormalizedNodeSerializationContext.class), null);
+
+    }
+
+    @Test
+    public void testDeSerializeNullContext(){
+        expectedException.expect(NullPointerException.class);
+        expectedException.expectMessage("context should not be null");
+
+        PathArgumentSerializer.deSerialize(null, NormalizedNodeMessages.PathArgument.getDefaultInstance());
+
+    }
+
+    @Test
+    public void testDeSerializeNullPathArgument(){
+        expectedException.expect(NullPointerException.class);
+        expectedException.expectMessage("pathArgument should not be null");
+
+        PathArgumentSerializer.deSerialize(mock(NormalizedNodeDeSerializationContext.class), null);
+
+    }
+
+    @Test
+    public void testSerializeNodeIdentifier(){
+        NormalizedNodeSerializationContext serializationContext =
+            mock(NormalizedNodeSerializationContext.class);
+
+        when(serializationContext.addLocalName(anyString())).thenReturn(5);
+        when(serializationContext.addNamespace(any(URI.class))).thenReturn(10);
+        when(serializationContext.addRevision(any(Date.class))).thenReturn(11);
+
+        NormalizedNodeMessages.PathArgument actual = PathArgumentSerializer
+            .serialize(serializationContext,
+                new YangInstanceIdentifier.NodeIdentifier(
+                    TestModel.TEST_QNAME));
+
+        assertEquals(PathArgumentType.NODE_IDENTIFIER.ordinal(), actual.getIntType());
+        assertEquals(5, actual.getNodeType().getLocalName());
+        assertEquals(10, actual.getNodeType().getNamespace());
+        assertEquals(11, actual.getNodeType().getRevision());
+
+
+    }
+
+    @Test
+    public void testSerializeNodeIdentifierWithValue(){
+        NormalizedNodeSerializationContext serializationContext =
+            mock(NormalizedNodeSerializationContext.class);
+
+        when(serializationContext.addLocalName(anyString())).thenReturn(5);
+        when(serializationContext.addNamespace(any(URI.class))).thenReturn(10);
+        when(serializationContext.addRevision(any(Date.class))).thenReturn(11);
+
+        NormalizedNodeMessages.PathArgument actual = PathArgumentSerializer
+            .serialize(serializationContext,
+                new YangInstanceIdentifier.NodeWithValue(
+                    TestModel.TEST_QNAME, "foo"));
+
+        assertEquals(PathArgumentType.NODE_IDENTIFIER_WITH_VALUE.ordinal(), actual.getIntType());
+        assertEquals(5, actual.getNodeType().getLocalName());
+        assertEquals(10, actual.getNodeType().getNamespace());
+        assertEquals(11, actual.getNodeType().getRevision());
+        assertEquals("foo", actual.getAttribute(0).getValue());
+
+
+    }
+
+    @Test
+    public void testSerializeNodeIdentifierWithPredicates(){
+        NormalizedNodeSerializationContext serializationContext =
+            mock(NormalizedNodeSerializationContext.class);
+
+
+        when(serializationContext.addLocalName("test")).thenReturn(5);
+        when(serializationContext.addLocalName("child-name")).thenReturn(55);
+
+        when(serializationContext.addNamespace(TestModel.TEST_QNAME.getNamespace())).thenReturn(
+            10);
+        when(serializationContext.addNamespace(TestModel.CHILD_NAME_QNAME.getNamespace())).thenReturn(66);
+
+        when(serializationContext.addRevision(TestModel.TEST_QNAME.getRevision())).thenReturn(
+            11);
+        when(serializationContext.addRevision(TestModel.CHILD_NAME_QNAME.getRevision())).thenReturn(77);
+
+        Map<QName, Object> predicates = new HashMap<>();
+
+        predicates.put(TestModel.CHILD_NAME_QNAME, "foobar");
+
+        NormalizedNodeMessages.PathArgument actual = PathArgumentSerializer
+            .serialize(serializationContext,
+                new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+                    TestModel.TEST_QNAME, predicates));
+
+        assertEquals(PathArgumentType.NODE_IDENTIFIER_WITH_PREDICATES.ordinal(), actual.getIntType());
+        assertEquals(5, actual.getNodeType().getLocalName());
+        assertEquals(10, actual.getNodeType().getNamespace());
+        assertEquals(11, actual.getNodeType().getRevision());
+
+        assertEquals(55, actual.getAttribute(0).getName().getLocalName());
+        assertEquals(66, actual.getAttribute(0).getName().getNamespace());
+        assertEquals(77, actual.getAttribute(0).getName().getRevision());
+
+        assertEquals("foobar", actual.getAttribute(0).getValue());
+
+
+    }
+
+    @Test
+    public void testSerializeAugmentationIdentifier(){
+        NormalizedNodeSerializationContext serializationContext =
+            mock(NormalizedNodeSerializationContext.class);
+
+        when(serializationContext.addLocalName(anyString())).thenReturn(55);
+        when(serializationContext.addNamespace(any(URI.class))).thenReturn(66);
+        when(serializationContext.addRevision(any(Date.class))).thenReturn(77);
+
+        NormalizedNodeMessages.PathArgument actual = PathArgumentSerializer
+            .serialize(serializationContext,
+                new YangInstanceIdentifier.AugmentationIdentifier(
+                    ImmutableSet.of(TestModel.TEST_QNAME)));
+
+        assertEquals(PathArgumentType.AUGMENTATION_IDENTIFIER.ordinal(), actual.getIntType());
+
+        assertEquals(55, actual.getAttribute(0).getName().getLocalName());
+        assertEquals(66, actual.getAttribute(0).getName().getNamespace());
+        assertEquals(77, actual.getAttribute(0).getName().getRevision());
+
+    }
+
+    @Test
+    public void testDeSerializeNodeIdentifier(){
+
+        NormalizedNodeMessages.Node.Builder nodeBuilder = NormalizedNodeMessages.Node.newBuilder();
+        NormalizedNodeMessages.PathArgument.Builder pathBuilder = NormalizedNodeMessages.PathArgument.newBuilder();
+        NormalizedNodeMessages.QName.Builder qNameBuilder = NormalizedNodeMessages.QName.newBuilder();
+
+        qNameBuilder.setNamespace(0);
+        qNameBuilder.setRevision(1);
+        qNameBuilder.setLocalName(2);
+
+        pathBuilder.setNodeType(qNameBuilder);
+        pathBuilder.setIntType(PathArgumentType.NODE_IDENTIFIER.ordinal());
+
+        nodeBuilder.addCode(TestModel.TEST_QNAME.getNamespace().toString());
+        nodeBuilder.addCode(TestModel.TEST_QNAME.getFormattedRevision());
+        nodeBuilder.addCode(TestModel.TEST_QNAME.getLocalName());
+
+        YangInstanceIdentifier.PathArgument pathArgument =
+            NormalizedNodeSerializer
+                .deSerialize(nodeBuilder.build(), pathBuilder.build());
+
+        assertEquals(new YangInstanceIdentifier.NodeIdentifier(TestModel.TEST_QNAME), pathArgument);
+
+    }
+
+    @Test
+    public void testDeSerializeNodeWithValue(){
+        NormalizedNodeMessages.Node.Builder nodeBuilder = NormalizedNodeMessages.Node.newBuilder();
+        NormalizedNodeMessages.PathArgument.Builder pathBuilder = NormalizedNodeMessages.PathArgument.newBuilder();
+        NormalizedNodeMessages.QName.Builder qNameBuilder = NormalizedNodeMessages.QName.newBuilder();
+
+        qNameBuilder.setNamespace(0);
+        qNameBuilder.setRevision(1);
+        qNameBuilder.setLocalName(2);
+
+        pathBuilder.setNodeType(qNameBuilder);
+        pathBuilder.setIntType(PathArgumentType.NODE_IDENTIFIER_WITH_VALUE.ordinal());
+        pathBuilder.addAttribute(
+            NormalizedNodeMessages.PathArgumentAttribute.newBuilder()
+                .setValue("foo").setType(ValueType.STRING_TYPE.ordinal()));
+
+        nodeBuilder.addCode(TestModel.TEST_QNAME.getNamespace().toString());
+        nodeBuilder.addCode(TestModel.TEST_QNAME.getFormattedRevision());
+        nodeBuilder.addCode(TestModel.TEST_QNAME.getLocalName());
+
+        YangInstanceIdentifier.PathArgument pathArgument =
+            NormalizedNodeSerializer
+                .deSerialize(nodeBuilder.build(), pathBuilder.build());
+
+        assertEquals(new YangInstanceIdentifier.NodeWithValue(TestModel.TEST_QNAME, "foo"), pathArgument);
+
+    }
+    @Test
+    public void testDeSerializeNodeIdentifierWithPredicates(){
+        NormalizedNodeMessages.Node.Builder nodeBuilder = NormalizedNodeMessages.Node.newBuilder();
+        NormalizedNodeMessages.PathArgument.Builder pathBuilder = NormalizedNodeMessages.PathArgument.newBuilder();
+        NormalizedNodeMessages.QName.Builder qNameBuilder = NormalizedNodeMessages.QName.newBuilder();
+
+        qNameBuilder.setNamespace(0);
+        qNameBuilder.setRevision(1);
+        qNameBuilder.setLocalName(2);
+
+        pathBuilder.setNodeType(qNameBuilder);
+        pathBuilder.setIntType(PathArgumentType.NODE_IDENTIFIER_WITH_PREDICATES.ordinal());
+        pathBuilder.addAttribute(NormalizedNodeMessages.PathArgumentAttribute.newBuilder().setName(qNameBuilder).setValue(
+            "foo").setType(ValueType.STRING_TYPE.ordinal()));
+
+        nodeBuilder.addCode(TestModel.TEST_QNAME.getNamespace().toString());
+        nodeBuilder.addCode(TestModel.TEST_QNAME.getFormattedRevision());
+        nodeBuilder.addCode(TestModel.TEST_QNAME.getLocalName());
+
+        YangInstanceIdentifier.PathArgument pathArgument =
+            NormalizedNodeSerializer
+                .deSerialize(nodeBuilder.build(), pathBuilder.build());
+
+        assertEquals(new YangInstanceIdentifier.NodeIdentifierWithPredicates(TestModel.TEST_QNAME,
+            ImmutableMap.<QName, Object>of(TestModel.TEST_QNAME, "foo")), pathArgument);
+
+    }
+    @Test
+    public void testDeSerializeNodeAugmentationIdentifier(){
+        NormalizedNodeMessages.Node.Builder nodeBuilder = NormalizedNodeMessages.Node.newBuilder();
+        NormalizedNodeMessages.PathArgument.Builder pathBuilder = NormalizedNodeMessages.PathArgument.newBuilder();
+        NormalizedNodeMessages.QName.Builder qNameBuilder = NormalizedNodeMessages.QName.newBuilder();
+
+        qNameBuilder.setNamespace(0);
+        qNameBuilder.setRevision(1);
+        qNameBuilder.setLocalName(2);
+
+        pathBuilder.setIntType(PathArgumentType.AUGMENTATION_IDENTIFIER.ordinal());
+        pathBuilder.addAttribute(NormalizedNodeMessages.PathArgumentAttribute.newBuilder().setName(qNameBuilder).setType(ValueType.STRING_TYPE.ordinal()));
+
+        nodeBuilder.addCode(TestModel.TEST_QNAME.getNamespace().toString());
+        nodeBuilder.addCode(TestModel.TEST_QNAME.getFormattedRevision());
+        nodeBuilder.addCode(TestModel.TEST_QNAME.getLocalName());
+
+        YangInstanceIdentifier.PathArgument pathArgument =
+            NormalizedNodeSerializer
+                .deSerialize(nodeBuilder.build(), pathBuilder.build());
+
+        assertEquals(new YangInstanceIdentifier.AugmentationIdentifier(ImmutableSet.of(TestModel.TEST_QNAME)), pathArgument);
+
+    }
+
+
+
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/ValueSerializerTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/serialization/ValueSerializerTest.java
new file mode 100644 (file)
index 0000000..af7a385
--- /dev/null
@@ -0,0 +1,449 @@
+package org.opendaylight.controller.cluster.datastore.node.utils.serialization;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.opendaylight.controller.cluster.datastore.util.TestModel;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+public class ValueSerializerTest{
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
+    @Test
+    public void testSerializeShort(){
+        short v1 = 5;
+        NormalizedNodeMessages.Node.Builder builder = NormalizedNodeMessages.Node.newBuilder();
+        ValueSerializer.serialize(builder, mock(NormalizedNodeSerializationContext.class), v1);
+
+        assertEquals(ValueType.SHORT_TYPE.ordinal(), builder.getIntValueType());
+        assertEquals("5", builder.getValue());
+
+        NormalizedNodeMessages.PathArgumentAttribute.Builder builder1 = NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
+
+        ValueSerializer.serialize(builder1, mock(NormalizedNodeSerializationContext.class), v1);
+
+        assertEquals(ValueType.SHORT_TYPE.ordinal(), builder1.getType());
+        assertEquals("5", builder.getValue());
+
+    }
+
+    @Test
+    public void testSerializeInteger(){
+        String hexNumber = "f3";
+
+        Integer expected = Integer.valueOf(hexNumber, 16);
+
+
+        NormalizedNodeMessages.Node.Builder builder = NormalizedNodeMessages.Node.newBuilder();
+        ValueSerializer.serialize(builder, mock(
+            NormalizedNodeSerializationContext.class), expected);
+
+        assertEquals(ValueType.INT_TYPE.ordinal(), builder.getIntValueType());
+        assertEquals("243", builder.getValue());
+
+        NormalizedNodeMessages.PathArgumentAttribute.Builder builder1 = NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
+
+        ValueSerializer.serialize(builder1, mock(
+            NormalizedNodeSerializationContext.class), expected);
+
+        assertEquals(ValueType.INT_TYPE.ordinal(), builder1.getType());
+        assertEquals("243", builder1.getValue());
+
+
+    }
+
+
+    @Test
+    public void testSerializeLong(){
+        long v1 = 5;
+        NormalizedNodeMessages.Node.Builder builder = NormalizedNodeMessages.Node.newBuilder();
+        ValueSerializer.serialize(builder, mock(
+            NormalizedNodeSerializationContext.class), v1);
+
+        assertEquals(ValueType.LONG_TYPE.ordinal(), builder.getIntValueType());
+        assertEquals("5", builder.getValue());
+
+        NormalizedNodeMessages.PathArgumentAttribute.Builder builder1 = NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
+
+        ValueSerializer.serialize(builder1, mock(
+            NormalizedNodeSerializationContext.class), v1);
+
+        assertEquals(ValueType.LONG_TYPE.ordinal(), builder1.getType());
+        assertEquals("5", builder1.getValue());
+
+    }
+
+    @Test
+    public void testSerializeByte(){
+        byte v1 = 5;
+        NormalizedNodeMessages.Node.Builder builder = NormalizedNodeMessages.Node.newBuilder();
+        ValueSerializer.serialize(builder, mock(
+            NormalizedNodeSerializationContext.class), v1);
+
+        assertEquals(ValueType.BYTE_TYPE.ordinal(), builder.getIntValueType());
+        assertEquals("5", builder.getValue());
+
+        NormalizedNodeMessages.PathArgumentAttribute.Builder builder1 = NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
+
+        ValueSerializer.serialize(builder1, mock(
+            NormalizedNodeSerializationContext.class), v1);
+
+        assertEquals(ValueType.BYTE_TYPE.ordinal(), builder1.getType());
+        assertEquals("5", builder1.getValue());
+
+    }
+
+    @Test
+    public void testSerializeBits(){
+        NormalizedNodeMessages.Node.Builder builder = NormalizedNodeMessages.Node.newBuilder();
+        ValueSerializer.serialize(builder, mock(
+            NormalizedNodeSerializationContext.class),
+            ImmutableSet.of("foo", "bar"));
+
+        assertEquals(ValueType.BITS_TYPE.ordinal(), builder.getIntValueType());
+        assertTrue( "foo not in bits", builder.getBitsValueList().contains("foo"));
+        assertTrue( "bar not in bits", builder.getBitsValueList().contains("bar"));
+
+        NormalizedNodeMessages.PathArgumentAttribute.Builder builder1 = NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
+
+        ValueSerializer.serialize(builder1, mock(
+            NormalizedNodeSerializationContext.class),
+            ImmutableSet.of("foo", "bar"));
+
+        assertEquals(ValueType.BITS_TYPE.ordinal(), builder1.getType());
+        assertEquals("[foo, bar]", builder1.getValue());
+
+    }
+
+    @Test
+    public void testSerializeWrongTypeOfSet(){
+        expectedException.expect(IllegalArgumentException.class);
+        expectedException.expectMessage("Expected value type to be Bits but was :");
+        NormalizedNodeMessages.Node.Builder builder = NormalizedNodeMessages.Node.newBuilder();
+        ValueSerializer.serialize(builder, mock(
+                NormalizedNodeSerializationContext.class),
+            ImmutableSet.of(1, 2));
+
+    }
+
+    @Test
+    public void testSerializeEmptyString(){
+        NormalizedNodeMessages.Node.Builder builder = NormalizedNodeMessages.Node.newBuilder();
+        ValueSerializer.serialize(builder, mock(
+            NormalizedNodeSerializationContext.class),"");
+
+        assertEquals(ValueType.STRING_TYPE.ordinal(), builder.getIntValueType());
+        assertEquals("", builder.getValue());
+
+        NormalizedNodeMessages.PathArgumentAttribute.Builder builder1 = NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
+
+        ValueSerializer.serialize(builder1, mock(
+            NormalizedNodeSerializationContext.class),"");
+
+        assertEquals(ValueType.STRING_TYPE.ordinal(), builder1.getType());
+        assertEquals("", builder1.getValue());
+
+    }
+
+    @Test
+    public void testSerializeString(){
+        NormalizedNodeMessages.Node.Builder builder = NormalizedNodeMessages.Node.newBuilder();
+        ValueSerializer.serialize(builder, mock(
+            NormalizedNodeSerializationContext.class),"foo");
+
+        assertEquals(ValueType.STRING_TYPE.ordinal(), builder.getIntValueType());
+        assertEquals("foo", builder.getValue());
+
+        NormalizedNodeMessages.PathArgumentAttribute.Builder builder1 = NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
+
+        ValueSerializer.serialize(builder1, mock(
+            NormalizedNodeSerializationContext.class),"foo");
+
+        assertEquals(ValueType.STRING_TYPE.ordinal(), builder1.getType());
+        assertEquals("foo", builder1.getValue());
+
+    }
+
+
+    @Test
+    public void testSerializeBoolean(){
+        boolean v1 = true;
+        NormalizedNodeMessages.Node.Builder builder = NormalizedNodeMessages.Node.newBuilder();
+        ValueSerializer.serialize(builder, mock(
+            NormalizedNodeSerializationContext.class), v1);
+
+        assertEquals(ValueType.BOOL_TYPE.ordinal(), builder.getIntValueType());
+        assertEquals("true", builder.getValue());
+
+        NormalizedNodeMessages.PathArgumentAttribute.Builder builder1 = NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
+        ValueSerializer.serialize(builder1, mock(
+            NormalizedNodeSerializationContext.class), v1);
+
+        assertEquals(ValueType.BOOL_TYPE.ordinal(), builder1.getType());
+        assertEquals("true", builder1.getValue());
+    }
+
+    @Test
+    public void testSerializeQName(){
+        QName v1 = TestModel.TEST_QNAME;
+        NormalizedNodeMessages.Node.Builder builder = NormalizedNodeMessages.Node.newBuilder();
+        ValueSerializer.serialize(builder, mock(
+            NormalizedNodeSerializationContext.class), v1);
+
+        assertEquals(ValueType.QNAME_TYPE.ordinal(), builder.getIntValueType());
+        assertEquals("(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test", builder.getValue());
+
+        NormalizedNodeMessages.PathArgumentAttribute.Builder builder1 = NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
+
+        ValueSerializer.serialize(builder1, mock(
+            NormalizedNodeSerializationContext.class), v1);
+
+        assertEquals(ValueType.QNAME_TYPE.ordinal(), builder1.getType());
+        assertEquals("(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test", builder1.getValue());
+
+    }
+
+    @Test
+    public void testSerializeYangIdentifier(){
+        YangInstanceIdentifier v1 = TestModel.TEST_PATH;
+
+        NormalizedNodeMessages.Node.Builder builder = NormalizedNodeMessages.Node.newBuilder();
+        ValueSerializer.serialize(builder, mock(
+            NormalizedNodeSerializationContext.class), v1);
+
+
+        assertEquals(ValueType.YANG_IDENTIFIER_TYPE.ordinal(), builder.getIntValueType());
+        NormalizedNodeMessages.InstanceIdentifier serializedYangInstanceIdentifier =
+            builder.getInstanceIdentifierValue();
+
+        assertEquals(1, serializedYangInstanceIdentifier.getArgumentsCount());
+        assertEquals(TestModel.TEST_QNAME.toString(), serializedYangInstanceIdentifier.getArguments(0).getNodeType().getValue());
+    }
+
+    @Test
+    public void testSerializeBigInteger(){
+        BigInteger v1 = new BigInteger("1000000000000000000000000");
+        NormalizedNodeMessages.Node.Builder builder = NormalizedNodeMessages.Node.newBuilder();
+        ValueSerializer.serialize(builder, mock(
+            NormalizedNodeSerializationContext.class), v1);
+
+        assertEquals(ValueType.BIG_INTEGER_TYPE.ordinal(), builder.getIntValueType());
+        assertEquals("1000000000000000000000000", builder.getValue());
+
+        NormalizedNodeMessages.PathArgumentAttribute.Builder builder1 = NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
+
+        ValueSerializer.serialize(builder1, mock(
+            NormalizedNodeSerializationContext.class), v1);
+
+        assertEquals(ValueType.BIG_INTEGER_TYPE.ordinal(), builder1.getType());
+        assertEquals("1000000000000000000000000", builder1.getValue());
+
+    }
+
+    @Test
+    public void testSerializeBigDecimal(){
+        BigDecimal v1 = new BigDecimal("1000000000000000000000000.51616");
+        NormalizedNodeMessages.Node.Builder builder = NormalizedNodeMessages.Node.newBuilder();
+        ValueSerializer.serialize(builder, mock(
+            NormalizedNodeSerializationContext.class), v1);
+
+        assertEquals(ValueType.BIG_DECIMAL_TYPE.ordinal(), builder.getIntValueType());
+        assertEquals("1000000000000000000000000.51616", builder.getValue());
+
+        NormalizedNodeMessages.PathArgumentAttribute.Builder builder1 = NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
+        ValueSerializer.serialize(builder1, mock(
+            NormalizedNodeSerializationContext.class), v1);
+
+        assertEquals(ValueType.BIG_DECIMAL_TYPE.ordinal(), builder1.getType());
+        assertEquals("1000000000000000000000000.51616", builder1.getValue());
+
+    }
+
+    @Test
+    public void testDeSerializeShort(){
+        NormalizedNodeMessages.Node.Builder nodeBuilder = NormalizedNodeMessages.Node.newBuilder();
+        nodeBuilder.setIntValueType(ValueType.SHORT_TYPE.ordinal());
+        nodeBuilder.setValue("25");
+
+        Object o = ValueSerializer
+            .deSerialize(mock(NormalizedNodeDeSerializationContext.class),
+                nodeBuilder.build());
+
+        assertTrue(o instanceof Short);
+        assertEquals(25, ((Short) o).shortValue());
+    }
+
+    @Test
+    public void testDeSerializeByte(){
+        NormalizedNodeMessages.Node.Builder nodeBuilder = NormalizedNodeMessages.Node.newBuilder();
+        nodeBuilder.setIntValueType(ValueType.BYTE_TYPE.ordinal());
+        nodeBuilder.setValue("25");
+
+        Object o = ValueSerializer
+            .deSerialize(mock(NormalizedNodeDeSerializationContext.class),
+                nodeBuilder.build());
+
+        assertTrue(o instanceof Byte);
+        assertEquals(25, ((Byte) o).byteValue());
+
+    }
+
+    @Test
+    public void testDeSerializeInteger(){
+        NormalizedNodeMessages.Node.Builder nodeBuilder = NormalizedNodeMessages.Node.newBuilder();
+        nodeBuilder.setIntValueType(ValueType.INT_TYPE.ordinal());
+        nodeBuilder.setValue("25");
+
+        Object o = ValueSerializer
+            .deSerialize(mock(NormalizedNodeDeSerializationContext.class),
+                nodeBuilder.build());
+
+        assertTrue(o instanceof Integer);
+        assertEquals(25, ((Integer) o).intValue());
+
+    }
+
+    @Test
+    public void testDeSerializeLong(){
+        NormalizedNodeMessages.Node.Builder nodeBuilder = NormalizedNodeMessages.Node.newBuilder();
+        nodeBuilder.setIntValueType(ValueType.LONG_TYPE.ordinal());
+        nodeBuilder.setValue("25");
+
+        Object o = ValueSerializer
+            .deSerialize(mock(NormalizedNodeDeSerializationContext.class),
+                nodeBuilder.build());
+
+        assertTrue(o instanceof Long);
+        assertEquals(25, ((Long) o).longValue());
+
+    }
+
+    @Test
+    public void testDeSerializeBoolean(){
+        NormalizedNodeMessages.Node.Builder nodeBuilder = NormalizedNodeMessages.Node.newBuilder();
+        nodeBuilder.setIntValueType(ValueType.BOOL_TYPE.ordinal());
+        nodeBuilder.setValue("false");
+
+        Object o = ValueSerializer
+            .deSerialize(mock(NormalizedNodeDeSerializationContext.class),
+                nodeBuilder.build());
+
+        assertTrue(o instanceof Boolean);
+        assertEquals(false, ((Boolean) o).booleanValue());
+
+    }
+
+    @Test
+    public void testDeSerializeQName(){
+        NormalizedNodeMessages.Node.Builder nodeBuilder = NormalizedNodeMessages.Node.newBuilder();
+        nodeBuilder.setIntValueType(ValueType.QNAME_TYPE.ordinal());
+        nodeBuilder.setValue(TestModel.TEST_QNAME.toString());
+
+        Object o = ValueSerializer
+            .deSerialize(mock(NormalizedNodeDeSerializationContext.class),
+                nodeBuilder.build());
+
+        assertTrue(o instanceof QName);
+        assertEquals(TestModel.TEST_QNAME, o);
+
+    }
+
+    @Test
+    public void testDeSerializeBits(){
+        NormalizedNodeMessages.Node.Builder nodeBuilder = NormalizedNodeMessages.Node.newBuilder();
+        nodeBuilder.setIntValueType(ValueType.BITS_TYPE.ordinal());
+        nodeBuilder.addAllBitsValue(ImmutableList.of("foo", "bar"));
+
+        Object o = ValueSerializer
+            .deSerialize(mock(NormalizedNodeDeSerializationContext.class),
+                nodeBuilder.build());
+
+        assertTrue(o instanceof Set);
+        assertTrue(((Set)o).contains("foo"));
+        assertTrue(((Set) o).contains("bar"));
+
+    }
+
+    @Test
+    public void testDeSerializeYangIdentifier(){
+        NormalizedNodeMessages.Node.Builder nodeBuilder = NormalizedNodeMessages.Node.newBuilder();
+        NormalizedNodeMessages.InstanceIdentifier.Builder idBuilder = NormalizedNodeMessages.InstanceIdentifier.newBuilder();
+        NormalizedNodeMessages.PathArgument.Builder pathBuilder = NormalizedNodeMessages.PathArgument.newBuilder();
+
+        pathBuilder.setValue(TestModel.TEST_QNAME.toString());
+        pathBuilder.setIntType(PathArgumentType.NODE_IDENTIFIER.ordinal());
+
+        idBuilder.addArguments(pathBuilder);
+
+        nodeBuilder.setIntValueType(ValueType.YANG_IDENTIFIER_TYPE.ordinal());
+        nodeBuilder.setInstanceIdentifierValue(idBuilder);
+
+        Object o = ValueSerializer
+            .deSerialize(mock(NormalizedNodeDeSerializationContext.class),
+                nodeBuilder.build());
+
+        assertTrue(o instanceof YangInstanceIdentifier);
+        assertEquals(TestModel.TEST_PATH, o);
+
+    }
+
+    @Test
+    public void testDeSerializeString(){
+        NormalizedNodeMessages.Node.Builder nodeBuilder = NormalizedNodeMessages.Node.newBuilder();
+        nodeBuilder.setIntValueType(ValueType.STRING_TYPE.ordinal());
+        nodeBuilder.setValue("25");
+
+        Object o = ValueSerializer
+            .deSerialize(mock(NormalizedNodeDeSerializationContext.class),
+                nodeBuilder.build());
+
+        assertTrue(o instanceof String);
+        assertEquals("25", o);
+
+    }
+
+    @Test
+    public void testDeSerializeBigInteger(){
+        NormalizedNodeMessages.Node.Builder nodeBuilder = NormalizedNodeMessages.Node.newBuilder();
+        nodeBuilder.setIntValueType(ValueType.BIG_INTEGER_TYPE.ordinal());
+        nodeBuilder.setValue("25");
+
+        Object o = ValueSerializer
+            .deSerialize(mock(NormalizedNodeDeSerializationContext.class),
+                nodeBuilder.build());
+
+        assertTrue(o instanceof BigInteger);
+        assertEquals(new BigInteger("25"), o);
+
+    }
+
+    @Test
+    public void testDeSerializeBigDecimal(){
+        NormalizedNodeMessages.Node.Builder nodeBuilder = NormalizedNodeMessages.Node.newBuilder();
+        nodeBuilder.setIntValueType(ValueType.BIG_DECIMAL_TYPE.ordinal());
+        nodeBuilder.setValue("25");
+
+        Object o = ValueSerializer
+            .deSerialize(mock(NormalizedNodeDeSerializationContext.class),
+                nodeBuilder.build());
+
+        assertTrue(o instanceof BigDecimal);
+        assertEquals(new BigDecimal("25"), o);
+
+    }
+
+}
index 3eeb06f93ca6cead53174dac1cd4f436b15fd46f..cda4b06e2926cf42bb8c975c8e4b7fd79a89b781 100644 (file)
 
 package org.opendaylight.controller.cluster.datastore.util;
 
+import com.google.common.collect.ImmutableSet;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
@@ -24,6 +26,7 @@ import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 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.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetEntryNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
@@ -355,12 +358,20 @@ public class TestModel {
     // Create augmentations
     MapEntryNode mapEntry = createAugmentedListEntry(1, "First Test");
 
+    // Create a bits leaf
+      NormalizedNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifier, Object, LeafNode<Object>>
+          myBits = Builders.leafBuilder().withNodeIdentifier(
+          new YangInstanceIdentifier.NodeIdentifier(
+              QName.create(TEST_QNAME, "my-bits"))).withValue(
+          ImmutableSet.of("foo", "bar"));
 
-    // Create the document
+
+      // Create the document
     return ImmutableContainerNodeBuilder
         .create()
         .withNodeIdentifier(
             new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME))
+        .withChild(myBits.build())
         .withChild(ImmutableNodes.leafNode(DESC_QNAME, DESC))
         .withChild(ImmutableNodes.leafNode(POINTER_QNAME, "pointer"))
         .withChild(
index 1e60803f05af52d965a3b927b2423bd22e023064..0f96c1002de540fa0071a4cb7d96710c591bfd23 100644 (file)
@@ -44,7 +44,8 @@ public class MeteredBoundedMailboxTest {
         actorSystem.eventStream().subscribe(mockReceiver.getRef(), DeadLetter.class);
 
 
-        final FiniteDuration TEN_SEC = new FiniteDuration(10, TimeUnit.SECONDS);
+        final FiniteDuration TWENTY_SEC = new FiniteDuration(20, TimeUnit.SECONDS);
+
         String boundedMailBox = actorSystem.name() + ".bounded-mailbox";
         ActorRef pingPongActor = actorSystem.actorOf(PingPongActor.props(lock).withMailbox(boundedMailBox),
                                                      "pingpongactor");
@@ -59,11 +60,11 @@ public class MeteredBoundedMailboxTest {
             pingPongActor.tell("ping", mockReceiver.getRef());
         }
 
-        mockReceiver.expectMsgClass(TEN_SEC, DeadLetter.class);
+        mockReceiver.expectMsgClass(TWENTY_SEC, DeadLetter.class);
 
         lock.unlock();
 
-        Object[] eleven = mockReceiver.receiveN(11, TEN_SEC);
+        Object[] eleven = mockReceiver.receiveN(11, TWENTY_SEC);
     }
 
     /**
@@ -89,8 +90,12 @@ public class MeteredBoundedMailboxTest {
         @Override
         public void onReceive(Object message) throws Exception {
             lock.lock();
-            if ("ping".equals(message))
-                getSender().tell("pong", getSelf());
+            try {
+                if ("ping".equals(message))
+                    getSender().tell("pong", getSelf());
+            } finally {
+                lock.unlock();
+            }
         }
     }
 }
\ No newline at end of file
index e4eca7b71738df8e06ec7bde21f0344160c68b40..246cc682cd7ae277f36e152392209c8577c3785d 100644 (file)
@@ -11,6 +11,27 @@ module odl-datastore-test {
     }
 
     container test {
+        leaf my-bits {
+            type bits {
+                bit ten-mb-hd;
+                bit ten-mb-fd;
+                bit hundred-mb-hd;
+                bit hundred-mb-fd;
+                bit one-gb-hd;
+                bit one-gb-fd;
+                bit ten-gb-fd;
+                bit forty-gb-fd;
+                bit hundred-gb-fd;
+                bit one-tb-fd;
+                bit other;
+                bit copper;
+                bit fiber;
+                bit autoeng;
+                bit pause;
+                bit pause-asym;
+            }
+        }
+
         leaf desc {
             type string;
         }
index a42a66aed14d48423101e0667dc10ad3760258b4..31b658d1d7ea6f618f8277e4c5d214124d4613d6 100644 (file)
   <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/05-clustering.xml.conf</file>
+                  <type>xml</type>
+                  <classifier>config</classifier>
+                </artifact>
+              </artifacts>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
   </build>
 </project>
index 5bf231dbe1ca31040565bad6b82d90201a4c0df2..05322137aafc2d62b6b18e548a419be91446aeeb 100644 (file)
@@ -1,5 +1,10 @@
 
 odl-cluster-data {
+  bounded-mailbox {
+    mailbox-type = "org.opendaylight.controller.common.actor.MeteredBoundedMailbox"
+    mailbox-capacity = 1000
+    mailbox-push-timeout-time = 100ms
+  }    
   akka {
     actor {
       provider = "akka.cluster.ClusterActorRefProvider"
@@ -25,7 +30,7 @@ odl-cluster-data {
     }
 
     cluster {
-      seed-nodes = ["akka.tcp://opendaylight-cluster-data@<CHANGE_ME>:2550"]
+      seed-nodes = ["akka.tcp://opendaylight-cluster-data@<CHANGE_SEED_IP>:2550"]
 
       auto-down-unreachable-after = 10s
     }
@@ -33,6 +38,11 @@ odl-cluster-data {
 }
 
 odl-cluster-rpc {
+  bounded-mailbox {
+    mailbox-type = "org.opendaylight.controller.common.actor.MeteredBoundedMailbox"
+    mailbox-capacity = 1000
+    mailbox-push-timeout-time = 100ms
+  }
   akka {
     actor {
       provider = "akka.cluster.ClusterActorRefProvider"
@@ -47,7 +57,7 @@ odl-cluster-rpc {
     }
 
     cluster {
-      seed-nodes = ["akka.tcp://opendaylight-cluster-rpc@<CHANGE_ME>:2551"]
+      seed-nodes = ["akka.tcp://opendaylight-cluster-rpc@<CHANGE_SEED_IP>:2551"]
 
       auto-down-unreachable-after = 10s
     }
index 940559ef895bf9cec406eee2fbe73a7617da581a..32e32f94eb34e59d5b956095235883a717d3f95b 100644 (file)
@@ -10,39 +10,114 @@ package org.opendaylight.controller.md.sal.common.api.data;
 import org.opendaylight.yangtools.concepts.Path;
 
 /**
- * A chain of transactions. Transactions in a chain need to be committed in sequence and each
- * transaction should see the effects of previous transactions as if they happened. A chain
- * makes no guarantees of atomicity, in fact transactions are committed as soon as possible.
+ * A chain of transactions. Transactions in a chain need to be committed in
+ * sequence and each transaction should see the effects of previous committed transactions
+ * as they occurred. A chain makes no guarantees of atomicity across the chained transactions -
+ * the transactions are committed as soon as possible in the order that they were submitted.
  *
+ * This behaviour is different from the default AsyncDataBroker, where a
+ * transaction is always created from the current global state, not taking into
+ * account any transactions previously committed by the calling thread. Due to
+ * the asynchronous nature of transaction submission this can lead to surprising
+ * results. If a thread executes the following sequence sufficiently quickly:
+ *
+ * AsyncWriteTransaction t1 = broker.newWriteOnlyTransaction();
+ * t1.put(id, data);
+ * t1.submit();
+ *
+ * AsyncReadTransaction t2 = broker.newReadOnlyTransaction();
+ * Optional<?> maybeData = t2.read(id).get();
+ *
+ * it may happen, that it sees maybeData.isPresent() == false, simply because
+ * t1 has not completed the processes of being applied and t2 is actually
+ * allocated from the previous state. This is obviously bad for users who create
+ * incremental state in the datastore and actually read what they write in
+ * subsequent transactions.
+ *
+ * Using a TransactionChain instead of a broker solves this particular problem,
+ * and leads to expected behavior: t2 will always see the data written in t1
+ * present.
  */
-public interface TransactionChain<P extends Path<P>, D> extends AutoCloseable, AsyncDataTransactionFactory<P, D> {
+public interface TransactionChain<P extends Path<P>, D> extends AutoCloseable,
+        AsyncDataTransactionFactory<P, D> {
 
     /**
      * Create a new read only transaction which will continue the chain.
-     * The previous read-write transaction has to be either COMMITED or CANCELLED.
+     *
+     * <p>
+     * The previous write transaction has to be either SUBMITTED
+     * ({@link AsyncWriteTransaction#submit submit} was invoked) or CANCELLED
+     * ({@link #close close} was invoked).
+     * <p>
+     * The returned read-only transaction presents an isolated view of the data if the previous
+     * write transaction was successful - in other words, this read-only transaction will see the
+     * state changes made by the previous write transaction in the chain. However, state which
+     * was introduced by other transactions outside this transaction chain after creation of
+     * the previous transaction is not visible.
      *
      * @return New transaction in the chain.
-     * @throws IllegalStateException if the previous transaction was not COMMITED
-     *    or CANCELLED.
-     * @throws TransactionChainClosedException if the chain has been closed.
+     * @throws IllegalStateException
+     *             if the previous transaction was not SUBMITTED or CANCELLED.
+     * @throws TransactionChainClosedException
+     *             if the chain has been closed.
      */
     @Override
     public AsyncReadOnlyTransaction<P, D> newReadOnlyTransaction();
 
-
     /**
-     * Create a new read write transaction which will continue the chain.
-     * The previous read-write transaction has to be either COMMITED or CANCELLED.
+     * Create a new read-write transaction which will continue the chain.
+     *
+     * <p>
+     * The previous write transaction has to be either SUBMITTED
+     * ({@link AsyncWriteTransaction#submit submit} was invoked) or CANCELLED
+     * ({@link #close close} was invoked).
+     * <p>
+     * The returned read-write transaction presents an isolated view of the data if the previous
+     * write transaction was successful - in other words, this read-write transaction will see the
+     * state changes made by the previous write transaction in the chain. However, state which
+     * was introduced by other transactions outside this transaction chain after creation of
+     * the previous transaction is not visible.
+     * <p>
+     * Committing this read-write transaction using {@link AsyncWriteTransaction#submit submit}
+     * will submit the state changes in this transaction to be visible to any subsequent
+     * transaction in this chain and also to any transaction outside this chain.
      *
      * @return New transaction in the chain.
-     * @throws IllegalStateException if the previous transaction was not COMMITTED
-     *    or CANCELLED.
-     * @throws TransactionChainClosedException if the chain has been closed.
+     * @throws IllegalStateException
+     *             if the previous transaction was not SUBMITTED or CANCELLED.
+     * @throws TransactionChainClosedException
+     *             if the chain has been closed.
      */
     @Override
     public AsyncReadWriteTransaction<P, D> newReadWriteTransaction();
 
+    /**
+     * Create a new write-only transaction which will continue the chain.
+     *
+     * <p>
+     * The previous write transaction has to be either SUBMITTED
+     * ({@link AsyncWriteTransaction#submit submit} was invoked) or CANCELLED
+     * ({@link #close close} was invoked).
+     * <p>
+     * The returned write-only transaction presents an isolated view of the data if the previous
+     * write transaction was successful - in other words, this write-only transaction will see the
+     * state changes made by the previous write transaction in the chain. However, state which
+     * was introduced by other transactions outside this transaction chain after creation of
+     * the previous transaction is not visible.
+     * <p>
+     * Committing this write-only transaction using {@link AsyncWriteTransaction#submit submit}
+     * will submit the state changes in this transaction to be visible to any subsequent
+     * transaction in this chain and also to any transaction outside this chain.
+     *
+     * @return New transaction in the chain.
+     * @throws IllegalStateException
+     *             if the previous transaction was not SUBMITTED or CANCELLED.
+     * @throws TransactionChainClosedException
+     *             if the chain has been closed.
+     */
+    @Override
+    public AsyncWriteTransaction<P, D> newWriteOnlyTransaction();
+
     @Override
     void close();
 }
-
index 94d21f5fd6bb02736a360592dc6826a3c70e4ae4..470e6110047adb93014455ae679dc8126b7e1dd3 100644 (file)
@@ -13,6 +13,7 @@ import org.opendaylight.yangtools.concepts.Path;
  * Interface for creating transaction chains.
  */
 public interface TransactionChainFactory<P extends Path<P>, D> {
+
     /**
      * Create a new transaction chain. The chain will be initialized to read
      * from its backing datastore, with no outstanding transaction. Listener
diff --git a/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/AbstractMXBean.java b/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/AbstractMXBean.java
new file mode 100644 (file)
index 0000000..a2db29d
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * 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.util.jmx;
+
+import java.lang.management.ManagementFactory;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Abstract base for an MXBean implementation class.
+ * <p>
+ * This class is not intended for use outside of MD-SAL and its part of private
+ * implementation (still exported as public to be reused across MD-SAL implementation
+ * components) and may be removed in subsequent
+ * releases.
+ *
+ * @author Thomas Pantelis
+ */
+@Beta
+public abstract class AbstractMXBean {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractMXBean.class);
+
+    public static String BASE_JMX_PREFIX = "org.opendaylight.controller:";
+
+    private final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+
+    private final String mBeanName;
+    private final String mBeanType;
+    private final String mBeanCategory;
+
+    /**
+     * Constructor.
+     *
+     * @param mBeanName Used as the <code>name</code> property in the bean's ObjectName.
+     * @param mBeanType Used as the <code>type</code> property in the bean's ObjectName.
+     * @param mBeanCategory Used as the <code>Category</code> property in the bean's ObjectName.
+     */
+    protected AbstractMXBean(@Nonnull String mBeanName, @Nonnull String mBeanType,
+            @Nullable String mBeanCategory) {
+        this.mBeanName = mBeanName;
+        this.mBeanType = mBeanType;
+        this.mBeanCategory = mBeanCategory;
+    }
+
+    private ObjectName getMBeanObjectName() throws MalformedObjectNameException {
+        StringBuilder builder = new StringBuilder(BASE_JMX_PREFIX)
+                .append("type=").append(getMBeanType());
+
+        if(getMBeanCategory() != null) {
+            builder.append(",Category=").append(getMBeanCategory());
+        }
+
+        builder.append(",name=").append(getMBeanName());
+        return new ObjectName(builder.toString());
+    }
+
+    /**
+     * Registers this bean with the platform MBean server with the domain defined by
+     * {@link #BASE_JMX_PREFIX}.
+     *
+     * @return true is successfully registered, false otherwise.
+     */
+    public boolean registerMBean() {
+        boolean registered = false;
+        try {
+            // Object to identify MBean
+            final ObjectName mbeanName = this.getMBeanObjectName();
+
+            LOG.debug("Register MBean {}", mbeanName);
+
+            // unregistered if already registered
+            if(server.isRegistered(mbeanName)) {
+
+                LOG.debug("MBean {} found to be already registered", mbeanName);
+
+                try {
+                    unregisterMBean(mbeanName);
+                } catch(Exception e) {
+
+                    LOG.warn("unregister mbean {} resulted in exception {} ", mbeanName, e);
+                }
+            }
+            server.registerMBean(this, mbeanName);
+            registered = true;
+
+            LOG.debug("MBean {} registered successfully", mbeanName.getCanonicalName());
+        } catch(Exception e) {
+
+            LOG.error("registration failed {}", e);
+
+        }
+        return registered;
+    }
+
+    /**
+     * Unregisters this bean with the platform MBean server.
+     *
+     * @return true is successfully unregistered, false otherwise.
+     */
+    public boolean unregisterMBean() {
+        boolean unregister = false;
+        try {
+            ObjectName mbeanName = this.getMBeanObjectName();
+            unregisterMBean(mbeanName);
+            unregister = true;
+        } catch(Exception e) {
+
+            LOG.error("Failed when unregistering MBean {}", e);
+        }
+
+        return unregister;
+    }
+
+    private void unregisterMBean(ObjectName mbeanName) throws MBeanRegistrationException,
+            InstanceNotFoundException {
+        server.unregisterMBean(mbeanName);
+    }
+
+    /**
+     * Returns the <code>name</code> property of the bean's ObjectName.
+     */
+    public String getMBeanName() {
+        return mBeanName;
+    }
+
+    /**
+     * Returns the <code>type</code> property of the bean's ObjectName.
+     */
+    public String getMBeanType() {
+        return mBeanType;
+    }
+
+    /**
+     * Returns the <code>Category</code> property of the bean's ObjectName.
+     */
+    public String getMBeanCategory() {
+        return mBeanCategory;
+    }
+}
diff --git a/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/QueuedNotificationManagerMXBean.java b/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/QueuedNotificationManagerMXBean.java
new file mode 100644 (file)
index 0000000..9646adc
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.util.jmx;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.util.concurrent.ListenerNotificationQueueStats;
+
+/**
+ * MXBean interface for {@link QueuedNotificationManager} statistic metrics.
+ *
+ * @author Thomas Pantelis
+ */
+public interface QueuedNotificationManagerMXBean {
+
+    /**
+     * Returns a list of stat instances for each current listener notification task in progress.
+     */
+    List<ListenerNotificationQueueStats> getCurrentListenerQueueStats();
+
+    /**
+     * Returns the configured maximum listener queue size.
+     */
+    int getMaxListenerQueueSize();
+}
diff --git a/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/QueuedNotificationManagerMXBeanImpl.java b/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/QueuedNotificationManagerMXBeanImpl.java
new file mode 100644 (file)
index 0000000..e6148fc
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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.util.jmx;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.util.concurrent.ListenerNotificationQueueStats;
+import org.opendaylight.yangtools.util.concurrent.QueuedNotificationManager;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * Implementation of the QueuedNotificationManagerMXBean interface.
+ *
+ * <p>
+ * This class is not intended for use outside of MD-SAL and its part of private
+ * implementation (still exported as public to be reused across MD-SAL implementation
+ * components) and may be removed in subsequent
+ * releases.
+ *
+ * @author Thomas Pantelis
+ */
+public class QueuedNotificationManagerMXBeanImpl extends AbstractMXBean
+                                                 implements QueuedNotificationManagerMXBean {
+
+    private final QueuedNotificationManager<?,?> manager;
+
+    public QueuedNotificationManagerMXBeanImpl( QueuedNotificationManager<?,?> manager,
+            String mBeanName, String mBeanType, String mBeanCategory ) {
+        super(mBeanName, mBeanType, mBeanCategory);
+        this.manager = Preconditions.checkNotNull( manager );
+    }
+
+    @Override
+    public List<ListenerNotificationQueueStats> getCurrentListenerQueueStats() {
+        return manager.getListenerNotificationQueueStats();
+    }
+
+    @Override
+    public int getMaxListenerQueueSize() {
+        return manager.getMaxQueueCapacity();
+    }
+
+    public QueuedNotificationManagerStats toQueuedNotificationManagerStats() {
+        return new QueuedNotificationManagerStats( getMaxListenerQueueSize(),
+                getCurrentListenerQueueStats() );
+    }
+}
diff --git a/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/QueuedNotificationManagerStats.java b/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/QueuedNotificationManagerStats.java
new file mode 100644 (file)
index 0000000..c6e5006
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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.util.jmx;
+
+import java.beans.ConstructorProperties;
+import java.util.List;
+
+import org.opendaylight.yangtools.util.concurrent.ListenerNotificationQueueStats;
+
+/**
+ * A bean class that holds various QueuedNotificationManager statistic metrics. This class is
+ * suitable for mapping to the MXBean CompositeDataSupport type.
+ *
+ * <p>
+ * This class is not intended for use outside of MD-SAL and its part of private
+ * implementation (still exported as public to be reused across MD-SAL implementation
+ * components) and may be removed in subsequent
+ * releases.
+ * @author Thomas Pantelis
+ * @see QueuedNotificationManagerMXBeanImpl
+ */
+public class QueuedNotificationManagerStats {
+
+    private final int maxListenerQueueSize;
+    private final List<ListenerNotificationQueueStats> currentListenerQueueStats;
+
+    @ConstructorProperties({"maxListenerQueueSize","currentListenerQueueStats"})
+    public QueuedNotificationManagerStats( int maxListenerQueueSize,
+            List<ListenerNotificationQueueStats> currentListenerQueueStats ) {
+        super();
+        this.maxListenerQueueSize = maxListenerQueueSize;
+        this.currentListenerQueueStats = currentListenerQueueStats;
+    }
+
+    public List<ListenerNotificationQueueStats> getCurrentListenerQueueStats() {
+        return currentListenerQueueStats;
+    }
+
+    public int getMaxListenerQueueSize() {
+        return maxListenerQueueSize;
+    }
+}
diff --git a/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/ThreadExecutorStats.java b/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/ThreadExecutorStats.java
new file mode 100644 (file)
index 0000000..0a766c0
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * 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.util.jmx;
+
+import java.beans.ConstructorProperties;
+
+/**
+ * A bean class that holds various thread executor statistic metrics. This class is suitable for
+ * mapping to the MXBean CompositeDataSupport type;
+ *
+ * @author Thomas Pantelis
+ * @see ThreadExecutorStatsMXBeanImpl
+ */
+public class ThreadExecutorStats {
+
+    private final long activeThreadCount;
+    private final long completedTaskCount;
+    private final long currentQueueSize;
+    private final long maxThreadPoolSize;
+    private final long totalTaskCount;
+    private final long largestThreadPoolSize;
+    private final long maxQueueSize;
+    private final long currentThreadPoolSize;
+
+    // The following fields are defined as Long because they may be null if we can't a value
+    // from the underlying executor.
+    private final Long largestQueueSize;
+    private final Long rejectedTaskCount;
+
+    @ConstructorProperties({"activeThreadCount","currentThreadPoolSize","largestThreadPoolSize",
+        "maxThreadPoolSize","currentQueueSize","largestQueueSize","maxQueueSize",
+        "completedTaskCount","totalTaskCount","rejectedTaskCount"})
+    public ThreadExecutorStats(long activeThreadCount, long currentThreadPoolSize,
+            long largestThreadPoolSize, long maxThreadPoolSize, long currentQueueSize,
+            Long largestQueueSize, long maxQueueSize, long completedTaskCount,
+            long totalTaskCount, Long rejectedTaskCount) {
+        this.activeThreadCount = activeThreadCount;
+        this.currentThreadPoolSize = currentThreadPoolSize;
+        this.largestQueueSize = largestQueueSize;
+        this.largestThreadPoolSize = largestThreadPoolSize;
+        this.maxThreadPoolSize = maxThreadPoolSize;
+        this.currentQueueSize = currentQueueSize;
+        this.maxQueueSize = maxQueueSize;
+        this.completedTaskCount = completedTaskCount;
+        this.totalTaskCount = totalTaskCount;
+        this.rejectedTaskCount = rejectedTaskCount;
+    }
+
+    public long getActiveThreadCount() {
+        return activeThreadCount;
+    }
+
+    public long getCompletedTaskCount() {
+        return completedTaskCount;
+    }
+
+    public Long getRejectedTaskCount() {
+        return rejectedTaskCount;
+    }
+
+    public long getCurrentQueueSize() {
+        return currentQueueSize;
+    }
+
+    public Long getLargestQueueSize() {
+        return largestQueueSize;
+    }
+
+    public long getMaxThreadPoolSize() {
+        return maxThreadPoolSize;
+    }
+
+    public long getTotalTaskCount() {
+        return totalTaskCount;
+    }
+
+    public long getLargestThreadPoolSize() {
+        return largestThreadPoolSize;
+    }
+
+    public long getMaxQueueSize() {
+        return maxQueueSize;
+    }
+
+    public long getCurrentThreadPoolSize() {
+        return currentThreadPoolSize;
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/ThreadExecutorStatsMXBean.java b/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/ThreadExecutorStatsMXBean.java
new file mode 100644 (file)
index 0000000..d30bf88
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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.util.jmx;
+
+/**
+ * MXBean interface for thread executor statistic metrics.
+ *
+ * @author Thomas Pantelis
+ */
+public interface ThreadExecutorStatsMXBean {
+
+    /**
+     * Returns the current thread pool size.
+     */
+    long getCurrentThreadPoolSize();
+
+    /**
+     * Returns the largest thread pool size.
+     */
+    long getLargestThreadPoolSize();
+
+    /**
+     * Returns the maximum thread pool size.
+     */
+    long getMaxThreadPoolSize();
+
+    /**
+     * Returns the current queue size.
+     */
+    long getCurrentQueueSize();
+
+    /**
+     * Returns the largest queue size, if available.
+     */
+    Long getLargestQueueSize();
+
+    /**
+     * Returns the maximum queue size.
+     */
+    long getMaxQueueSize();
+
+    /**
+     * Returns the active thread count.
+     */
+    long getActiveThreadCount();
+
+    /**
+     * Returns the completed task count.
+     */
+    long getCompletedTaskCount();
+
+    /**
+     * Returns the total task count.
+     */
+    long getTotalTaskCount();
+
+    /**
+     * Returns the rejected task count, if available.
+     */
+    Long getRejectedTaskCount();
+}
diff --git a/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/ThreadExecutorStatsMXBeanImpl.java b/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/md/sal/common/util/jmx/ThreadExecutorStatsMXBeanImpl.java
new file mode 100644 (file)
index 0000000..b67855d
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * 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.util.jmx;
+
+import com.google.common.base.Preconditions;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadPoolExecutor;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.util.concurrent.CountingRejectedExecutionHandler;
+import org.opendaylight.yangtools.util.concurrent.TrackingLinkedBlockingQueue;
+
+/**
+ * MXBean implementation of the ThreadExecutorStatsMXBean interface that retrieves statistics
+ * from a backing {@link java.util.concurrent.ExecutorService}.
+ *
+ * @author Thomas Pantelis
+ */
+public class ThreadExecutorStatsMXBeanImpl extends AbstractMXBean
+                                           implements ThreadExecutorStatsMXBean {
+
+    private final ThreadPoolExecutor executor;
+
+    /**
+     * Constructs an instance for the given {@link Executor}.
+     *
+     * @param executor the backing {@link Executor}
+     * @param mBeanName Used as the <code>name</code> property in the bean's ObjectName.
+     * @param mBeanType Used as the <code>type</code> property in the bean's ObjectName.
+     * @param mBeanCategory Used as the <code>Category</code> property in the bean's ObjectName.
+     */
+    public ThreadExecutorStatsMXBeanImpl(Executor executor, String mBeanName,
+            String mBeanType, @Nullable String mBeanCategory) {
+        super(mBeanName, mBeanType, mBeanCategory);
+
+        Preconditions.checkArgument(executor instanceof ThreadPoolExecutor,
+                "The ExecutorService of type {} is not an instanceof ThreadPoolExecutor",
+                executor.getClass());
+        this.executor = (ThreadPoolExecutor)executor;
+    }
+
+    @Override
+    public long getCurrentThreadPoolSize() {
+        return executor.getPoolSize();
+    }
+
+    @Override
+    public long getLargestThreadPoolSize() {
+        return  executor.getLargestPoolSize();
+    }
+
+    @Override
+    public long getMaxThreadPoolSize() {
+        return executor.getMaximumPoolSize();
+    }
+
+    @Override
+    public long getCurrentQueueSize() {
+        return executor.getQueue().size();
+    }
+
+    @Override
+    public Long getLargestQueueSize() {
+        BlockingQueue<Runnable> queue = executor.getQueue();
+        if(queue instanceof TrackingLinkedBlockingQueue) {
+            return Long.valueOf(((TrackingLinkedBlockingQueue<?>)queue).getLargestQueueSize());
+        }
+
+        return null;
+    }
+
+    @Override
+    public long getMaxQueueSize() {
+        long queueSize = executor.getQueue().size();
+        return executor.getQueue().remainingCapacity() + queueSize;
+    }
+
+    @Override
+    public long getActiveThreadCount() {
+        return executor.getActiveCount();
+    }
+
+    @Override
+    public long getCompletedTaskCount() {
+        return  executor.getCompletedTaskCount();
+    }
+
+    @Override
+    public long getTotalTaskCount() {
+        return executor.getTaskCount();
+    }
+
+    @Override
+    public Long getRejectedTaskCount() {
+        RejectedExecutionHandler rejectedHandler = executor.getRejectedExecutionHandler();
+        if(rejectedHandler instanceof CountingRejectedExecutionHandler) {
+            return Long.valueOf(((CountingRejectedExecutionHandler)rejectedHandler)
+                                                                     .getRejectedTaskCount());
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns a {@link ThreadExecutorStats} instance containing a snapshot of the statistic
+     * metrics.
+     */
+    public ThreadExecutorStats toThreadExecutorStats() {
+        return new ThreadExecutorStats(getActiveThreadCount(), getCurrentThreadPoolSize(),
+                getLargestThreadPoolSize(), getMaxThreadPoolSize(), getCurrentQueueSize(),
+                getLargestQueueSize(), getMaxQueueSize(), getCompletedTaskCount(),
+                getTotalTaskCount(), getRejectedTaskCount());
+    }
+}
index 9c5129d6a4eb932f764a158530e304808dbb375d..31b0bb80c05ca221fc865b6d8de467a4e43ebac8 100644 (file)
       <dependency>
           <groupId>com.codahale.metrics</groupId>
           <artifactId>metrics-core</artifactId>
-          <version>3.0.1</version>
+      </dependency>
+
+      <dependency>
+          <groupId>com.codahale.metrics</groupId>
+          <artifactId>metrics-graphite</artifactId>
       </dependency>
     <!-- Test Dependencies -->
     <dependency>
         <configuration>
           <includes>
             <include>org.opendaylight.controller.*</include>
+
           </includes>
+          <excludes>
+              <exclude>org.opendaylight.controller.config.yang.config.*</exclude>
+          </excludes>
           <check>false</check>
         </configuration>
         <executions>
index 36c0447b6e90d35c8f54f8844cf762c3fc0e1897..2e822f1d437f4328be6c5b4a39a82380247b3bdf 100644 (file)
@@ -13,7 +13,7 @@ import com.google.protobuf.GeneratedMessage;
 import com.google.protobuf.InvalidProtocolBufferException;
 import com.google.protobuf.UnknownFieldSet;
 import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
-import org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages;
+import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
 import org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages;
 
 import java.io.Serializable;
index 1dab285679474378b47c1c0a1c488ebf89d66fea..b3283a18b1baaf4c3c7530570b8ae8a09512211f 100644 (file)
@@ -10,7 +10,9 @@ package org.opendaylight.controller.cluster.datastore;
 
 import akka.actor.Props;
 import akka.japi.Creator;
+
 import com.google.common.base.Preconditions;
+
 import org.opendaylight.controller.cluster.datastore.messages.DataChanged;
 import org.opendaylight.controller.cluster.datastore.messages.DataChangedReply;
 import org.opendaylight.controller.cluster.datastore.messages.EnableNotification;
@@ -18,20 +20,14 @@ import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
 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;
 
 public class DataChangeListener extends AbstractUntypedActor {
     private final AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> listener;
-    private final SchemaContext schemaContext;
-    private final YangInstanceIdentifier pathId;
-    private boolean notificationsEnabled = false;
+    private volatile boolean notificationsEnabled = false;
 
-    public DataChangeListener(SchemaContext schemaContext,
-                              AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> listener, YangInstanceIdentifier pathId) {
-
-        this.schemaContext = Preconditions.checkNotNull(schemaContext, "schemaContext should not be null");
+    public DataChangeListener(AsyncDataChangeListener<YangInstanceIdentifier,
+                                                      NormalizedNode<?, ?>> listener) {
         this.listener = Preconditions.checkNotNull(listener, "listener should not be null");
-        this.pathId  = Preconditions.checkNotNull(pathId, "pathId should not be null");
     }
 
     @Override public void handleReceive(Object message) throws Exception {
@@ -63,14 +59,24 @@ public class DataChangeListener extends AbstractUntypedActor {
         }
     }
 
-    public static Props props(final SchemaContext schemaContext, final AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> listener, final YangInstanceIdentifier pathId) {
-        return Props.create(new Creator<DataChangeListener>() {
-            @Override
-            public DataChangeListener create() throws Exception {
-                return new DataChangeListener(schemaContext,listener,pathId );
-            }
+    public static Props props(final AsyncDataChangeListener<YangInstanceIdentifier,
+                                                            NormalizedNode<?, ?>> listener) {
+        return Props.create(new DataChangeListenerCreator(listener));
+    }
+
+    private static class DataChangeListenerCreator implements Creator<DataChangeListener> {
+        private static final long serialVersionUID = 1L;
+
+        final AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> listener;
 
-        });
+        DataChangeListenerCreator(
+                AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> listener) {
+            this.listener = listener;
+        }
 
+        @Override
+        public DataChangeListener create() throws Exception {
+            return new DataChangeListener(listener);
+        }
     }
 }
index 6d835498afa2af24ec915e3b010e67710f685d51..a1b6b9252eb452082f101fe1bb748fb2d6b28536 100644 (file)
@@ -9,7 +9,9 @@
 package org.opendaylight.controller.cluster.datastore;
 
 import akka.actor.ActorSelection;
+
 import com.google.common.base.Preconditions;
+
 import org.opendaylight.controller.cluster.datastore.messages.DataChanged;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
@@ -24,13 +26,13 @@ public class DataChangeListenerProxy implements AsyncDataChangeListener<YangInst
     private final ActorSelection dataChangeListenerActor;
     private final SchemaContext schemaContext;
 
-    public DataChangeListenerProxy(SchemaContext schemaContext,ActorSelection dataChangeListenerActor) {
+    public DataChangeListenerProxy(SchemaContext schemaContext, ActorSelection dataChangeListenerActor) {
         this.dataChangeListenerActor = Preconditions.checkNotNull(dataChangeListenerActor, "dataChangeListenerActor should not be null");
         this.schemaContext = schemaContext;
     }
 
     @Override public void onDataChanged(
         AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
-        dataChangeListenerActor.tell(new DataChanged(schemaContext,change), null);
+        dataChangeListenerActor.tell(new DataChanged(schemaContext, change), null);
     }
 }
index 9e50b5b332babf4bcc033aeea3778fed850681d3..818f73392d1d880ad0dde5d84704c1e4c9d15c17 100644 (file)
@@ -11,19 +11,21 @@ package org.opendaylight.controller.cluster.datastore;
 import akka.actor.PoisonPill;
 import akka.actor.Props;
 import akka.japi.Creator;
+
 import org.opendaylight.controller.cluster.datastore.messages.CloseDataChangeListenerRegistration;
 import org.opendaylight.controller.cluster.datastore.messages.CloseDataChangeListenerRegistrationReply;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
 public class DataChangeListenerRegistration extends AbstractUntypedActor {
 
-    private final org.opendaylight.yangtools.concepts.ListenerRegistration<AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>>
+    private final ListenerRegistration<AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>>
         registration;
 
     public DataChangeListenerRegistration(
-        org.opendaylight.yangtools.concepts.ListenerRegistration<AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>> registration) {
+        ListenerRegistration<AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>> registration) {
         this.registration = registration;
     }
 
@@ -36,14 +38,8 @@ public class DataChangeListenerRegistration extends AbstractUntypedActor {
     }
 
     public static Props props(
-        final org.opendaylight.yangtools.concepts.ListenerRegistration<AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>> registration) {
-        return Props.create(new Creator<DataChangeListenerRegistration>() {
-
-            @Override
-            public DataChangeListenerRegistration create() throws Exception {
-                return new DataChangeListenerRegistration(registration);
-            }
-        });
+        final ListenerRegistration<AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>> registration) {
+        return Props.create(new DataChangeListenerRegistrationCreator(registration));
     }
 
     private void closeListenerRegistration(
@@ -53,4 +49,21 @@ public class DataChangeListenerRegistration extends AbstractUntypedActor {
             .tell(new CloseDataChangeListenerRegistrationReply().toSerializable(), getSelf());
         getSelf().tell(PoisonPill.getInstance(), getSelf());
     }
+
+    private static class DataChangeListenerRegistrationCreator
+                                            implements Creator<DataChangeListenerRegistration> {
+        final ListenerRegistration<AsyncDataChangeListener<YangInstanceIdentifier,
+                                                           NormalizedNode<?, ?>>> registration;
+
+        DataChangeListenerRegistrationCreator(
+                ListenerRegistration<AsyncDataChangeListener<YangInstanceIdentifier,
+                                                             NormalizedNode<?, ?>>> registration) {
+            this.registration = registration;
+        }
+
+        @Override
+        public DataChangeListenerRegistration create() throws Exception {
+            return new DataChangeListenerRegistration(registration);
+        }
+    }
 }
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DatastoreContext.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DatastoreContext.java
new file mode 100644 (file)
index 0000000..af8a987
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.cluster.datastore;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreConfigProperties;
+import scala.concurrent.duration.Duration;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Contains contextual data for shards.
+ *
+ * @author Thomas Pantelis
+ */
+public class DatastoreContext {
+
+    private final InMemoryDOMDataStoreConfigProperties dataStoreProperties;
+    private final Duration shardTransactionIdleTimeout;
+
+    public DatastoreContext() {
+        this.dataStoreProperties = null;
+        this.shardTransactionIdleTimeout = Duration.create(10, TimeUnit.MINUTES);
+    }
+
+    public DatastoreContext(InMemoryDOMDataStoreConfigProperties dataStoreProperties,
+        Duration shardTransactionIdleTimeout) {
+        this.dataStoreProperties = Preconditions.checkNotNull(dataStoreProperties);
+        this.shardTransactionIdleTimeout = Preconditions.checkNotNull(shardTransactionIdleTimeout);
+    }
+
+    public InMemoryDOMDataStoreConfigProperties getDataStoreProperties() {
+        return dataStoreProperties;
+    }
+
+    public Duration getShardTransactionIdleTimeout() {
+        return shardTransactionIdleTimeout;
+    }
+
+
+}
index 404a4e02033ea1c89f9fada4135cfe0e4b6a935e..202ced9a26512047f57ee8ad2b0ced7e61366771 100644 (file)
@@ -8,14 +8,16 @@
 
 package org.opendaylight.controller.cluster.datastore;
 
+import java.util.concurrent.TimeUnit;
+
 import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
 
 import com.google.common.base.Preconditions;
+
 import org.opendaylight.controller.cluster.datastore.identifiers.ShardManagerIdentifier;
 import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListener;
 import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListenerReply;
-import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
 import org.opendaylight.controller.cluster.datastore.shardstrategy.ShardStrategyFactory;
 import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
@@ -34,6 +36,8 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import scala.concurrent.duration.Duration;
+
 /**
  *
  */
@@ -42,11 +46,10 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener, Au
     private static final Logger LOG = LoggerFactory.getLogger(DistributedDataStore.class);
 
     private final ActorContext actorContext;
-
-    private SchemaContext schemaContext;
+    private final DatastoreContext datastoreContext;
 
     public DistributedDataStore(ActorSystem actorSystem, String type, ClusterWrapper cluster,
-            Configuration configuration, InMemoryDOMDataStoreConfigProperties dataStoreProperties) {
+            Configuration configuration, DistributedDataStoreProperties dataStoreProperties) {
         Preconditions.checkNotNull(actorSystem, "actorSystem should not be null");
         Preconditions.checkNotNull(type, "type should not be null");
         Preconditions.checkNotNull(cluster, "cluster should not be null");
@@ -57,13 +60,23 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener, Au
 
         LOG.info("Creating ShardManager : {}", shardManagerId);
 
-        this.actorContext = new ActorContext(actorSystem, actorSystem
-            .actorOf(ShardManager.props(type, cluster, configuration, dataStoreProperties),
-                shardManagerId ), cluster, configuration);
+        datastoreContext = new DatastoreContext(InMemoryDOMDataStoreConfigProperties.create(
+                dataStoreProperties.getMaxShardDataChangeExecutorPoolSize(),
+                dataStoreProperties.getMaxShardDataChangeExecutorQueueSize(),
+                dataStoreProperties.getMaxShardDataChangeListenerQueueSize()),
+                Duration.create(dataStoreProperties.getShardTransactionIdleTimeoutInMinutes(),
+                        TimeUnit.MINUTES));
+
+        actorContext
+                = new ActorContext(
+                    actorSystem, actorSystem.actorOf(
+                        ShardManager.props(type, cluster, configuration, datastoreContext).
+                            withMailbox(ActorContext.MAILBOX), shardManagerId ), cluster, configuration);
     }
 
     public DistributedDataStore(ActorContext actorContext) {
         this.actorContext = Preconditions.checkNotNull(actorContext, "actorContext should not be null");
+        this.datastoreContext = new DatastoreContext();
     }
 
 
@@ -80,7 +93,7 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener, Au
         LOG.debug("Registering listener: {} for path: {} scope: {}", listener, path, scope);
 
         ActorRef dataChangeListenerActor = actorContext.getActorSystem().actorOf(
-            DataChangeListener.props(schemaContext,listener,path ));
+            DataChangeListener.props(listener ));
 
         String shardName = ShardStrategyFactory.getStrategy(path).findShard(path);
 
@@ -104,35 +117,31 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener, Au
 
     @Override
     public DOMStoreTransactionChain createTransactionChain() {
-        return new TransactionChainProxy(actorContext, schemaContext);
+        return new TransactionChainProxy(actorContext);
     }
 
     @Override
     public DOMStoreReadTransaction newReadOnlyTransaction() {
-        return new TransactionProxy(actorContext, TransactionProxy.TransactionType.READ_ONLY,
-            schemaContext);
+        return new TransactionProxy(actorContext, TransactionProxy.TransactionType.READ_ONLY);
     }
 
     @Override
     public DOMStoreWriteTransaction newWriteOnlyTransaction() {
-        return new TransactionProxy(actorContext, TransactionProxy.TransactionType.WRITE_ONLY,
-            schemaContext);
+        return new TransactionProxy(actorContext, TransactionProxy.TransactionType.WRITE_ONLY);
     }
 
     @Override
     public DOMStoreReadWriteTransaction newReadWriteTransaction() {
-        return new TransactionProxy(actorContext, TransactionProxy.TransactionType.READ_WRITE,
-            schemaContext);
+        return new TransactionProxy(actorContext, TransactionProxy.TransactionType.READ_WRITE);
     }
 
-    @Override public void onGlobalContextUpdated(SchemaContext schemaContext) {
-        this.schemaContext = schemaContext;
-        actorContext.getShardManager().tell(
-            new UpdateSchemaContext(schemaContext), null);
+    @Override
+    public void onGlobalContextUpdated(SchemaContext schemaContext) {
+        actorContext.setSchemaContext(schemaContext);
     }
 
-    @Override public void close() throws Exception {
+    @Override
+    public void close() throws Exception {
         actorContext.shutdown();
-
     }
 }
index a1a3e87510e78d151b769fd579c2602503ec656c..65a39a60e6c0819fe7f14543c268997a53fddff0 100644 (file)
@@ -11,12 +11,11 @@ package org.opendaylight.controller.cluster.datastore;
 import akka.actor.ActorSystem;
 
 import org.opendaylight.controller.cluster.datastore.shardstrategy.ShardStrategyFactory;
-import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreConfigProperties;
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
 
 public class DistributedDataStoreFactory {
     public static DistributedDataStore createInstance(String name, SchemaService schemaService,
-            InMemoryDOMDataStoreConfigProperties dataStoreProperties) {
+            DistributedDataStoreProperties dataStoreProperties) {
 
         ActorSystem actorSystem = ActorSystemFactory.getInstance();
         Configuration config = new ConfigurationImpl("module-shards.conf", "modules.conf");
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreProperties.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreProperties.java
new file mode 100644 (file)
index 0000000..eb6a536
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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.cluster.datastore;
+
+/**
+ * Wrapper class for DistributedDataStore configuration properties.
+ *
+ * @author Thomas Pantelis
+ */
+public class DistributedDataStoreProperties {
+    private final int maxShardDataChangeListenerQueueSize;
+    private final int maxShardDataChangeExecutorQueueSize;
+    private final int maxShardDataChangeExecutorPoolSize;
+    private final int shardTransactionIdleTimeoutInMinutes;
+
+    public DistributedDataStoreProperties() {
+        maxShardDataChangeListenerQueueSize = 1000;
+        maxShardDataChangeExecutorQueueSize = 1000;
+        maxShardDataChangeExecutorPoolSize = 20;
+        shardTransactionIdleTimeoutInMinutes = 10;
+    }
+
+    public DistributedDataStoreProperties(int maxShardDataChangeListenerQueueSize,
+            int maxShardDataChangeExecutorQueueSize, int maxShardDataChangeExecutorPoolSize,
+            int shardTransactionIdleTimeoutInMinutes) {
+        this.maxShardDataChangeListenerQueueSize = maxShardDataChangeListenerQueueSize;
+        this.maxShardDataChangeExecutorQueueSize = maxShardDataChangeExecutorQueueSize;
+        this.maxShardDataChangeExecutorPoolSize = maxShardDataChangeExecutorPoolSize;
+        this.shardTransactionIdleTimeoutInMinutes = shardTransactionIdleTimeoutInMinutes;
+    }
+
+    public int getMaxShardDataChangeListenerQueueSize() {
+        return maxShardDataChangeListenerQueueSize;
+    }
+
+    public int getMaxShardDataChangeExecutorQueueSize() {
+        return maxShardDataChangeExecutorQueueSize;
+    }
+
+    public int getMaxShardDataChangeExecutorPoolSize() {
+        return maxShardDataChangeExecutorPoolSize;
+    }
+
+    public int getShardTransactionIdleTimeoutInMinutes() {
+        return shardTransactionIdleTimeoutInMinutes;
+    }
+}
index 75f540ade088e6bb45b10e9b92bc4af8789b0218..43a9faa3e44e5d6fe77db7cce74929f8888dcadb 100644 (file)
@@ -15,11 +15,13 @@ 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.base.Preconditions;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+
 import org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier;
 import org.opendaylight.controller.cluster.datastore.identifiers.ShardTransactionIdentifier;
 import org.opendaylight.controller.cluster.datastore.jmx.mbeans.shard.ShardMBeanFactory;
@@ -43,14 +45,15 @@ import org.opendaylight.controller.cluster.raft.RaftActor;
 import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
-import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreConfigProperties;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreFactory;
 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.yangtools.concepts.ListenerRegistration;
 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;
@@ -89,17 +92,21 @@ public class Shard extends RaftActor {
     /// The name of this shard
     private final ShardIdentifier name;
 
-    private volatile SchemaContext schemaContext;
-
     private final ShardStats shardMBean;
 
     private final List<ActorSelection> dataChangeListeners = new ArrayList<>();
 
+    private final DatastoreContext datastoreContext;
+
+
+    private SchemaContext schemaContext;
+
     private Shard(ShardIdentifier name, Map<ShardIdentifier, String> peerAddresses,
-            InMemoryDOMDataStoreConfigProperties dataStoreProperties) {
+            DatastoreContext datastoreContext) {
         super(name.toString(), mapPeerAddresses(peerAddresses), Optional.of(configParams));
 
         this.name = name;
+        this.datastoreContext = datastoreContext;
 
         String setting = System.getProperty("shard.persistent");
 
@@ -107,10 +114,12 @@ public class Shard extends RaftActor {
 
         LOG.info("Shard created : {} persistent : {}", name, persistent);
 
-        store = InMemoryDOMDataStoreFactory.create(name.toString(), null, dataStoreProperties);
+        store = InMemoryDOMDataStoreFactory.create(name.toString(), null,
+                datastoreContext.getDataStoreProperties());
 
         shardMBean = ShardMBeanFactory.getShardStatsMBean(name.toString());
 
+
     }
 
     private static Map<String, String> mapPeerAddresses(
@@ -125,27 +134,16 @@ public class Shard extends RaftActor {
         return map;
     }
 
-
-
-
     public static Props props(final ShardIdentifier name,
         final Map<ShardIdentifier, String> peerAddresses,
-        final InMemoryDOMDataStoreConfigProperties dataStoreProperties) {
+        DatastoreContext datastoreContext) {
         Preconditions.checkNotNull(name, "name should not be null");
-        Preconditions
-            .checkNotNull(peerAddresses, "peerAddresses should not be null");
-
-        return Props.create(new Creator<Shard>() {
-
-            @Override
-            public Shard create() throws Exception {
-                return new Shard(name, peerAddresses, dataStoreProperties);
-            }
+        Preconditions.checkNotNull(peerAddresses, "peerAddresses should not be null");
+        Preconditions.checkNotNull(datastoreContext, "shardContext should not be null");
 
-        });
+        return Props.create(new ShardCreator(name, peerAddresses, datastoreContext));
     }
 
-
     @Override public void onReceiveCommand(Object message) {
         LOG.debug("Received message {} from {}", message.getClass().toString(),
             getSender());
@@ -188,9 +186,8 @@ public class Shard extends RaftActor {
             shardMBean.incrementReadOnlyTransactionCount();
 
             return getContext().actorOf(
-                ShardTransaction
-                    .props(store.newReadOnlyTransaction(), getSelf(),
-                        schemaContext), transactionId.toString());
+                ShardTransaction.props(store.newReadOnlyTransaction(), getSelf(),
+                        schemaContext,datastoreContext, name.toString()), transactionId.toString());
 
         } else if (createTransaction.getTransactionType()
             == TransactionProxy.TransactionType.READ_WRITE.ordinal()) {
@@ -198,9 +195,8 @@ public class Shard extends RaftActor {
             shardMBean.incrementReadWriteTransactionCount();
 
             return getContext().actorOf(
-                ShardTransaction
-                    .props(store.newReadWriteTransaction(), getSelf(),
-                        schemaContext), transactionId.toString());
+                ShardTransaction.props(store.newReadWriteTransaction(), getSelf(),
+                        schemaContext, datastoreContext,name.toString()), transactionId.toString());
 
 
         } else if (createTransaction.getTransactionType()
@@ -209,9 +205,8 @@ public class Shard extends RaftActor {
             shardMBean.incrementWriteOnlyTransactionCount();
 
             return getContext().actorOf(
-                ShardTransaction
-                    .props(store.newWriteOnlyTransaction(), getSelf(),
-                        schemaContext), transactionId.toString());
+                ShardTransaction.props(store.newWriteOnlyTransaction(), getSelf(),
+                        schemaContext, datastoreContext, name.toString()), transactionId.toString());
         } else {
             throw new IllegalArgumentException(
                 "Shard="+name + ":CreateTransaction message has unidentified transaction type="
@@ -269,12 +264,14 @@ public class Shard extends RaftActor {
         final ActorRef self = getSelf();
 
         Futures.addCallback(future, new FutureCallback<Void>() {
+            @Override
             public void onSuccess(Void v) {
                sender.tell(new CommitTransactionReply().toSerializable(),self);
                shardMBean.incrementCommittedTransactionCount();
                shardMBean.setLastCommittedTransactionTime(new Date());
             }
 
+            @Override
             public void onFailure(Throwable t) {
                 LOG.error(t, "An exception happened during commit");
                 shardMBean.incrementFailedTransactionsCount();
@@ -327,12 +324,10 @@ public class Shard extends RaftActor {
         dataChangeListeners.add(dataChangeListenerPath);
 
         AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>
-            listener =
-            new DataChangeListenerProxy(schemaContext, dataChangeListenerPath);
+            listener = new DataChangeListenerProxy(schemaContext, dataChangeListenerPath);
 
-        org.opendaylight.yangtools.concepts.ListenerRegistration<AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>>
-            registration =
-            store.registerChangeListener(registerChangeListener.getPath(),
+        ListenerRegistration<AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>>
+            registration = store.registerChangeListener(registerChangeListener.getPath(),
                 listener, registerChangeListener.getScope());
         ActorRef listenerRegistration =
             getContext().actorOf(
@@ -349,12 +344,9 @@ public class Shard extends RaftActor {
 
     private void createTransactionChain() {
         DOMStoreTransactionChain chain = store.createTransactionChain();
-        ActorRef transactionChain =
-            getContext().actorOf(
-                ShardTransactionChain.props(chain, schemaContext));
-        getSender()
-            .tell(new CreateTransactionChainReply(transactionChain.path())
-                    .toSerializable(),
+        ActorRef transactionChain = getContext().actorOf(
+                ShardTransactionChain.props(chain, schemaContext, datastoreContext,name.toString() ));
+        getSender().tell(new CreateTransactionChainReply(transactionChain.path()).toSerializable(),
                 getSelf());
     }
 
@@ -426,4 +418,25 @@ public class Shard extends RaftActor {
             return HEART_BEAT_INTERVAL;
         }
     }
+
+    private static class ShardCreator implements Creator<Shard> {
+
+        private static final long serialVersionUID = 1L;
+
+        final ShardIdentifier name;
+        final Map<ShardIdentifier, String> peerAddresses;
+        final DatastoreContext datastoreContext;
+
+        ShardCreator(ShardIdentifier name, Map<ShardIdentifier, String> peerAddresses,
+                DatastoreContext datastoreContext) {
+            this.name = name;
+            this.peerAddresses = peerAddresses;
+            this.datastoreContext = datastoreContext;
+        }
+
+        @Override
+        public Shard create() throws Exception {
+            return new Shard(name, peerAddresses, datastoreContext);
+        }
+    }
 }
index 2972772a4840cf5117ef3b9c9ca2cb4947d2352c..e51d49bff2aff8b6380081e0e772765d172246b0 100644 (file)
@@ -17,7 +17,9 @@ import akka.actor.SupervisorStrategy;
 import akka.cluster.ClusterEvent;
 import akka.japi.Creator;
 import akka.japi.Function;
+
 import com.google.common.base.Preconditions;
+
 import org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier;
 import org.opendaylight.controller.cluster.datastore.identifiers.ShardManagerIdentifier;
 import org.opendaylight.controller.cluster.datastore.jmx.mbeans.shardmanager.ShardManagerInfo;
@@ -30,8 +32,8 @@ import org.opendaylight.controller.cluster.datastore.messages.PeerAddressResolve
 import org.opendaylight.controller.cluster.datastore.messages.PrimaryFound;
 import org.opendaylight.controller.cluster.datastore.messages.PrimaryNotFound;
 import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
-import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreConfigProperties;
 
+import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
 import scala.concurrent.duration.Duration;
 
 import java.util.ArrayList;
@@ -70,19 +72,19 @@ public class ShardManager extends AbstractUntypedActor {
 
     private ShardManagerInfoMBean mBean;
 
-    private final InMemoryDOMDataStoreConfigProperties dataStoreProperties;
+    private final DatastoreContext datastoreContext;
 
     /**
      * @param type defines the kind of data that goes into shards created by this shard manager. Examples of type would be
      *             configuration or operational
      */
     private ShardManager(String type, ClusterWrapper cluster, Configuration configuration,
-            InMemoryDOMDataStoreConfigProperties dataStoreProperties) {
+            DatastoreContext datastoreContext) {
 
         this.type = Preconditions.checkNotNull(type, "type should not be null");
         this.cluster = Preconditions.checkNotNull(cluster, "cluster should not be null");
         this.configuration = Preconditions.checkNotNull(configuration, "configuration should not be null");
-        this.dataStoreProperties = dataStoreProperties;
+        this.datastoreContext = datastoreContext;
 
         // Subscribe this actor to cluster member events
         cluster.subscribeToMemberEvents(getSelf());
@@ -95,22 +97,15 @@ public class ShardManager extends AbstractUntypedActor {
     public static Props props(final String type,
         final ClusterWrapper cluster,
         final Configuration configuration,
-        final InMemoryDOMDataStoreConfigProperties dataStoreProperties) {
+        final DatastoreContext datastoreContext) {
 
         Preconditions.checkNotNull(type, "type should not be null");
         Preconditions.checkNotNull(cluster, "cluster should not be null");
         Preconditions.checkNotNull(configuration, "configuration should not be null");
 
-        return Props.create(new Creator<ShardManager>() {
-
-            @Override
-            public ShardManager create() throws Exception {
-                return new ShardManager(type, cluster, configuration, dataStoreProperties);
-            }
-        });
+        return Props.create(new ShardManagerCreator(type, cluster, configuration, datastoreContext));
     }
 
-
     @Override
     public void handleReceive(Object message) throws Exception {
         if (message.getClass().equals(FindPrimary.SERIALIZABLE_CLASS)) {
@@ -250,8 +245,9 @@ public class ShardManager extends AbstractUntypedActor {
             ShardIdentifier shardId = getShardIdentifier(memberName, shardName);
             Map<ShardIdentifier, String> peerAddresses = getPeerAddresses(shardName);
             ActorRef actor = getContext()
-                .actorOf(Shard.props(shardId, peerAddresses, dataStoreProperties),
-                    shardId.toString());
+                .actorOf(Shard.props(shardId, peerAddresses, datastoreContext).
+                    withMailbox(ActorContext.MAILBOX), shardId.toString());
+
             localShardActorNames.add(shardId.toString());
             localShards.put(shardName, new ShardInformation(shardName, actor, peerAddresses));
         }
@@ -351,6 +347,28 @@ public class ShardManager extends AbstractUntypedActor {
             }
         }
     }
+
+    private static class ShardManagerCreator implements Creator<ShardManager> {
+        private static final long serialVersionUID = 1L;
+
+        final String type;
+        final ClusterWrapper cluster;
+        final Configuration configuration;
+        final DatastoreContext datastoreContext;
+
+        ShardManagerCreator(String type, ClusterWrapper cluster,
+                Configuration configuration, DatastoreContext datastoreContext) {
+            this.type = type;
+            this.cluster = cluster;
+            this.configuration = configuration;
+            this.datastoreContext = datastoreContext;
+        }
+
+        @Override
+        public ShardManager create() throws Exception {
+            return new ShardManager(type, cluster, configuration, datastoreContext);
+        }
+    }
 }
 
 
index 1328d466f34b6fff82a91b98379cd815b488155c..91d629432f41f7633d128dd6c17e03a283c6bc18 100644 (file)
 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.DataExists;
 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.controller.sal.core.spi.data.DOMStoreTransaction;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 /**
@@ -27,40 +23,27 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
  * 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;
-
-  }
+    private final DOMStoreReadTransaction 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 if(DataExists.SERIALIZABLE_CLASS.equals(message.getClass())) {
-        dataExists(transaction, DataExists.fromSerializable(message));
-    } else {
-      super.handleReceive(message);
+    public ShardReadTransaction(DOMStoreReadTransaction transaction, ActorRef shardActor,
+            SchemaContext schemaContext,String shardName) {
+        super(shardActor, schemaContext, shardName);
+        this.transaction = transaction;
     }
-  }
-  protected void closeTransaction(CloseTransaction message) {
-    transaction.close();
-    getSender().tell(new CloseTransactionReply().toSerializable(), getSelf());
-    getSelf().tell(PoisonPill.getInstance(), getSelf());
-  }
 
-  //default scope test method to check if we get correct exception
-  void forUnitTestOnlyExplicitTransactionClose(){
-      transaction.close();
-  }
+    @Override
+    public void handleReceive(Object message) throws Exception {
+        if(ReadData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+            readData(transaction, ReadData.fromSerializable(message));
+        } else if(DataExists.SERIALIZABLE_CLASS.equals(message.getClass())) {
+            dataExists(transaction, DataExists.fromSerializable(message));
+        } else {
+            super.handleReceive(message);
+        }
+    }
 
+    @Override
+    protected DOMStoreTransaction getDOMStoreTransaction() {
+        return transaction;
+    }
 }
index 49c7b7e78f52295e9b3b1fc5b1ae2ea10926def2..bd71c27fd67d8b2d2b9d99808a82f91f878d35fc 100644 (file)
 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.DataExists;
 import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
 import org.opendaylight.controller.cluster.datastore.messages.MergeData;
@@ -23,7 +19,7 @@ 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.controller.sal.core.spi.data.DOMStoreTransaction;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 /**
@@ -31,50 +27,35 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
  * 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;
-  }
+    private final DOMStoreReadWriteTransaction 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.fromSerializable(message));
-    } else if (ReadyTransaction.SERIALIZABLE_CLASS.equals(message.getClass())) {
-      readyTransaction(transaction,new ReadyTransaction());
-    } else if(DataExists.SERIALIZABLE_CLASS.equals(message.getClass())) {
-        dataExists(transaction, DataExists.fromSerializable(message));
-    }else {
-      super.handleReceive(message);
+    public ShardReadWriteTransaction(DOMStoreReadWriteTransaction transaction, ActorRef shardActor,
+            SchemaContext schemaContext,String shardName) {
+        super(shardActor, schemaContext, shardName);
+        this.transaction = transaction;
     }
-  }
 
-  protected void closeTransaction(CloseTransaction message) {
-    transaction.close();
-    getSender().tell(new CloseTransactionReply().toSerializable(), getSelf());
-    getSelf().tell(PoisonPill.getInstance(), getSelf());
-  }
+    @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.fromSerializable(message));
+        } else if(ReadyTransaction.SERIALIZABLE_CLASS.equals(message.getClass())) {
+            readyTransaction(transaction, new ReadyTransaction());
+        } else if(DataExists.SERIALIZABLE_CLASS.equals(message.getClass())) {
+            dataExists(transaction, DataExists.fromSerializable(message));
+        } else {
+            super.handleReceive(message);
+        }
+    }
 
-    /**
-     * The following method is used in unit testing only
-     * hence the default scope.
-     * This is done to test out failure cases.
-     */
-    public void forUnitTestOnlyExplicitTransactionClose() {
-        transaction.close();
+    @Override
+    protected DOMStoreTransaction getDOMStoreTransaction() {
+        return transaction;
     }
 }
index 360a10722c06df2c3e357631b43d89eac801a3d3..3b0e0934d9b67c6a18fde38edeb27ae7e92e52f4 100644 (file)
@@ -9,14 +9,16 @@
 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;
+import akka.actor.ReceiveTimeout;
 import akka.japi.Creator;
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.CheckedFuture;
 import org.opendaylight.controller.cluster.datastore.exceptions.UnknownMessageException;
+import org.opendaylight.controller.cluster.datastore.jmx.mbeans.shard.ShardMBeanFactory;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
 import org.opendaylight.controller.cluster.datastore.messages.DataExists;
 import org.opendaylight.controller.cluster.datastore.messages.DataExistsReply;
 import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
@@ -39,7 +41,7 @@ import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 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.DOMStoreTransaction;
 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;
@@ -69,142 +71,79 @@ import org.opendaylight.yangtools.yang.model.api.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.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 UnknownMessageException(message);
+    private final ActorRef shardActor;
+    protected final SchemaContext schemaContext;
+    private final String  shardName;
+
+
+    private final MutableCompositeModification modification = new MutableCompositeModification();
+
+    protected ShardTransaction(ActorRef shardActor, SchemaContext schemaContext,
+        String shardName) {
+        this.shardActor = shardActor;
+        this.schemaContext = schemaContext;
+        this.shardName = shardName;
+    }
+
+    public static Props props(DOMStoreTransaction transaction, ActorRef shardActor,
+            SchemaContext schemaContext,DatastoreContext datastoreContext, String shardName) {
+        return Props.create(new ShardTransactionCreator(transaction, shardActor, schemaContext,
+           datastoreContext, shardName));
     }
-  }
 
-  abstract protected  void closeTransaction(CloseTransaction message);
+    protected abstract DOMStoreTransaction getDOMStoreTransaction();
+
+    @Override
+    public void handleReceive(Object message) throws Exception {
+        if (message.getClass().equals(CloseTransaction.SERIALIZABLE_CLASS)) {
+            closeTransaction(true);
+        } else if (message instanceof GetCompositedModification) {
+            // This is here for testing only
+            getSender().tell(new GetCompositeModificationReply(
+                    new ImmutableCompositeModification(modification)), getSelf());
+        } else if (message instanceof ReceiveTimeout) {
+            LOG.debug("Got ReceiveTimeout for inactivity - closing Tx");
+            closeTransaction(false);
+        } else {
+            throw new UnknownMessageException(message);
+        }
+    }
 
-  protected void readData(DOMStoreReadTransaction transaction,ReadData message) {
-    final ActorRef sender = getSender();
-    final ActorRef self = getSelf();
-    final YangInstanceIdentifier path = message.getPath();
-    final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> future =
-          transaction.read(path);
+    private void closeTransaction(boolean sendReply) {
+        getDOMStoreTransaction().close();
 
-      future.addListener(new Runnable() {
-      @Override
-      public void run() {
-        try {
-          Optional<NormalizedNode<?, ?>> optional = future.checkedGet();
-          if (optional.isPresent()) {
-            sender.tell(new ReadDataReply(schemaContext,optional.get()).toSerializable(), self);
-          } else {
-            sender.tell(new ReadDataReply(schemaContext,null).toSerializable(), self);
-          }
-        } catch (Exception e) {
-            sender.tell(new akka.actor.Status.Failure(e),self);
+        if(sendReply) {
+            getSender().tell(new CloseTransactionReply().toSerializable(), getSelf());
         }
 
-      }
-    }, getContext().dispatcher());
-  }
+        getSelf().tell(PoisonPill.getInstance(), getSelf());
+    }
+
+    protected void readData(DOMStoreReadTransaction transaction,ReadData message) {
+        final ActorRef sender = getSender();
+        final ActorRef self = getSelf();
+        final YangInstanceIdentifier path = message.getPath();
+        final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> future =
+                transaction.read(path);
+
+        future.addListener(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    Optional<NormalizedNode<?, ?>> optional = future.checkedGet();
+                    if (optional.isPresent()) {
+                        sender.tell(new ReadDataReply(schemaContext,optional.get()).toSerializable(), self);
+                    } else {
+                        sender.tell(new ReadDataReply(schemaContext,null).toSerializable(), self);
+                    }
+                } catch (Exception e) {
+                    ShardMBeanFactory.getShardStatsMBean(shardName).incrementFailedReadTransactionsCount();
+                    sender.tell(new akka.actor.Status.Failure(e), self);
+                }
+
+            }
+        }, getContext().dispatcher());
+    }
 
     protected void dataExists(DOMStoreReadTransaction transaction, DataExists message) {
         final YangInstanceIdentifier path = message.getPath();
@@ -218,71 +157,106 @@ public abstract class ShardTransaction extends AbstractUntypedActor {
 
     }
 
-  protected void writeData(DOMStoreWriteTransaction transaction, WriteData message) {
-    modification.addModification(
-        new WriteModification(message.getPath(), message.getData(),schemaContext));
-    LOG.debug("writeData at path : " + message.getPath().toString());
+    protected void writeData(DOMStoreWriteTransaction transaction, WriteData message) {
+        modification.addModification(
+                new WriteModification(message.getPath(), message.getData(),schemaContext));
+        LOG.debug("writeData at path : " + message.getPath().toString());
 
-    try {
-        transaction.write(message.getPath(), message.getData());
-        getSender().tell(new WriteDataReply().toSerializable(), getSelf());
-    }catch(Exception e){
-        getSender().tell(new akka.actor.Status.Failure(e), getSelf());
+        try {
+            transaction.write(message.getPath(), message.getData());
+            getSender().tell(new WriteDataReply().toSerializable(), getSelf());
+        }catch(Exception e){
+            getSender().tell(new akka.actor.Status.Failure(e), 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());
-    try {
-        transaction.merge(message.getPath(), message.getData());
-        getSender().tell(new MergeDataReply().toSerializable(), getSelf());
-    }catch(Exception e){
-        getSender().tell(new akka.actor.Status.Failure(e), 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());
+        try {
+            transaction.merge(message.getPath(), message.getData());
+            getSender().tell(new MergeDataReply().toSerializable(), getSelf());
+        }catch(Exception e){
+            getSender().tell(new akka.actor.Status.Failure(e), getSelf());
+        }
     }
-  }
-
-  protected void deleteData(DOMStoreWriteTransaction transaction, DeleteData message) {
-    LOG.debug("deleteData at path : " + message.getPath().toString());
-    modification.addModification(new DeleteModification(message.getPath()));
-    try {
-        transaction.delete(message.getPath());
-        getSender().tell(new DeleteDataReply().toSerializable(), getSelf());
-    }catch(Exception e){
-        getSender().tell(new akka.actor.Status.Failure(e), getSelf());
+
+    protected void deleteData(DOMStoreWriteTransaction transaction, DeleteData message) {
+        LOG.debug("deleteData at path : " + message.getPath().toString());
+        modification.addModification(new DeleteModification(message.getPath()));
+        try {
+            transaction.delete(message.getPath());
+            getSender().tell(new DeleteDataReply().toSerializable(), getSelf());
+        }catch(Exception e){
+            getSender().tell(new akka.actor.Status.Failure(e), getSelf());
+        }
     }
-  }
 
-  protected void readyTransaction(DOMStoreWriteTransaction transaction, ReadyTransaction message) {
-    DOMStoreThreePhaseCommitCohort cohort =  transaction.ready();
-    ActorRef cohortActor = getContext().actorOf(
-        ThreePhaseCommitCohort.props(cohort, shardActor, modification), "cohort");
-    getSender()
+    protected void readyTransaction(DOMStoreWriteTransaction transaction, ReadyTransaction message) {
+        DOMStoreThreePhaseCommitCohort cohort =  transaction.ready();
+        ActorRef cohortActor = getContext().actorOf(
+            ThreePhaseCommitCohort.props(cohort, shardActor, modification, shardName), "cohort");
+        getSender()
         .tell(new ReadyTransactionReply(cohortActor.path()).toSerializable(), getSelf());
 
-  }
+    }
 
+    private static class ShardTransactionCreator implements Creator<ShardTransaction> {
 
-  // These classes are in here for test purposes only
+        private static final long serialVersionUID = 1L;
 
+        final DOMStoreTransaction transaction;
+        final ActorRef shardActor;
+        final SchemaContext schemaContext;
+        final DatastoreContext datastoreContext;
+        final String shardName;
 
-  static class GetCompositedModification {
+        ShardTransactionCreator(DOMStoreTransaction transaction, ActorRef shardActor,
+                SchemaContext schemaContext, DatastoreContext datastoreContext, String shardName) {
+            this.transaction = transaction;
+            this.shardActor = shardActor;
+            this.shardName = shardName;
+            this.schemaContext = schemaContext;
+            this.datastoreContext = datastoreContext;
+        }
 
-  }
+        @Override
+        public ShardTransaction create() throws Exception {
+            ShardTransaction tx;
+            if(transaction instanceof DOMStoreReadWriteTransaction) {
+                tx = new ShardReadWriteTransaction((DOMStoreReadWriteTransaction)transaction,
+                        shardActor, schemaContext, shardName);
+            } else if(transaction instanceof DOMStoreReadTransaction) {
+                tx = new ShardReadTransaction((DOMStoreReadTransaction)transaction, shardActor,
+                        schemaContext, shardName);
+            } else {
+                tx = new ShardWriteTransaction((DOMStoreWriteTransaction)transaction,
+                        shardActor, schemaContext, shardName);
+            }
+
+            tx.getContext().setReceiveTimeout(datastoreContext.getShardTransactionIdleTimeout());
+            return tx;
+        }
+    }
 
+    // These classes are in here for test purposes only
 
-  static class GetCompositeModificationReply {
-    private final CompositeModification modification;
+    static class GetCompositedModification {
+    }
 
 
-    GetCompositeModificationReply(CompositeModification modification) {
-      this.modification = modification;
-    }
+    static class GetCompositeModificationReply {
+        private final CompositeModification modification;
 
 
-    public CompositeModification getModification() {
-      return modification;
+        GetCompositeModificationReply(CompositeModification modification) {
+            this.modification = modification;
+        }
+
+
+        public CompositeModification getModification() {
+            return modification;
+        }
     }
-  }
 }
index c508255ea490ee09b370dae8a49320495166c820..e7a181865e70c54917a272a6268704316111d13c 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.controller.cluster.datastore;
 import akka.actor.ActorRef;
 import akka.actor.Props;
 import akka.japi.Creator;
+
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionChain;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionChainReply;
 import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
@@ -24,11 +25,16 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 public class ShardTransactionChain extends AbstractUntypedActor {
 
     private final DOMStoreTransactionChain chain;
+    private final DatastoreContext datastoreContext;
     private final SchemaContext schemaContext;
+    private final String shardName;
 
-    public ShardTransactionChain(DOMStoreTransactionChain chain, SchemaContext schemaContext) {
+    public ShardTransactionChain(DOMStoreTransactionChain chain, SchemaContext schemaContext,
+            DatastoreContext datastoreContext,String shardName) {
         this.chain = chain;
+        this.datastoreContext = datastoreContext;
         this.schemaContext = schemaContext;
+        this.shardName = shardName;
     }
 
     @Override
@@ -48,23 +54,29 @@ public class ShardTransactionChain extends AbstractUntypedActor {
         return getContext().parent();
     }
 
-  private ActorRef createTypedTransactionActor(CreateTransaction createTransaction,String transactionId){
-    if(createTransaction.getTransactionType()== TransactionProxy.TransactionType.READ_ONLY.ordinal()){
-      return getContext().actorOf(
-          ShardTransaction.props( chain.newReadOnlyTransaction(), getShardActor(), schemaContext), transactionId);
-
-    }else if (createTransaction.getTransactionType()== TransactionProxy.TransactionType.READ_WRITE.ordinal()){
-      return getContext().actorOf(
-          ShardTransaction.props( chain.newReadWriteTransaction(), getShardActor(), schemaContext), transactionId);
-
-
-    }else if (createTransaction.getTransactionType()== TransactionProxy.TransactionType.WRITE_ONLY.ordinal()){
-      return getContext().actorOf(
-          ShardTransaction.props( chain.newWriteOnlyTransaction(), getShardActor(), schemaContext), transactionId);
-    }else{
-      throw new IllegalArgumentException ("CreateTransaction message has unidentified transaction type="+createTransaction.getTransactionType()) ;
+    private ActorRef createTypedTransactionActor(CreateTransaction createTransaction,
+            String transactionId) {
+        if(createTransaction.getTransactionType() ==
+                TransactionProxy.TransactionType.READ_ONLY.ordinal()) {
+            return getContext().actorOf(
+                    ShardTransaction.props( chain.newReadOnlyTransaction(), getShardActor(),
+                            schemaContext, datastoreContext,shardName), transactionId);
+        } else if (createTransaction.getTransactionType() ==
+                TransactionProxy.TransactionType.READ_WRITE.ordinal()) {
+            return getContext().actorOf(
+                    ShardTransaction.props( chain.newReadWriteTransaction(), getShardActor(),
+                            schemaContext, datastoreContext,shardName), transactionId);
+        } else if (createTransaction.getTransactionType() ==
+                TransactionProxy.TransactionType.WRITE_ONLY.ordinal()) {
+            return getContext().actorOf(
+                    ShardTransaction.props( chain.newWriteOnlyTransaction(), getShardActor(),
+                            schemaContext, datastoreContext,shardName), transactionId);
+        } else {
+            throw new IllegalArgumentException (
+                    "CreateTransaction message has unidentified transaction type=" +
+                             createTransaction.getTransactionType());
+        }
     }
-  }
 
     private void createTransaction(CreateTransaction createTransaction) {
 
@@ -74,13 +86,31 @@ public class ShardTransactionChain extends AbstractUntypedActor {
                 getSelf());
     }
 
-    public static Props props(final DOMStoreTransactionChain chain, final SchemaContext schemaContext) {
-        return Props.create(new Creator<ShardTransactionChain>() {
+    public static Props props(DOMStoreTransactionChain chain, SchemaContext schemaContext,
+        DatastoreContext datastoreContext, String shardName) {
+        return Props.create(new ShardTransactionChainCreator(chain, schemaContext, datastoreContext, shardName));
+    }
+
+    private static class ShardTransactionChainCreator implements Creator<ShardTransactionChain> {
+        private static final long serialVersionUID = 1L;
+
+        final DOMStoreTransactionChain chain;
+        final DatastoreContext datastoreContext;
+        final SchemaContext schemaContext;
+        final String shardName;
+
 
-            @Override
-            public ShardTransactionChain create() throws Exception {
-                return new ShardTransactionChain(chain, schemaContext);
-            }
-        });
+        ShardTransactionChainCreator(DOMStoreTransactionChain chain, SchemaContext schemaContext,
+            DatastoreContext datastoreContext, String shardName) {
+            this.chain = chain;
+            this.datastoreContext = datastoreContext;
+            this.schemaContext = schemaContext;
+            this.shardName = shardName;
+        }
+
+        @Override
+        public ShardTransactionChain create() throws Exception {
+            return new ShardTransactionChain(chain, schemaContext, datastoreContext,shardName);
+        }
     }
 }
index b01fe7d4ac11a4a0eea7cfa28b16f5bea8e7aec5..41c46c3375c58c6177f91b4e397daafaf426b064 100644 (file)
 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.DOMStoreTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
@@ -29,47 +25,31 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
  * 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;
-
-  }
+    private final DOMStoreWriteTransaction 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.fromSerializable(message));
-    } else if (ReadyTransaction.SERIALIZABLE_CLASS.equals(message.getClass())) {
-      readyTransaction(transaction,new ReadyTransaction());
-    }else {
-      super.handleReceive(message);
+    public ShardWriteTransaction(DOMStoreWriteTransaction transaction, ActorRef shardActor,
+            SchemaContext schemaContext,String shardName) {
+        super(shardActor, schemaContext, shardName);
+        this.transaction = transaction;
     }
-  }
 
-  protected void closeTransaction(CloseTransaction message) {
-    transaction.close();
-    getSender().tell(new CloseTransactionReply().toSerializable(), getSelf());
-    getSelf().tell(PoisonPill.getInstance(), getSelf());
-  }
+    @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.fromSerializable(message));
+        } else if(ReadyTransaction.SERIALIZABLE_CLASS.equals(message.getClass())) {
+            readyTransaction(transaction, new ReadyTransaction());
+        } else {
+            super.handleReceive(message);
+        }
+    }
 
-    /**
-     * The following method is used in unit testing only
-     * hence the default scope.
-     * This is done to test out failure cases.
-     */
-    public void forUnitTestOnlyExplicitTransactionClose() {
-        transaction.close();
+    @Override
+    protected DOMStoreTransaction getDOMStoreTransaction() {
+        return transaction;
     }
 }
index 34d35312838fd4346e7446161cd4f1f1c8f9cc74..5a6d0eca5c2a159963febc4ee9d6436f2e864a5d 100644 (file)
@@ -14,9 +14,12 @@ import akka.actor.Props;
 import akka.event.Logging;
 import akka.event.LoggingAdapter;
 import akka.japi.Creator;
+
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+
+import org.opendaylight.controller.cluster.datastore.jmx.mbeans.shard.ShardMBeanFactory;
 import org.opendaylight.controller.cluster.datastore.messages.AbortTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.AbortTransactionReply;
 import org.opendaylight.controller.cluster.datastore.messages.CanCommitTransaction;
@@ -32,30 +35,27 @@ public class ThreePhaseCommitCohort extends AbstractUntypedActor {
     private final DOMStoreThreePhaseCommitCohort cohort;
     private final ActorRef shardActor;
     private final CompositeModification modification;
+    private final String shardName;
 
     public ThreePhaseCommitCohort(DOMStoreThreePhaseCommitCohort cohort,
-        ActorRef shardActor, CompositeModification modification) {
+        ActorRef shardActor, CompositeModification modification,String shardName) {
 
         this.cohort = cohort;
         this.shardActor = shardActor;
         this.modification = modification;
+        this.shardName = shardName;
     }
 
     private final LoggingAdapter log =
         Logging.getLogger(getContext().system(), this);
 
     public static Props props(final DOMStoreThreePhaseCommitCohort cohort,
-        final ActorRef shardActor, final CompositeModification modification) {
-        return Props.create(new Creator<ThreePhaseCommitCohort>() {
-            @Override
-            public ThreePhaseCommitCohort create() throws Exception {
-                return new ThreePhaseCommitCohort(cohort, shardActor,
-                    modification);
-            }
-        });
+        final ActorRef shardActor, final CompositeModification modification,
+        String shardName) {
+        return Props.create(new ThreePhaseCommitCohortCreator(cohort, shardActor, modification,
+           shardName));
     }
 
-
     @Override
     public void handleReceive(Object message) throws Exception {
         if (message.getClass()
@@ -81,12 +81,15 @@ public class ThreePhaseCommitCohort extends AbstractUntypedActor {
         final ActorRef self = getSelf();
 
         Futures.addCallback(future, new FutureCallback<Void>() {
+            @Override
             public void onSuccess(Void v) {
+                ShardMBeanFactory.getShardStatsMBean(shardName).incrementAbortTransactionsCount();
                 sender
                     .tell(new AbortTransactionReply().toSerializable(),
-                        self);
+                    self);
             }
 
+            @Override
             public void onFailure(Throwable t) {
                 LOG.error(t, "An exception happened during abort");
                 sender
@@ -110,12 +113,14 @@ public class ThreePhaseCommitCohort extends AbstractUntypedActor {
         final ActorRef sender = getSender();
         final ActorRef self = getSelf();
         Futures.addCallback(future, new FutureCallback<Void>() {
+            @Override
             public void onSuccess(Void v) {
                 sender
                     .tell(new PreCommitTransactionReply().toSerializable(),
                         self);
             }
 
+            @Override
             public void onFailure(Throwable t) {
                 LOG.error(t, "An exception happened during pre-commit");
                 sender
@@ -130,18 +135,38 @@ public class ThreePhaseCommitCohort extends AbstractUntypedActor {
         final ActorRef sender = getSender();
         final ActorRef self = getSelf();
         Futures.addCallback(future, new FutureCallback<Boolean>() {
+            @Override
             public void onSuccess(Boolean canCommit) {
                 sender.tell(new CanCommitTransactionReply(canCommit)
                     .toSerializable(), self);
             }
 
+            @Override
             public void onFailure(Throwable t) {
                 LOG.error(t, "An exception happened during canCommit");
                 sender
                     .tell(new akka.actor.Status.Failure(t), self);
             }
         });
+    }
 
+    private static class ThreePhaseCommitCohortCreator implements Creator<ThreePhaseCommitCohort> {
+        final DOMStoreThreePhaseCommitCohort cohort;
+        final ActorRef shardActor;
+        final CompositeModification modification;
+        final String shardName;
+
+        ThreePhaseCommitCohortCreator(DOMStoreThreePhaseCommitCohort cohort,
+            ActorRef shardActor, CompositeModification modification, String shardName) {
+            this.cohort = cohort;
+            this.shardActor = shardActor;
+            this.modification = modification;
+            this.shardName = shardName;
+        }
 
+        @Override
+        public ThreePhaseCommitCohort create() throws Exception {
+            return new ThreePhaseCommitCohort(cohort, shardActor, modification, shardName);
+        }
     }
 }
index fc455b193e27118f6dcfcc2de93032f2676c5619..c557118b1e8f92234d597ce6372cda2674f6a6bd 100644 (file)
@@ -13,6 +13,7 @@ import akka.actor.ActorSelection;
 import akka.dispatch.Futures;
 import akka.dispatch.OnComplete;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.SettableFuture;
@@ -31,6 +32,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import scala.concurrent.Future;
+import scala.runtime.AbstractFunction1;
 
 import java.util.Collections;
 import java.util.List;
@@ -40,32 +42,79 @@ import java.util.List;
  */
 public class ThreePhaseCommitCohortProxy implements DOMStoreThreePhaseCommitCohort{
 
-    private static final Logger LOG = LoggerFactory.getLogger(DistributedDataStore.class);
+    private static final Logger LOG = LoggerFactory.getLogger(ThreePhaseCommitCohortProxy.class);
 
     private final ActorContext actorContext;
-    private final List<ActorPath> cohortPaths;
+    private final List<Future<ActorPath>> cohortPathFutures;
+    private volatile List<ActorPath> cohortPaths;
     private final String transactionId;
 
-    public ThreePhaseCommitCohortProxy(ActorContext actorContext, List<ActorPath> cohortPaths,
-            String transactionId) {
+    public ThreePhaseCommitCohortProxy(ActorContext actorContext,
+            List<Future<ActorPath>> cohortPathFutures, String transactionId) {
         this.actorContext = actorContext;
-        this.cohortPaths = cohortPaths;
+        this.cohortPathFutures = cohortPathFutures;
         this.transactionId = transactionId;
     }
 
+    private Future<Void> buildCohortPathsList() {
+
+        Future<Iterable<ActorPath>> combinedFutures = Futures.sequence(cohortPathFutures,
+                actorContext.getActorSystem().dispatcher());
+
+        return combinedFutures.transform(new AbstractFunction1<Iterable<ActorPath>, Void>() {
+            @Override
+            public Void apply(Iterable<ActorPath> paths) {
+                cohortPaths = Lists.newArrayList(paths);
+
+                LOG.debug("Tx {} successfully built cohort path list: {}",
+                        transactionId, cohortPaths);
+                return null;
+            }
+        }, TransactionProxy.SAME_FAILURE_TRANSFORMER, actorContext.getActorSystem().dispatcher());
+    }
+
     @Override
     public ListenableFuture<Boolean> canCommit() {
-        LOG.debug("txn {} canCommit", transactionId);
+        LOG.debug("Tx {} canCommit", transactionId);
+
+        final SettableFuture<Boolean> returnFuture = SettableFuture.create();
+
+        // The first phase of canCommit is to gather the list of cohort actor paths that will
+        // participate in the commit. buildCohortPathsList combines the cohort path Futures into
+        // one Future which we wait on asynchronously here. The cohort actor paths are
+        // extracted from ReadyTransactionReply messages by the Futures that were obtained earlier
+        // and passed to us from upstream processing. If any one fails then  we'll fail canCommit.
+
+        buildCohortPathsList().onComplete(new OnComplete<Void>() {
+            @Override
+            public void onComplete(Throwable failure, Void notUsed) throws Throwable {
+                if(failure != null) {
+                    LOG.debug("Tx {}: a cohort path Future failed: {}", transactionId, failure);
+                    returnFuture.setException(failure);
+                } else {
+                    finishCanCommit(returnFuture);
+                }
+            }
+        }, actorContext.getActorSystem().dispatcher());
+
+        return returnFuture;
+    }
+
+    private void finishCanCommit(final SettableFuture<Boolean> returnFuture) {
+
+        LOG.debug("Tx {} finishCanCommit", transactionId);
+
+        // The last phase of canCommit is to invoke all the cohort actors asynchronously to perform
+        // their canCommit processing. If any one fails then we'll fail canCommit.
 
         Future<Iterable<Object>> combinedFuture =
                 invokeCohorts(new CanCommitTransaction().toSerializable());
 
-        final SettableFuture<Boolean> returnFuture = SettableFuture.create();
-
         combinedFuture.onComplete(new OnComplete<Iterable<Object>>() {
             @Override
             public void onComplete(Throwable failure, Iterable<Object> responses) throws Throwable {
                 if(failure != null) {
+                    LOG.debug("Tx {}: a canCommit cohort Future failed: {}", transactionId, failure);
                     returnFuture.setException(failure);
                     return;
                 }
@@ -87,18 +136,18 @@ public class ThreePhaseCommitCohortProxy implements DOMStoreThreePhaseCommitCoho
                     }
                 }
 
+                LOG.debug("Tx {}: canCommit returning result: {}", transactionId, result);
+
                 returnFuture.set(Boolean.valueOf(result));
             }
         }, actorContext.getActorSystem().dispatcher());
-
-        return returnFuture;
     }
 
     private Future<Iterable<Object>> invokeCohorts(Object message) {
         List<Future<Object>> futureList = Lists.newArrayListWithCapacity(cohortPaths.size());
         for(ActorPath actorPath : cohortPaths) {
 
-            LOG.debug("txn {} Sending {} to {}", transactionId, message, actorPath);
+            LOG.debug("Tx {}: Sending {} to cohort {}", transactionId, message, actorPath);
 
             ActorSelection cohort = actorContext.actorSelection(actorPath);
 
@@ -111,39 +160,73 @@ public class ThreePhaseCommitCohortProxy implements DOMStoreThreePhaseCommitCoho
 
     @Override
     public ListenableFuture<Void> preCommit() {
-        LOG.debug("txn {} preCommit", transactionId);
-        return voidOperation(new PreCommitTransaction().toSerializable(),
+        return voidOperation("preCommit",  new PreCommitTransaction().toSerializable(),
                 PreCommitTransactionReply.SERIALIZABLE_CLASS, true);
     }
 
     @Override
     public ListenableFuture<Void> abort() {
-        LOG.debug("txn {} abort", transactionId);
-
         // Note - we pass false for propagateException. In the front-end data broker, this method
         // is called when one of the 3 phases fails with an exception. We'd rather have that
         // original exception propagated to the client. If our abort fails and we propagate the
         // exception then that exception will supersede and suppress the original exception. But
         // it's the original exception that is the root cause and of more interest to the client.
 
-        return voidOperation(new AbortTransaction().toSerializable(),
+        return voidOperation("abort", new AbortTransaction().toSerializable(),
                 AbortTransactionReply.SERIALIZABLE_CLASS, false);
     }
 
     @Override
     public ListenableFuture<Void> commit() {
-        LOG.debug("txn {} commit", transactionId);
-        return voidOperation(new CommitTransaction().toSerializable(),
+        return voidOperation("commit",  new CommitTransaction().toSerializable(),
                 CommitTransactionReply.SERIALIZABLE_CLASS, true);
     }
 
-    private ListenableFuture<Void> voidOperation(final Object message,
+    private ListenableFuture<Void> voidOperation(final String operationName, final Object message,
             final Class<?> expectedResponseClass, final boolean propagateException) {
 
-        Future<Iterable<Object>> combinedFuture = invokeCohorts(message);
+        LOG.debug("Tx {} {}", transactionId, operationName);
 
         final SettableFuture<Void> returnFuture = SettableFuture.create();
 
+        // The cohort actor list should already be built at this point by the canCommit phase but,
+        // if not for some reason, we'll try to build it here.
+
+        if(cohortPaths != null) {
+            finishVoidOperation(operationName, message, expectedResponseClass, propagateException,
+                    returnFuture);
+        } else {
+            buildCohortPathsList().onComplete(new OnComplete<Void>() {
+                @Override
+                public void onComplete(Throwable failure, Void notUsed) throws Throwable {
+                    if(failure != null) {
+                        LOG.debug("Tx {}: a {} cohort path Future failed: {}", transactionId,
+                                operationName, failure);
+
+                        if(propagateException) {
+                            returnFuture.setException(failure);
+                        } else {
+                            returnFuture.set(null);
+                        }
+                    } else {
+                        finishVoidOperation(operationName, message, expectedResponseClass,
+                                propagateException, returnFuture);
+                    }
+                }
+            }, actorContext.getActorSystem().dispatcher());
+        }
+
+        return returnFuture;
+    }
+
+    private void finishVoidOperation(final String operationName, final Object message,
+            final Class<?> expectedResponseClass, final boolean propagateException,
+            final SettableFuture<Void> returnFuture) {
+
+        LOG.debug("Tx {} finish {}", transactionId, operationName);
+
+        Future<Iterable<Object>> combinedFuture = invokeCohorts(message);
+
         combinedFuture.onComplete(new OnComplete<Iterable<Object>>() {
             @Override
             public void onComplete(Throwable failure, Iterable<Object> responses) throws Throwable {
@@ -161,6 +244,9 @@ public class ThreePhaseCommitCohortProxy implements DOMStoreThreePhaseCommitCoho
                 }
 
                 if(exceptionToPropagate != null) {
+                    LOG.debug("Tx {}: a {} cohort Future failed: {}", transactionId,
+                            operationName, exceptionToPropagate);
+
                     if(propagateException) {
                         // We don't log the exception here to avoid redundant logging since we're
                         // propagating to the caller in MD-SAL core who will log it.
@@ -174,15 +260,15 @@ public class ThreePhaseCommitCohortProxy implements DOMStoreThreePhaseCommitCoho
                         returnFuture.set(null);
                     }
                 } else {
+                    LOG.debug("Tx {}: {} succeeded", transactionId, operationName);
                     returnFuture.set(null);
                 }
             }
         }, actorContext.getActorSystem().dispatcher());
-
-        return returnFuture;
     }
 
-    public List<ActorPath> getCohortPaths() {
-        return Collections.unmodifiableList(this.cohortPaths);
+    @VisibleForTesting
+    List<Future<ActorPath>> getCohortPathFutures() {
+        return Collections.unmodifiableList(cohortPathFutures);
     }
 }
index c4ec760b40cd57d54579144f010b5e0f7425363e..9b4610a99c4a6e5977115f560d12b551131e9be5 100644 (file)
@@ -13,36 +13,33 @@ 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.DOMStoreTransactionChain;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 /**
  * TransactionChainProxy acts as a proxy for a DOMStoreTransactionChain created on a remote shard
  */
 public class TransactionChainProxy implements DOMStoreTransactionChain{
     private final ActorContext actorContext;
-    private final SchemaContext schemaContext;
 
-    public TransactionChainProxy(ActorContext actorContext, SchemaContext schemaContext) {
+    public TransactionChainProxy(ActorContext actorContext) {
         this.actorContext = actorContext;
-        this.schemaContext = schemaContext;
     }
 
     @Override
     public DOMStoreReadTransaction newReadOnlyTransaction() {
         return new TransactionProxy(actorContext,
-            TransactionProxy.TransactionType.READ_ONLY, schemaContext);
+            TransactionProxy.TransactionType.READ_ONLY);
     }
 
     @Override
     public DOMStoreReadWriteTransaction newReadWriteTransaction() {
         return new TransactionProxy(actorContext,
-            TransactionProxy.TransactionType.WRITE_ONLY, schemaContext);
+            TransactionProxy.TransactionType.READ_WRITE);
     }
 
     @Override
     public DOMStoreWriteTransaction newWriteOnlyTransaction() {
         return new TransactionProxy(actorContext,
-            TransactionProxy.TransactionType.READ_WRITE, schemaContext);
+            TransactionProxy.TransactionType.WRITE_ONLY);
     }
 
     @Override
index 5b5b1296af08e42c2278b6db80ac05cbf08329c6..fc1a3aad74ca95ca0545f319303c50a50cd994df 100644 (file)
@@ -9,13 +9,15 @@
 package org.opendaylight.controller.cluster.datastore;
 
 import akka.actor.ActorPath;
-import akka.actor.ActorRef;
 import akka.actor.ActorSelection;
-import akka.actor.Props;
 import akka.dispatch.OnComplete;
 
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.FinalizablePhantomReference;
+import com.google.common.base.FinalizableReferenceQueue;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.SettableFuture;
@@ -45,12 +47,15 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import scala.Function1;
 import scala.concurrent.Future;
+import scala.runtime.AbstractFunction1;
 
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
 
 /**
@@ -72,24 +77,112 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
         READ_WRITE
     }
 
+    static Function1<Throwable, Throwable> SAME_FAILURE_TRANSFORMER = new AbstractFunction1<
+                                                                          Throwable, Throwable>() {
+        @Override
+        public Throwable apply(Throwable failure) {
+            return failure;
+        }
+    };
+
     private static final AtomicLong counter = new AtomicLong();
 
     private static final Logger
         LOG = LoggerFactory.getLogger(TransactionProxy.class);
 
 
+    /**
+     * Used to enqueue the PhantomReferences for read-only TransactionProxy instances. The
+     * FinalizableReferenceQueue is safe to use statically in an OSGi environment as it uses some
+     * trickery to clean up its internal thread when the bundle is unloaded.
+     */
+    private static final FinalizableReferenceQueue phantomReferenceQueue =
+                                                                  new FinalizableReferenceQueue();
+
+    /**
+     * This stores the TransactionProxyCleanupPhantomReference instances statically, This is
+     * necessary because PhantomReferences need a hard reference so they're not garbage collected.
+     * Once finalized, the TransactionProxyCleanupPhantomReference removes itself from this map
+     * and thus becomes eligible for garbage collection.
+     */
+    private static final Map<TransactionProxyCleanupPhantomReference,
+                             TransactionProxyCleanupPhantomReference> phantomReferenceCache =
+                                                                        new ConcurrentHashMap<>();
+
+    /**
+     * A PhantomReference that closes remote transactions for a TransactionProxy when it's
+     * garbage collected. This is used for read-only transactions as they're not explicitly closed
+     * by clients. So the only way to detect that a transaction is no longer in use and it's safe
+     * to clean up is when it's garbage collected. It's inexact as to when an instance will be GC'ed
+     * but TransactionProxy instances should generally be short-lived enough to avoid being moved
+     * to the old generation space and thus should be cleaned up in a timely manner as the GC
+     * runs on the young generation (eden, swap1...) space much more frequently.
+     */
+    private static class TransactionProxyCleanupPhantomReference
+                                           extends FinalizablePhantomReference<TransactionProxy> {
+
+        private final List<ActorSelection> remoteTransactionActors;
+        private final AtomicBoolean remoteTransactionActorsMB;
+        private final ActorContext actorContext;
+        private final TransactionIdentifier identifier;
+
+        protected TransactionProxyCleanupPhantomReference(TransactionProxy referent) {
+            super(referent, phantomReferenceQueue);
+
+            // Note we need to cache the relevant fields from the TransactionProxy as we can't
+            // have a hard reference to the TransactionProxy instance itself.
+
+            remoteTransactionActors = referent.remoteTransactionActors;
+            remoteTransactionActorsMB = referent.remoteTransactionActorsMB;
+            actorContext = referent.actorContext;
+            identifier = referent.identifier;
+        }
+
+        @Override
+        public void finalizeReferent() {
+            LOG.trace("Cleaning up {} Tx actors for TransactionProxy {}",
+                    remoteTransactionActors.size(), identifier);
+
+            phantomReferenceCache.remove(this);
+
+            // Access the memory barrier volatile to ensure all previous updates to the
+            // remoteTransactionActors list are visible to this thread.
+
+            if(remoteTransactionActorsMB.get()) {
+                for(ActorSelection actor : remoteTransactionActors) {
+                    LOG.trace("Sending CloseTransaction to {}", actor);
+                    actorContext.sendRemoteOperationAsync(actor,
+                            new CloseTransaction().toSerializable());
+                }
+            }
+        }
+    }
+
+    /**
+     * Stores the remote Tx actors for each requested data store path to be used by the
+     * PhantomReference to close the remote Tx's. This is only used for read-only Tx's. The
+     * remoteTransactionActorsMB volatile serves as a memory barrier to publish updates to the
+     * remoteTransactionActors list so they will be visible to the thread accessing the
+     * PhantomReference.
+     */
+    private List<ActorSelection> remoteTransactionActors;
+    private AtomicBoolean remoteTransactionActorsMB;
+
+    private final Map<String, TransactionContext> remoteTransactionPaths = new HashMap<>();
+
     private final TransactionType transactionType;
     private final ActorContext actorContext;
-    private final Map<String, TransactionContext> remoteTransactionPaths = new HashMap<>();
     private final TransactionIdentifier identifier;
     private final SchemaContext schemaContext;
     private boolean inReadyState;
 
-    public TransactionProxy(ActorContext actorContext, TransactionType transactionType,
-            SchemaContext schemaContext) {
-        this.actorContext = Preconditions.checkNotNull(actorContext, "actorContext should not be null");
-        this.transactionType = Preconditions.checkNotNull(transactionType, "transactionType should not be null");
-        this.schemaContext = Preconditions.checkNotNull(schemaContext, "schemaContext should not be null");
+    public TransactionProxy(ActorContext actorContext, TransactionType transactionType) {
+        this.actorContext = Preconditions.checkNotNull(actorContext,
+                "actorContext should not be null");
+        this.transactionType = Preconditions.checkNotNull(transactionType,
+                "transactionType should not be null");
+        this.schemaContext = Preconditions.checkNotNull(actorContext.getSchemaContext(),
+                "schemaContext should not be null");
 
         String memberName = actorContext.getCurrentMemberName();
         if(memberName == null){
@@ -99,8 +192,30 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
         this.identifier = TransactionIdentifier.builder().memberName(memberName).counter(
                 counter.getAndIncrement()).build();
 
-        LOG.debug("Created txn {}", identifier);
+        if(transactionType == TransactionType.READ_ONLY) {
+            // Read-only Tx's aren't explicitly closed by the client so we create a PhantomReference
+            // to close the remote Tx's when this instance is no longer in use and is garbage
+            // collected.
 
+            remoteTransactionActors = Lists.newArrayList();
+            remoteTransactionActorsMB = new AtomicBoolean();
+
+            TransactionProxyCleanupPhantomReference cleanup =
+                                              new TransactionProxyCleanupPhantomReference(this);
+            phantomReferenceCache.put(cleanup, cleanup);
+        }
+
+        LOG.debug("Created txn {} of type {}", identifier, transactionType);
+    }
+
+    @VisibleForTesting
+    List<Future<Object>> getRecordedOperationFutures() {
+        List<Future<Object>> recordedOperationFutures = Lists.newArrayList();
+        for(TransactionContext transactionContext : remoteTransactionPaths.values()) {
+            recordedOperationFutures.addAll(transactionContext.getRecordedOperationFutures());
+        }
+
+        return recordedOperationFutures;
     }
 
     @Override
@@ -110,7 +225,7 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
         Preconditions.checkState(transactionType != TransactionType.WRITE_ONLY,
                 "Read operation on write-only transaction is not allowed");
 
-        LOG.debug("txn {} read {}", identifier, path);
+        LOG.debug("Tx {} read {}", identifier, path);
 
         createTransactionIfMissing(actorContext, path);
 
@@ -123,7 +238,7 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
         Preconditions.checkState(transactionType != TransactionType.WRITE_ONLY,
                 "Exists operation on write-only transaction is not allowed");
 
-        LOG.debug("txn {} exists {}", identifier, path);
+        LOG.debug("Tx {} exists {}", identifier, path);
 
         createTransactionIfMissing(actorContext, path);
 
@@ -134,7 +249,7 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
         Preconditions.checkState(transactionType != TransactionType.READ_ONLY,
                 "Modification operation on read-only transaction is not allowed");
         Preconditions.checkState(!inReadyState,
-                "Transaction is sealed - further modifications are allowed");
+                "Transaction is sealed - further modifications are not allowed");
     }
 
     @Override
@@ -142,7 +257,7 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
 
         checkModificationState();
 
-        LOG.debug("txn {} write {}", identifier, path);
+        LOG.debug("Tx {} write {}", identifier, path);
 
         createTransactionIfMissing(actorContext, path);
 
@@ -154,7 +269,7 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
 
         checkModificationState();
 
-        LOG.debug("txn {} merge {}", identifier, path);
+        LOG.debug("Tx {} merge {}", identifier, path);
 
         createTransactionIfMissing(actorContext, path);
 
@@ -166,7 +281,7 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
 
         checkModificationState();
 
-        LOG.debug("txn {} delete {}", identifier, path);
+        LOG.debug("Tx {} delete {}", identifier, path);
 
         createTransactionIfMissing(actorContext, path);
 
@@ -180,31 +295,21 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
 
         inReadyState = true;
 
-        List<ActorPath> cohortPaths = new ArrayList<>();
-
-        LOG.debug("txn {} Trying to get {} transactions ready for commit", identifier,
+        LOG.debug("Tx {} Trying to get {} transactions ready for commit", identifier,
                 remoteTransactionPaths.size());
 
+        List<Future<ActorPath>> cohortPathFutures = Lists.newArrayList();
+
         for(TransactionContext transactionContext : remoteTransactionPaths.values()) {
 
-            LOG.debug("txn {} Readying transaction for shard {}", identifier,
+            LOG.debug("Tx {} Readying transaction for shard {}", identifier,
                     transactionContext.getShardName());
 
-            Object result = transactionContext.readyTransaction();
-
-            if(result.getClass().equals(ReadyTransactionReply.SERIALIZABLE_CLASS)){
-                ReadyTransactionReply reply = ReadyTransactionReply.fromSerializable(
-                        actorContext.getActorSystem(),result);
-                String resolvedCohortPath = transactionContext.getResolvedCohortPath(
-                        reply.getCohortPath().toString());
-                cohortPaths.add(actorContext.actorFor(resolvedCohortPath));
-            } else {
-                LOG.error("Was expecting {} but got {}", ReadyTransactionReply.SERIALIZABLE_CLASS,
-                        result.getClass());
-            }
+            cohortPathFutures.add(transactionContext.readyTransaction());
         }
 
-        return new ThreePhaseCommitCohortProxy(actorContext, cohortPaths, identifier.toString());
+        return new ThreePhaseCommitCohortProxy(actorContext, cohortPathFutures,
+                identifier.toString());
     }
 
     @Override
@@ -217,6 +322,13 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
         for(TransactionContext transactionContext : remoteTransactionPaths.values()) {
             transactionContext.closeTransaction();
         }
+
+        remoteTransactionPaths.clear();
+
+        if(transactionType == TransactionType.READ_ONLY) {
+            remoteTransactionActors.clear();
+            remoteTransactionActorsMB.set(true);
+        }
     }
 
     private TransactionContext transactionContext(YangInstanceIdentifier path){
@@ -249,33 +361,42 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
 
                 String transactionPath = reply.getTransactionPath();
 
-                LOG.debug("txn {} Received transaction path = {}", identifier, transactionPath);
+                LOG.debug("Tx {} Received transaction path = {}", identifier, transactionPath);
+
+                ActorSelection transactionActor = actorContext.actorSelection(transactionPath);
 
-                ActorSelection transactionActor =
-                    actorContext.actorSelection(transactionPath);
-                transactionContext =
-                    new TransactionContextImpl(shardName, transactionPath,
-                        transactionActor);
+                if(transactionType == TransactionType.READ_ONLY) {
+                    // Add the actor to the remoteTransactionActors list for access by the
+                    // cleanup PhantonReference.
+                    remoteTransactionActors.add(transactionActor);
+
+                    // Write to the memory barrier volatile to publish the above update to the
+                    // remoteTransactionActors list for thread visibility.
+                    remoteTransactionActorsMB.set(true);
+                }
+
+                transactionContext = new TransactionContextImpl(shardName, transactionPath,
+                        transactionActor, identifier, actorContext, schemaContext);
 
                 remoteTransactionPaths.put(shardName, transactionContext);
             } else {
-                LOG.error("Was expecting {} but got {}", CreateTransactionReply.SERIALIZABLE_CLASS,
-                        response.getClass());
+                throw new IllegalArgumentException(String.format(
+                        "Invalid reply type {} for CreateTransaction", response.getClass()));
             }
         } catch(Exception e){
-            LOG.error("txn {} Creating NoOpTransaction because of : {}", identifier, e.getMessage());
-            remoteTransactionPaths.put(shardName, new NoOpTransactionContext(shardName, e));
+            LOG.debug("Tx {} Creating NoOpTransaction because of : {}", identifier, e.getMessage());
+            remoteTransactionPaths.put(shardName, new NoOpTransactionContext(shardName, e, identifier));
         }
     }
 
     private interface TransactionContext {
         String getShardName();
 
-        String getResolvedCohortPath(String cohortPath);
+        void closeTransaction();
 
-        public void closeTransaction();
+        Future<ActorPath> readyTransaction();
 
-        public Object readyTransaction();
+        void writeData(YangInstanceIdentifier path, NormalizedNode<?, ?> data);
 
         void deleteData(YangInstanceIdentifier path);
 
@@ -284,23 +405,20 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
         CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> readData(
                 final YangInstanceIdentifier path);
 
-        void writeData(YangInstanceIdentifier path, NormalizedNode<?, ?> data);
-
         CheckedFuture<Boolean, ReadFailedException> dataExists(YangInstanceIdentifier path);
-    }
 
+        List<Future<Object>> getRecordedOperationFutures();
+    }
 
-    private class TransactionContextImpl implements TransactionContext {
-        private final String shardName;
-        private final String actorPath;
-        private final ActorSelection actor;
+    private static abstract class AbstractTransactionContext implements TransactionContext {
 
+        protected final TransactionIdentifier identifier;
+        protected final String shardName;
+        protected final List<Future<Object>> recordedOperationFutures = Lists.newArrayList();
 
-        private TransactionContextImpl(String shardName, String actorPath,
-            ActorSelection actor) {
+        AbstractTransactionContext(String shardName, TransactionIdentifier identifier) {
             this.shardName = shardName;
-            this.actorPath = actorPath;
-            this.actor = actor;
+            this.identifier = identifier;
         }
 
         @Override
@@ -308,53 +426,199 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
             return shardName;
         }
 
+        @Override
+        public List<Future<Object>> getRecordedOperationFutures() {
+            return recordedOperationFutures;
+        }
+    }
+
+    private static class TransactionContextImpl extends AbstractTransactionContext {
+        private final Logger LOG = LoggerFactory.getLogger(TransactionContextImpl.class);
+
+        private final ActorContext actorContext;
+        private final SchemaContext schemaContext;
+        private final String actorPath;
+        private final ActorSelection actor;
+
+        private TransactionContextImpl(String shardName, String actorPath,
+                ActorSelection actor, TransactionIdentifier identifier, ActorContext actorContext,
+                SchemaContext schemaContext) {
+            super(shardName, identifier);
+            this.actorPath = actorPath;
+            this.actor = actor;
+            this.actorContext = actorContext;
+            this.schemaContext = schemaContext;
+        }
+
         private ActorSelection getActor() {
             return actor;
         }
 
-        @Override
-        public String getResolvedCohortPath(String cohortPath) {
+        private String getResolvedCohortPath(String cohortPath) {
             return actorContext.resolvePath(actorPath, cohortPath);
         }
 
         @Override
         public void closeTransaction() {
+            LOG.debug("Tx {} closeTransaction called", identifier);
             actorContext.sendRemoteOperationAsync(getActor(), new CloseTransaction().toSerializable());
         }
 
         @Override
-        public Object readyTransaction() {
-            return actorContext.executeRemoteOperation(getActor(),
+        public Future<ActorPath> readyTransaction() {
+            LOG.debug("Tx {} readyTransaction called with {} previous recorded operations pending",
+                    identifier, recordedOperationFutures.size());
+
+            // Send the ReadyTransaction message to the Tx actor.
+
+            final Future<Object> replyFuture = actorContext.executeRemoteOperationAsync(getActor(),
                     new ReadyTransaction().toSerializable(), ActorContext.ASK_DURATION);
+
+            // Combine all the previously recorded put/merge/delete operation reply Futures and the
+            // ReadyTransactionReply Future into one Future. If any one fails then the combined
+            // Future will fail. We need all prior operations and the ready operation to succeed
+            // in order to attempt commit.
+
+            List<Future<Object>> futureList =
+                    Lists.newArrayListWithCapacity(recordedOperationFutures.size() + 1);
+            futureList.addAll(recordedOperationFutures);
+            futureList.add(replyFuture);
+
+            Future<Iterable<Object>> combinedFutures = akka.dispatch.Futures.sequence(futureList,
+                    actorContext.getActorSystem().dispatcher());
+
+            // Transform the combined Future into a Future that returns the cohort actor path from
+            // the ReadyTransactionReply. That's the end result of the ready operation.
+
+            return combinedFutures.transform(new AbstractFunction1<Iterable<Object>, ActorPath>() {
+                @Override
+                public ActorPath apply(Iterable<Object> notUsed) {
+
+                    LOG.debug("Tx {} readyTransaction: pending recorded operations succeeded",
+                            identifier);
+
+                    // At this point all the Futures succeeded and we need to extract the cohort
+                    // actor path from the ReadyTransactionReply. For the recorded operations, they
+                    // don't return any data so we're only interested that they completed
+                    // successfully. We could be paranoid and verify the correct reply types but
+                    // that really should never happen so it's not worth the overhead of
+                    // de-serializing each reply.
+
+                    // Note the Future get call here won't block as it's complete.
+                    Object serializedReadyReply = replyFuture.value().get().get();
+                    if(serializedReadyReply.getClass().equals(
+                                                     ReadyTransactionReply.SERIALIZABLE_CLASS)) {
+                        ReadyTransactionReply reply = ReadyTransactionReply.fromSerializable(
+                                actorContext.getActorSystem(), serializedReadyReply);
+
+                        String resolvedCohortPath = getResolvedCohortPath(
+                                reply.getCohortPath().toString());
+
+                        LOG.debug("Tx {} readyTransaction: resolved cohort path {}",
+                                identifier, resolvedCohortPath);
+
+                        return actorContext.actorFor(resolvedCohortPath);
+                    } else {
+                        // Throwing an exception here will fail the Future.
+
+                        throw new IllegalArgumentException(String.format("Invalid reply type {}",
+                                serializedReadyReply.getClass()));
+                    }
+                }
+            }, SAME_FAILURE_TRANSFORMER, actorContext.getActorSystem().dispatcher());
         }
 
         @Override
         public void deleteData(YangInstanceIdentifier path) {
-            actorContext.sendRemoteOperationAsync(getActor(), new DeleteData(path).toSerializable() );
+            LOG.debug("Tx {} deleteData called path = {}", identifier, path);
+            recordedOperationFutures.add(actorContext.executeRemoteOperationAsync(getActor(),
+                    new DeleteData(path).toSerializable(), ActorContext.ASK_DURATION ));
         }
 
         @Override
         public void mergeData(YangInstanceIdentifier path, NormalizedNode<?, ?> data) {
-            actorContext.sendRemoteOperationAsync(getActor(),
-                    new MergeData(path, data, schemaContext).toSerializable());
+            LOG.debug("Tx {} mergeData called path = {}", identifier, path);
+            recordedOperationFutures.add(actorContext.executeRemoteOperationAsync(getActor(),
+                    new MergeData(path, data, schemaContext).toSerializable(),
+                    ActorContext.ASK_DURATION));
+        }
+
+        @Override
+        public void writeData(YangInstanceIdentifier path, NormalizedNode<?, ?> data) {
+            LOG.debug("Tx {} writeData called path = {}", identifier, path);
+            recordedOperationFutures.add(actorContext.executeRemoteOperationAsync(getActor(),
+                    new WriteData(path, data, schemaContext).toSerializable(),
+                    ActorContext.ASK_DURATION));
         }
 
         @Override
         public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> readData(
-            final YangInstanceIdentifier path) {
+                final YangInstanceIdentifier path) {
+
+            LOG.debug("Tx {} readData called path = {}", identifier, path);
 
             final SettableFuture<Optional<NormalizedNode<?, ?>>> returnFuture = SettableFuture.create();
 
+            // If there were any previous recorded put/merge/delete operation reply Futures then we
+            // must wait for them to successfully complete. This is necessary to honor the read
+            // uncommitted semantics of the public API contract. If any one fails then fail the read.
+
+            if(recordedOperationFutures.isEmpty()) {
+                finishReadData(path, returnFuture);
+            } else {
+                LOG.debug("Tx {} readData: verifying {} previous recorded operations",
+                        identifier, recordedOperationFutures.size());
+
+                // Note: we make a copy of recordedOperationFutures to be on the safe side in case
+                // Futures#sequence accesses the passed List on a different thread, as
+                // recordedOperationFutures is not synchronized.
+
+                Future<Iterable<Object>> combinedFutures = akka.dispatch.Futures.sequence(
+                        Lists.newArrayList(recordedOperationFutures),
+                        actorContext.getActorSystem().dispatcher());
+                OnComplete<Iterable<Object>> onComplete = new OnComplete<Iterable<Object>>() {
+                    @Override
+                    public void onComplete(Throwable failure, Iterable<Object> notUsed)
+                            throws Throwable {
+                        if(failure != null) {
+                            LOG.debug("Tx {} readData: a recorded operation failed: {}",
+                                    identifier, failure);
+
+                            returnFuture.setException(new ReadFailedException(
+                                    "The read could not be performed because a previous put, merge,"
+                                    + "or delete operation failed", failure));
+                        } else {
+                            finishReadData(path, returnFuture);
+                        }
+                    }
+                };
+
+                combinedFutures.onComplete(onComplete, actorContext.getActorSystem().dispatcher());
+            }
+
+            return MappingCheckedFuture.create(returnFuture, ReadFailedException.MAPPER);
+        }
+
+        private void finishReadData(final YangInstanceIdentifier path,
+                final SettableFuture<Optional<NormalizedNode<?, ?>>> returnFuture) {
+
+            LOG.debug("Tx {} finishReadData called path = {}", identifier, path);
+
             OnComplete<Object> onComplete = new OnComplete<Object>() {
                 @Override
-                public void onComplete(Throwable failure, Object response) throws Throwable {
+                public void onComplete(Throwable failure, Object readResponse) throws Throwable {
                     if(failure != null) {
+                        LOG.debug("Tx {} read operation failed: {}", identifier, failure);
+
                         returnFuture.setException(new ReadFailedException(
                                 "Error reading data for path " + path, failure));
+
                     } else {
-                        if (response.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)) {
+                        LOG.debug("Tx {} read operation succeeded", identifier, failure);
+
+                        if (readResponse.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)) {
                             ReadDataReply reply = ReadDataReply.fromSerializable(schemaContext,
-                                    path, response);
+                                    path, readResponse);
                             if (reply.getNormalizedNode() == null) {
                                 returnFuture.set(Optional.<NormalizedNode<?, ?>>absent());
                             } else {
@@ -369,32 +633,76 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
                 }
             };
 
-            Future<Object> future = actorContext.executeRemoteOperationAsync(getActor(),
+            Future<Object> readFuture = actorContext.executeRemoteOperationAsync(getActor(),
                     new ReadData(path).toSerializable(), ActorContext.ASK_DURATION);
-            future.onComplete(onComplete, actorContext.getActorSystem().dispatcher());
-
-            return MappingCheckedFuture.create(returnFuture, ReadFailedException.MAPPER);
-        }
-
-        @Override
-        public void writeData(YangInstanceIdentifier path, NormalizedNode<?, ?> data) {
-            actorContext.sendRemoteOperationAsync(getActor(),
-                    new WriteData(path, data, schemaContext).toSerializable());
+            readFuture.onComplete(onComplete, actorContext.getActorSystem().dispatcher());
         }
 
         @Override
         public CheckedFuture<Boolean, ReadFailedException> dataExists(
                 final YangInstanceIdentifier path) {
 
+            LOG.debug("Tx {} dataExists called path = {}", identifier, path);
+
             final SettableFuture<Boolean> returnFuture = SettableFuture.create();
 
+            // If there were any previous recorded put/merge/delete operation reply Futures then we
+            // must wait for them to successfully complete. This is necessary to honor the read
+            // uncommitted semantics of the public API contract. If any one fails then fail this
+            // request.
+
+            if(recordedOperationFutures.isEmpty()) {
+                finishDataExists(path, returnFuture);
+            } else {
+                LOG.debug("Tx {} dataExists: verifying {} previous recorded operations",
+                        identifier, recordedOperationFutures.size());
+
+                // Note: we make a copy of recordedOperationFutures to be on the safe side in case
+                // Futures#sequence accesses the passed List on a different thread, as
+                // recordedOperationFutures is not synchronized.
+
+                Future<Iterable<Object>> combinedFutures = akka.dispatch.Futures.sequence(
+                        Lists.newArrayList(recordedOperationFutures),
+                        actorContext.getActorSystem().dispatcher());
+                OnComplete<Iterable<Object>> onComplete = new OnComplete<Iterable<Object>>() {
+                    @Override
+                    public void onComplete(Throwable failure, Iterable<Object> notUsed)
+                            throws Throwable {
+                        if(failure != null) {
+                            LOG.debug("Tx {} dataExists: a recorded operation failed: {}",
+                                    identifier, failure);
+
+                            returnFuture.setException(new ReadFailedException(
+                                    "The data exists could not be performed because a previous "
+                                    + "put, merge, or delete operation failed", failure));
+                        } else {
+                            finishDataExists(path, returnFuture);
+                        }
+                    }
+                };
+
+                combinedFutures.onComplete(onComplete, actorContext.getActorSystem().dispatcher());
+            }
+
+            return MappingCheckedFuture.create(returnFuture, ReadFailedException.MAPPER);
+        }
+
+        private void finishDataExists(final YangInstanceIdentifier path,
+                final SettableFuture<Boolean> returnFuture) {
+
+            LOG.debug("Tx {} finishDataExists called path = {}", identifier, path);
+
             OnComplete<Object> onComplete = new OnComplete<Object>() {
                 @Override
                 public void onComplete(Throwable failure, Object response) throws Throwable {
                     if(failure != null) {
+                        LOG.debug("Tx {} dataExists operation failed: {}", identifier, failure);
+
                         returnFuture.setException(new ReadFailedException(
-                                "Error checking exists for path " + path, failure));
+                                "Error checking data exists for path " + path, failure));
                     } else {
+                        LOG.debug("Tx {} dataExists operation succeeded", identifier, failure);
+
                         if (response.getClass().equals(DataExistsReply.SERIALIZABLE_CLASS)) {
                             returnFuture.set(Boolean.valueOf(DataExistsReply.
                                         fromSerializable(response).exists()));
@@ -409,80 +717,61 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
             Future<Object> future = actorContext.executeRemoteOperationAsync(getActor(),
                     new DataExists(path).toSerializable(), ActorContext.ASK_DURATION);
             future.onComplete(onComplete, actorContext.getActorSystem().dispatcher());
-
-            return MappingCheckedFuture.create(returnFuture, ReadFailedException.MAPPER);
         }
     }
 
-    private class NoOpTransactionContext implements TransactionContext {
+    private static class NoOpTransactionContext extends AbstractTransactionContext {
 
-        private final Logger
-            LOG = LoggerFactory.getLogger(NoOpTransactionContext.class);
+        private final Logger LOG = LoggerFactory.getLogger(NoOpTransactionContext.class);
 
-        private final String shardName;
         private final Exception failure;
 
-        private ActorRef cohort;
-
-        public NoOpTransactionContext(String shardName, Exception failure){
-            this.shardName = shardName;
+        public NoOpTransactionContext(String shardName, Exception failure,
+                TransactionIdentifier identifier){
+            super(shardName, identifier);
             this.failure = failure;
         }
 
         @Override
-        public String getShardName() {
-            return  shardName;
-
+        public void closeTransaction() {
+            LOG.debug("NoOpTransactionContext {} closeTransaction called", identifier);
         }
 
         @Override
-        public String getResolvedCohortPath(String cohortPath) {
-            return cohort.path().toString();
+        public Future<ActorPath> readyTransaction() {
+            LOG.debug("Tx {} readyTransaction called", identifier);
+            return akka.dispatch.Futures.failed(failure);
         }
 
         @Override
-        public void closeTransaction() {
-            LOG.warn("txn {} closeTransaction called", identifier);
-        }
-
-        @Override public Object readyTransaction() {
-            LOG.warn("txn {} readyTransaction called", identifier);
-            cohort = actorContext.getActorSystem().actorOf(Props.create(NoOpCohort.class));
-            return new ReadyTransactionReply(cohort.path()).toSerializable();
+        public void deleteData(YangInstanceIdentifier path) {
+            LOG.debug("Tx {} deleteData called path = {}", identifier, path);
         }
 
         @Override
-        public void deleteData(YangInstanceIdentifier path) {
-            LOG.warn("txt {} deleteData called path = {}", identifier, path);
+        public void mergeData(YangInstanceIdentifier path, NormalizedNode<?, ?> data) {
+            LOG.debug("Tx {} mergeData called path = {}", identifier, path);
         }
 
         @Override
-        public void mergeData(YangInstanceIdentifier path,
-            NormalizedNode<?, ?> data) {
-            LOG.warn("txn {} mergeData called path = {}", identifier, path);
+        public void writeData(YangInstanceIdentifier path, NormalizedNode<?, ?> data) {
+            LOG.debug("Tx {} writeData called path = {}", identifier, path);
         }
 
         @Override
         public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> readData(
             YangInstanceIdentifier path) {
-            LOG.warn("txn {} readData called path = {}", identifier, path);
+            LOG.debug("Tx {} readData called path = {}", identifier, path);
             return Futures.immediateFailedCheckedFuture(new ReadFailedException(
                     "Error reading data for path " + path, failure));
         }
 
-        @Override public void writeData(YangInstanceIdentifier path,
-            NormalizedNode<?, ?> data) {
-            LOG.warn("txn {} writeData called path = {}", identifier, path);
-        }
-
-        @Override public CheckedFuture<Boolean, ReadFailedException> dataExists(
+        @Override
+        public CheckedFuture<Boolean, ReadFailedException> dataExists(
             YangInstanceIdentifier path) {
-            LOG.warn("txn {} dataExists called path = {}", identifier, path);
+            LOG.debug("Tx {} dataExists called path = {}", identifier, path);
             return Futures.immediateFailedCheckedFuture(new ReadFailedException(
                     "Error checking exists for path " + path, failure));
         }
     }
-
-
-
 }
index afca87f0df6458a041b8d2219e3e578066513481..2a409c0300889cb34586524fa12d2381b15f4a8b 100644 (file)
@@ -1,11 +1,18 @@
+/*
+ * 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.jmx.mbeans.shard;
 
 import java.util.HashMap;
 import java.util.Map;
 
 /**
- * @author: syedbahm
- * Date: 7/16/14
+ * @author Basheeruddin syedbahm@cisco.com
+ *
  */
 public class ShardMBeanFactory {
     private static Map<String, ShardStats> shardMBeans =
index c6c1579ce336dc78e64ecc6b79042c30eee28148..22ad8e7f5a3408ff7457876635ced85f19ad2842 100644 (file)
@@ -1,3 +1,11 @@
+/*
+ * 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.jmx.mbeans.shard;
 
 import org.opendaylight.controller.cluster.datastore.jmx.mbeans.AbstractBaseMBean;
@@ -6,37 +14,41 @@ import java.text.SimpleDateFormat;
 import java.util.Date;
 
 /**
- * @author: syedbahm
+ * @author  Basheeruddin syedbahm@cisco.com
  */
 public class ShardStats extends AbstractBaseMBean implements ShardStatsMBean {
 
     private final String shardName;
 
-    private Long committedTransactionsCount = 0L;
+    private long committedTransactionsCount = 0L;
 
-    private Long readOnlyTransactionCount = 0L;
+    private long readOnlyTransactionCount = 0L;
 
-    private Long writeOnlyTransactionCount = 0L;
+    private long writeOnlyTransactionCount = 0L;
 
-    private Long readWriteTransactionCount = 0L;
+    private long readWriteTransactionCount = 0L;
 
     private String leader;
 
     private String raftState;
 
-    private Long lastLogTerm = -1L;
+    private long lastLogTerm = -1L;
 
-    private Long lastLogIndex = -1L;
+    private long lastLogIndex = -1L;
 
-    private Long currentTerm = -1L;
+    private long currentTerm = -1L;
 
-    private Long commitIndex = -1L;
+    private long commitIndex = -1L;
 
-    private Long lastApplied = -1L;
+    private long lastApplied = -1L;
 
     private Date lastCommittedTransactionTime = new Date(0L);
 
-    private Long failedTransactionsCount = 0L;
+    private long failedTransactionsCount = 0L;
+
+    private long failedReadTransactionsCount = 0L;
+
+    private long abortTransactionsCount = 0L;
 
     private SimpleDateFormat sdf =
         new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
@@ -52,7 +64,7 @@ public class ShardStats extends AbstractBaseMBean implements ShardStatsMBean {
     }
 
     @Override
-    public Long getCommittedTransactionsCount() {
+    public long getCommittedTransactionsCount() {
         return committedTransactionsCount;
     }
 
@@ -64,35 +76,35 @@ public class ShardStats extends AbstractBaseMBean implements ShardStatsMBean {
         return raftState;
     }
 
-    @Override public Long getReadOnlyTransactionCount() {
+    @Override public long getReadOnlyTransactionCount() {
         return readOnlyTransactionCount;
     }
 
-    @Override public Long getWriteOnlyTransactionCount() {
+    @Override public long getWriteOnlyTransactionCount() {
         return writeOnlyTransactionCount;
     }
 
-    @Override public Long getReadWriteTransactionCount() {
+    @Override public long getReadWriteTransactionCount() {
         return readWriteTransactionCount;
     }
 
-    @Override public Long getLastLogIndex() {
+    @Override public long getLastLogIndex() {
         return lastLogIndex;
     }
 
-    @Override public Long getLastLogTerm() {
+    @Override public long getLastLogTerm() {
         return lastLogTerm;
     }
 
-    @Override public Long getCurrentTerm() {
+    @Override public long getCurrentTerm() {
         return currentTerm;
     }
 
-    @Override public Long getCommitIndex() {
+    @Override public long getCommitIndex() {
         return commitIndex;
     }
 
-    @Override public Long getLastApplied() {
+    @Override public long getLastApplied() {
         return lastApplied;
     }
 
@@ -102,26 +114,44 @@ public class ShardStats extends AbstractBaseMBean implements ShardStatsMBean {
         return sdf.format(lastCommittedTransactionTime);
     }
 
-    @Override public Long getFailedTransactionsCount() {
+    @Override public long getFailedTransactionsCount() {
         return failedTransactionsCount;
     }
 
-    public Long incrementCommittedTransactionCount() {
+    @Override public long getFailedReadTransactionsCount() {
+        return failedReadTransactionsCount;
+    }
+
+    @Override public long getAbortTransactionsCount() {
+        return abortTransactionsCount;
+    }
+
+    public long incrementCommittedTransactionCount() {
         return committedTransactionsCount++;
     }
 
-    public Long incrementReadOnlyTransactionCount() {
+    public long incrementReadOnlyTransactionCount() {
         return readOnlyTransactionCount++;
     }
 
-    public Long incrementWriteOnlyTransactionCount() {
+    public long incrementWriteOnlyTransactionCount() {
         return writeOnlyTransactionCount++;
     }
 
-    public Long incrementReadWriteTransactionCount() {
+    public long incrementReadWriteTransactionCount() {
         return readWriteTransactionCount++;
     }
 
+    public long incrementFailedTransactionsCount() {
+        return failedTransactionsCount++;
+    }
+
+    public long incrementFailedReadTransactionsCount() {
+        return failedReadTransactionsCount++;
+    }
+
+    public long incrementAbortTransactionsCount () { return abortTransactionsCount++;}
+
     public void setLeader(String leader) {
         this.leader = leader;
     }
@@ -130,23 +160,23 @@ public class ShardStats extends AbstractBaseMBean implements ShardStatsMBean {
         this.raftState = raftState;
     }
 
-    public void setLastLogTerm(Long lastLogTerm) {
+    public void setLastLogTerm(long lastLogTerm) {
         this.lastLogTerm = lastLogTerm;
     }
 
-    public void setLastLogIndex(Long lastLogIndex) {
+    public void setLastLogIndex(long lastLogIndex) {
         this.lastLogIndex = lastLogIndex;
     }
 
-    public void setCurrentTerm(Long currentTerm) {
+    public void setCurrentTerm(long currentTerm) {
         this.currentTerm = currentTerm;
     }
 
-    public void setCommitIndex(Long commitIndex) {
+    public void setCommitIndex(long commitIndex) {
         this.commitIndex = commitIndex;
     }
 
-    public void setLastApplied(Long lastApplied) {
+    public void setLastApplied(long lastApplied) {
         this.lastApplied = lastApplied;
     }
 
@@ -171,8 +201,28 @@ public class ShardStats extends AbstractBaseMBean implements ShardStatsMBean {
         return JMX_CATEGORY_SHARD;
     }
 
+    /**
+     * resets the counters related to transactions
+     */
+
+    public void resetTransactionCounters(){
+        committedTransactionsCount = 0L;
+
+        readOnlyTransactionCount = 0L;
+
+        writeOnlyTransactionCount = 0L;
+
+        readWriteTransactionCount = 0L;
+
+        lastCommittedTransactionTime = new Date(0L);
+
+        failedTransactionsCount = 0L;
+
+        failedReadTransactionsCount = 0L;
+
+        abortTransactionsCount = 0L;
 
-    public void incrementFailedTransactionsCount() {
-        this.failedTransactionsCount++;
     }
+
+
 }
index b8b220ee82fae3851e1f8bcc70a04f74b1c31560..c16f8421bfb3f7ea8e75ab9bd366859693ff98a8 100644 (file)
@@ -6,30 +6,36 @@ package org.opendaylight.controller.cluster.datastore.jmx.mbeans.shard;
 public interface ShardStatsMBean {
     String getShardName();
 
-    Long getCommittedTransactionsCount();
+    long getCommittedTransactionsCount();
 
     String getLeader();
 
     String getRaftState();
 
-    Long getReadOnlyTransactionCount();
+    long getReadOnlyTransactionCount();
 
-    Long getWriteOnlyTransactionCount();
+    long getWriteOnlyTransactionCount();
 
-    Long getReadWriteTransactionCount();
+    long getReadWriteTransactionCount();
 
-    Long getLastLogIndex();
+    long getLastLogIndex();
 
-    Long getLastLogTerm();
+    long getLastLogTerm();
 
-    Long getCurrentTerm();
+    long getCurrentTerm();
 
-    Long getCommitIndex();
+    long getCommitIndex();
 
-    Long getLastApplied();
+    long getLastApplied();
 
     String getLastCommittedTransactionTime();
 
-    Long getFailedTransactionsCount();
+    long getFailedTransactionsCount();
+
+    long getFailedReadTransactionsCount();
+
+    long getAbortTransactionsCount();
+
+    void resetTransactionCounters();
 
 }
index f584467ee91b37f2b0866cb9a39556eba3c9ace8..f5a6a348415308377d755011b133796659d3f27d 100644 (file)
@@ -9,14 +9,13 @@
 package org.opendaylight.controller.cluster.datastore.messages;
 
 import com.google.common.base.Preconditions;
-import org.opendaylight.controller.protobuff.messages.shard.ShardManagerMessages;
 
 /**
  * The FindPrimary message is used to locate the primary of any given shard
  *
  */
 public class FindPrimary implements SerializableMessage{
-  public static final Class SERIALIZABLE_CLASS = ShardManagerMessages.FindPrimary.class;
+  public static final Class SERIALIZABLE_CLASS = FindPrimary.class;
     private final String shardName;
 
     public FindPrimary(String shardName){
@@ -32,10 +31,10 @@ public class FindPrimary implements SerializableMessage{
 
   @Override
   public Object toSerializable() {
-    return ShardManagerMessages.FindPrimary.newBuilder().setShardName(shardName).build();
+    return this;
   }
 
   public static FindPrimary fromSerializable(Object message){
-    return new FindPrimary(((ShardManagerMessages.FindPrimary)message).getShardName());
+    return (FindPrimary) message;
   }
 }
index 69502837bcc6c114a1daa98986006ed0bd206aab..a2f6701524a7f4d2f42a4ce93b4463d368414659 100644 (file)
@@ -8,10 +8,9 @@
 
 package org.opendaylight.controller.cluster.datastore.messages;
 
-import org.opendaylight.controller.protobuff.messages.shard.ShardManagerMessages;
 
 public class PrimaryFound implements SerializableMessage {
-  public static final Class SERIALIZABLE_CLASS = ShardManagerMessages.PrimaryFound.class;
+  public static final Class SERIALIZABLE_CLASS = PrimaryFound.class;
   private final String primaryPath;
 
   public PrimaryFound(String primaryPath) {
@@ -49,10 +48,10 @@ public class PrimaryFound implements SerializableMessage {
 
   @Override
   public Object toSerializable() {
-    return  ShardManagerMessages.PrimaryFound.newBuilder().setPrimaryPath(primaryPath).build();
+    return  this;
   }
 
   public static PrimaryFound fromSerializable(Object message){
-    return new PrimaryFound(((ShardManagerMessages.PrimaryFound)message).getPrimaryPath());
+    return (PrimaryFound) message;
   }
 }
index 057028c469416df2767a067ef5e36e4256babd35..731a5364db247d52642e31da6e105ea655793196 100644 (file)
@@ -9,10 +9,9 @@
 package org.opendaylight.controller.cluster.datastore.messages;
 
 import com.google.common.base.Preconditions;
-import org.opendaylight.controller.protobuff.messages.shard.ShardManagerMessages;
 
 public class PrimaryNotFound implements SerializableMessage {
-  public static final Class SERIALIZABLE_CLASS = ShardManagerMessages.PrimaryNotFound.class;
+  public static final Class SERIALIZABLE_CLASS = PrimaryNotFound.class;
 
     private final String shardName;
 
@@ -42,10 +41,10 @@ public class PrimaryNotFound implements SerializableMessage {
 
   @Override
   public Object toSerializable() {
-    return ShardManagerMessages.PrimaryNotFound.newBuilder().setShardName(shardName).build();
+    return this;
   }
 
   public static PrimaryNotFound fromSerializable(Object message){
-    return new PrimaryNotFound(((ShardManagerMessages.PrimaryNotFound)message).getShardName());
+    return (PrimaryNotFound) message;
   }
 }
index e12a9663d1fca8a969c25166f38986ea19eab51a..818a8ca8b390ec2fcb33f2cad91ad597fa7ca758 100644 (file)
@@ -23,6 +23,8 @@ import org.opendaylight.controller.cluster.datastore.messages.FindLocalShard;
 import org.opendaylight.controller.cluster.datastore.messages.FindPrimary;
 import org.opendaylight.controller.cluster.datastore.messages.LocalShardFound;
 import org.opendaylight.controller.cluster.datastore.messages.PrimaryFound;
+import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -50,10 +52,13 @@ public class ActorContext {
     public static final Duration AWAIT_DURATION =
         Duration.create(5, TimeUnit.SECONDS);
 
+    public static final String MAILBOX = "bounded-mailbox";
+
     private final ActorSystem actorSystem;
     private final ActorRef shardManager;
     private final ClusterWrapper clusterWrapper;
     private final Configuration configuration;
+    private volatile SchemaContext schemaContext;
 
     public ActorContext(ActorSystem actorSystem, ActorRef shardManager,
         ClusterWrapper clusterWrapper,
@@ -80,6 +85,17 @@ public class ActorContext {
         return actorSystem.actorSelection(actorPath);
     }
 
+    public void setSchemaContext(SchemaContext schemaContext) {
+        this.schemaContext = schemaContext;
+
+        if(shardManager != null) {
+            shardManager.tell(new UpdateSchemaContext(schemaContext), null);
+        }
+    }
+
+    public SchemaContext getSchemaContext() {
+        return schemaContext;
+    }
 
     /**
      * Finds the primary for a given shard
index 592bc49d9e40648a53e6d448666d34c58f2f4184..f5a0d3783ab011728ab0688db60b404a9c53719e 100644 (file)
@@ -1,7 +1,7 @@
 package org.opendaylight.controller.config.yang.config.distributed_datastore_provider;
 
 import org.opendaylight.controller.cluster.datastore.DistributedDataStoreFactory;
-import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreConfigProperties;
+import org.opendaylight.controller.cluster.datastore.DistributedDataStoreProperties;
 
 public class DistributedConfigDataStoreProviderModule extends
     org.opendaylight.controller.config.yang.config.distributed_datastore_provider.AbstractDistributedConfigDataStoreProviderModule {
@@ -26,10 +26,16 @@ public class DistributedConfigDataStoreProviderModule extends
 
     @Override
     public java.lang.AutoCloseable createInstance() {
+
+        ConfigProperties props = getConfigProperties();
+        if(props == null) {
+            props = new ConfigProperties();
+        }
+
         return DistributedDataStoreFactory.createInstance("config", getConfigSchemaServiceDependency(),
-                InMemoryDOMDataStoreConfigProperties.create(getMaxShardDataChangeExecutorPoolSize(),
-                        getMaxShardDataChangeExecutorQueueSize(),
-                        getMaxShardDataChangeListenerQueueSize()));
+                new DistributedDataStoreProperties(props.getMaxShardDataChangeExecutorPoolSize(),
+                        props.getMaxShardDataChangeExecutorQueueSize(),
+                        props.getMaxShardDataChangeListenerQueueSize(),
+                        props.getShardTransactionIdleTimeoutInMinutes()));
     }
-
 }
index 9eb72d64d0e90079b5fe1ae7a0405bc5a522b8d0..443334d11f65378871da7a6f2ae97097d4c2eb87 100644 (file)
@@ -1,7 +1,7 @@
 package org.opendaylight.controller.config.yang.config.distributed_datastore_provider;
 
 import org.opendaylight.controller.cluster.datastore.DistributedDataStoreFactory;
-import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreConfigProperties;
+import org.opendaylight.controller.cluster.datastore.DistributedDataStoreProperties;
 
 public class DistributedOperationalDataStoreProviderModule extends
     org.opendaylight.controller.config.yang.config.distributed_datastore_provider.AbstractDistributedOperationalDataStoreProviderModule {
@@ -26,11 +26,18 @@ public class DistributedOperationalDataStoreProviderModule extends
 
     @Override
     public java.lang.AutoCloseable createInstance() {
+
+        OperationalProperties props = getOperationalProperties();
+        if(props == null) {
+            props = new OperationalProperties();
+        }
+
         return DistributedDataStoreFactory.createInstance("operational",
                 getOperationalSchemaServiceDependency(),
-                InMemoryDOMDataStoreConfigProperties.create(getMaxShardDataChangeExecutorPoolSize(),
-                        getMaxShardDataChangeExecutorQueueSize(),
-                        getMaxShardDataChangeListenerQueueSize()));
+                new DistributedDataStoreProperties(props.getMaxShardDataChangeExecutorPoolSize(),
+                        props.getMaxShardDataChangeExecutorQueueSize(),
+                        props.getMaxShardDataChangeListenerQueueSize(),
+                        props.getShardTransactionIdleTimeoutInMinutes()));
     }
 
 }
index 8af9bd07d793cfb0eb0dae33414b6631d109e4a9..c29f93bb073cb712df045bf4839cc247a2b49111 100644 (file)
@@ -1,5 +1,10 @@
 
 odl-cluster-data {
+  bounded-mailbox {
+    mailbox-type = "org.opendaylight.controller.common.actor.MeteredBoundedMailbox"
+    mailbox-capacity = 1000
+    mailbox-push-timeout-time = 100ms
+  }
   akka {
     loggers = ["akka.event.slf4j.Slf4jLogger"]
     cluster {
index ecb823e624709bc84f167e522efa09bba06e53f8..a9a8a1ad986c65835018f80773707561473934b8 100644 (file)
@@ -36,36 +36,48 @@ module distributed-datastore-provider {
                 config:java-name-prefix DistributedOperationalDataStoreProvider;
      }
 
+    grouping data-store-properties {
+        leaf max-shard-data-change-executor-queue-size {
+            default 1000;
+            type uint16;
+            description "The maximum queue size for each shard's data store data change notification executor.";
+         }
+
+         leaf max-shard-data-change-executor-pool-size {
+            default 20;
+            type uint16;
+            description "The maximum thread pool size for each shard's data store data change notification executor.";
+         }
+
+         leaf max-shard-data-change-listener-queue-size {
+            default 1000;
+            type uint16;
+            description "The maximum queue size for each shard's data store data change listeners.";
+         }
+         
+         leaf shard-transaction-idle-timeout-in-minutes {
+            default 10;
+            type uint16;
+            description "The maximum amount of time a shard transaction can be idle without receiving any messages before it self-destructs.";
+         }
+    }
+    
     // Augments the 'configuration' choice node under modules/module.
     augment "/config:modules/config:module/config:configuration" {
         case distributed-config-datastore-provider {
             when "/config:modules/config:module/config:type = 'distributed-config-datastore-provider'";
-            container config-schema-service {
-                uses config:service-ref {
-                    refine type {
-                        mandatory false;
-                        config:required-identity sal:schema-service;
+                container config-schema-service {
+                    uses config:service-ref {
+                        refine type {
+                            mandatory false;
+                            config:required-identity sal:schema-service;
+                        }
                     }
                 }
-            }
 
-            leaf max-shard-data-change-executor-queue-size {
-                default 1000;
-                type uint16;
-                description "The maximum queue size for each shard's data store data change notification executor.";
-            }
-
-            leaf max-shard-data-change-executor-pool-size {
-                default 20;
-                type uint16;
-                description "The maximum thread pool size for each shard's data store data change notification executor.";
-            }
-
-            leaf max-shard-data-change-listener-queue-size {
-                default 1000;
-                type uint16;
-                description "The maximum queue size for each shard's data store data change listeners.";
-            }
+                container config-properties {
+                    uses data-store-properties;
+                }
         }
     }
 
@@ -82,23 +94,9 @@ module distributed-datastore-provider {
                     }
                 }
 
-            leaf max-shard-data-change-executor-queue-size {
-                default 1000;
-                type uint16;
-                description "The maximum queue size for each shard's data store data change notification executor.";
-            }
-
-            leaf max-shard-data-change-executor-pool-size {
-                default 20;
-                type uint16;
-                description "The maximum thread pool size for each shard's data store data change notification executor.";
-            }
-
-            leaf max-shard-data-change-listener-queue-size {
-                default 1000;
-                type uint16;
-                description "The maximum queue size for each shard's data store data change listeners.";
-            }
-            }
+                container operational-properties {
+                    uses data-store-properties;
+                }
         }
+    }
 }
index 036b00a4c94bd46e77c480c32a16b7ad0b71b3f6..6f131f301fe8985dade813ce2b00bf994c7a1bf6 100644 (file)
@@ -14,6 +14,7 @@ import akka.actor.ActorSelection;
 import akka.actor.Props;
 import akka.event.Logging;
 import akka.testkit.JavaTestKit;
+
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier;
 import org.opendaylight.controller.cluster.datastore.messages.CommitTransaction;
@@ -30,6 +31,8 @@ import org.opendaylight.controller.cluster.datastore.messages.WriteData;
 import org.opendaylight.controller.cluster.datastore.messages.WriteDataReply;
 import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
 import scala.concurrent.Await;
 import scala.concurrent.Future;
 import scala.concurrent.duration.FiniteDuration;
@@ -58,22 +61,23 @@ public class BasicIntegrationTest extends AbstractActorTest {
                 ShardIdentifier.builder().memberName("member-1")
                     .shardName("inventory").type("config").build();
 
-            final Props props = Shard.props(identifier, Collections.EMPTY_MAP, null);
+            final SchemaContext schemaContext = TestModel.createTestContext();
+            DatastoreContext datastoreContext = new DatastoreContext();
+
+            final Props props = Shard.props(identifier, Collections.EMPTY_MAP, datastoreContext);
             final ActorRef shard = getSystem().actorOf(props);
 
-            new Within(duration("5 seconds")) {
+            new Within(duration("10 seconds")) {
+                @Override
                 protected void run() {
-
-
-                    shard.tell(
-                        new UpdateSchemaContext(TestModel.createTestContext()),
-                        getRef());
+                    shard.tell(new UpdateSchemaContext(schemaContext), getRef());
 
 
                     // Wait for a specific log message to show up
                     final boolean result =
                         new JavaTestKit.EventFilter<Boolean>(Logging.Info.class
                         ) {
+                            @Override
                             protected Boolean run() {
                                 return true;
                             }
@@ -87,7 +91,8 @@ public class BasicIntegrationTest extends AbstractActorTest {
                     shard.tell(new CreateTransactionChain().toSerializable(), getRef());
 
                     final ActorSelection transactionChain =
-                        new ExpectMsg<ActorSelection>(duration("1 seconds"), "CreateTransactionChainReply") {
+                        new ExpectMsg<ActorSelection>(duration("3 seconds"), "CreateTransactionChainReply") {
+                            @Override
                             protected ActorSelection match(Object in) {
                                 if (in.getClass().equals(CreateTransactionChainReply.SERIALIZABLE_CLASS)) {
                                     ActorPath transactionChainPath =
@@ -109,7 +114,8 @@ public class BasicIntegrationTest extends AbstractActorTest {
                     transactionChain.tell(new CreateTransaction("txn-1", TransactionProxy.TransactionType.WRITE_ONLY.ordinal() ).toSerializable(), getRef());
 
                     final ActorSelection transaction =
-                        new ExpectMsg<ActorSelection>(duration("1 seconds"), "CreateTransactionReply") {
+                        new ExpectMsg<ActorSelection>(duration("3 seconds"), "CreateTransactionReply") {
+                            @Override
                             protected ActorSelection match(Object in) {
                                 if (CreateTransactionReply.SERIALIZABLE_CLASS.equals(in.getClass())) {
                                     CreateTransactionReply reply = CreateTransactionReply.fromSerializable(in);
@@ -128,10 +134,11 @@ public class BasicIntegrationTest extends AbstractActorTest {
 
                     // 3. Write some data
                     transaction.tell(new WriteData(TestModel.TEST_PATH,
-                        ImmutableNodes.containerNode(TestModel.TEST_QNAME), TestModel.createTestContext()).toSerializable(),
+                        ImmutableNodes.containerNode(TestModel.TEST_QNAME), schemaContext).toSerializable(),
                         getRef());
 
-                    Boolean writeDone = new ExpectMsg<Boolean>(duration("1 seconds"), "WriteDataReply") {
+                    Boolean writeDone = new ExpectMsg<Boolean>(duration("3 seconds"), "WriteDataReply") {
+                        @Override
                         protected Boolean match(Object in) {
                             if (in.getClass().equals(WriteDataReply.SERIALIZABLE_CLASS)) {
                                 return true;
@@ -150,7 +157,8 @@ public class BasicIntegrationTest extends AbstractActorTest {
                     transaction.tell(new ReadyTransaction().toSerializable(), getRef());
 
                     final ActorSelection cohort =
-                        new ExpectMsg<ActorSelection>(duration("1 seconds"), "ReadyTransactionReply") {
+                        new ExpectMsg<ActorSelection>(duration("3 seconds"), "ReadyTransactionReply") {
+                            @Override
                             protected ActorSelection match(Object in) {
                                 if (in.getClass().equals(ReadyTransactionReply.SERIALIZABLE_CLASS)) {
                                     ActorPath cohortPath =
@@ -173,7 +181,8 @@ public class BasicIntegrationTest extends AbstractActorTest {
                     cohort.tell(new PreCommitTransaction().toSerializable(), getRef());
 
                     Boolean preCommitDone =
-                        new ExpectMsg<Boolean>(duration("1 seconds"), "PreCommitTransactionReply") {
+                        new ExpectMsg<Boolean>(duration("3 seconds"), "PreCommitTransactionReply") {
+                            @Override
                             protected Boolean match(Object in) {
                                 if (in.getClass().equals(PreCommitTransactionReply.SERIALIZABLE_CLASS)) {
                                     return true;
index 400eab1d8eb26f8857508ff244668370eb3d9b13..be43911fe12f26caca64c82b0cfc7ca43d8e505d 100644 (file)
@@ -8,7 +8,7 @@ import org.opendaylight.controller.cluster.datastore.modification.WriteModificat
 import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
 import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
 import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
-import org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages;
+import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
 import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 
index b2ee4a49fee1b40ee86730da0044f5f987b090a9..e653c3d3717351182a6a57cf570c4a6bf6449500 100644 (file)
@@ -3,7 +3,7 @@ package org.opendaylight.controller.cluster.datastore;
 
 import akka.actor.ActorRef;
 import akka.actor.Props;
-import junit.framework.Assert;
+import org.junit.Assert;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.messages.DataChanged;
 import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
@@ -47,7 +47,7 @@ public class DataChangeListenerProxyTest extends AbstractActorTest {
 
     @Override
     public Set<YangInstanceIdentifier> getRemovedPaths() {
-      Set<YangInstanceIdentifier>ids = new HashSet();
+      Set<YangInstanceIdentifier>ids = new HashSet<>();
       ids.add( CompositeModel.TEST_PATH);
       return ids;
     }
@@ -73,9 +73,8 @@ public class DataChangeListenerProxyTest extends AbstractActorTest {
         final Props props = Props.create(MessageCollectorActor.class);
         final ActorRef actorRef = getSystem().actorOf(props);
 
-        DataChangeListenerProxy dataChangeListenerProxy =
-            new DataChangeListenerProxy(TestModel.createTestContext(),
-                getSystem().actorSelection(actorRef.path()));
+        DataChangeListenerProxy dataChangeListenerProxy = new DataChangeListenerProxy(
+                TestModel.createTestContext(), getSystem().actorSelection(actorRef.path()));
 
         dataChangeListenerProxy.onDataChanged(new MockDataChangedEvent());
 
index 26ec583b3e058108f9cc18517f5f6909847f5cd6..b39cc84ceff6943d045c7a609afcbb996e212b31 100644 (file)
@@ -24,9 +24,9 @@ import static org.junit.Assert.assertTrue;
 public class DataChangeListenerTest extends AbstractActorTest {
 
     private static class MockDataChangedEvent implements AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> {
-       Map<YangInstanceIdentifier,NormalizedNode<?,?>> createdData = new HashMap();
-       Map<YangInstanceIdentifier,NormalizedNode<?,?>> updatedData = new HashMap();
-       Map<YangInstanceIdentifier,NormalizedNode<?,?>> originalData = new HashMap();
+       Map<YangInstanceIdentifier,NormalizedNode<?,?>> createdData = new HashMap<>();
+       Map<YangInstanceIdentifier,NormalizedNode<?,?>> updatedData = new HashMap<>();
+       Map<YangInstanceIdentifier,NormalizedNode<?,?>> originalData = new HashMap<>();
 
 
 
@@ -90,11 +90,12 @@ public class DataChangeListenerTest extends AbstractActorTest {
     public void testDataChangedWhenNotificationsAreEnabled(){
         new JavaTestKit(getSystem()) {{
             final MockDataChangeListener listener = new MockDataChangeListener();
-            final Props props = DataChangeListener.props(CompositeModel.createTestContext(),listener,CompositeModel.FAMILY_PATH );
+            final Props props = DataChangeListener.props(listener);
             final ActorRef subject =
                 getSystem().actorOf(props, "testDataChangedNotificationsEnabled");
 
             new Within(duration("1 seconds")) {
+                @Override
                 protected void run() {
 
                     // Let the DataChangeListener know that notifications should
@@ -107,6 +108,7 @@ public class DataChangeListenerTest extends AbstractActorTest {
 
                     final Boolean out = new ExpectMsg<Boolean>(duration("800 millis"), "dataChanged") {
                         // do not put code outside this method, will run afterwards
+                        @Override
                         protected Boolean match(Object in) {
                             if (in != null && in.getClass().equals(DataChangedReply.class)) {
 
@@ -123,8 +125,6 @@ public class DataChangeListenerTest extends AbstractActorTest {
 
                     expectNoMsg();
                 }
-
-
             };
         }};
     }
@@ -133,11 +133,12 @@ public class DataChangeListenerTest extends AbstractActorTest {
     public void testDataChangedWhenNotificationsAreDisabled(){
         new JavaTestKit(getSystem()) {{
             final MockDataChangeListener listener = new MockDataChangeListener();
-            final Props props = DataChangeListener.props(CompositeModel.createTestContext(),listener,CompositeModel.FAMILY_PATH );
+            final Props props = DataChangeListener.props(listener);
             final ActorRef subject =
                 getSystem().actorOf(props, "testDataChangedNotificationsDisabled");
 
             new Within(duration("1 seconds")) {
+                @Override
                 protected void run() {
 
                     subject.tell(
@@ -146,8 +147,6 @@ public class DataChangeListenerTest extends AbstractActorTest {
 
                     expectNoMsg();
                 }
-
-
             };
         }};
     }
index 49408b741019c98debbe70b37857d871d0f80b8b..21aa00e9e0b98c60b2d117fa67f36864e0c7700a 100644 (file)
@@ -3,9 +3,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;
@@ -69,10 +72,13 @@ public class DistributedDataStoreIntegrationTest {
             {
 
                 new Within(duration("10 seconds")) {
+                    @Override
                     protected void run() {
                         try {
                             final DistributedDataStore distributedDataStore =
-                                new DistributedDataStore(getSystem(), "config", new MockClusterWrapper(), configuration, null);
+                                new DistributedDataStore(getSystem(), "config",
+                                        new MockClusterWrapper(), configuration,
+                                        new DistributedDataStoreProperties());
 
                             distributedDataStore.onGlobalContextUpdated(TestModel.createTestContext());
 
@@ -80,6 +86,7 @@ public class DistributedDataStoreIntegrationTest {
                             final boolean result =
                                 new JavaTestKit.EventFilter<Boolean>(Logging.Info.class
                                     ) {
+                                    @Override
                                     protected Boolean run() {
                                         return true;
                                     }
@@ -150,6 +157,7 @@ public class DistributedDataStoreIntegrationTest {
             {
 
                 new Within(duration("10 seconds")) {
+                    @Override
                     protected void run() {
                         try {
                             final DistributedDataStore distributedDataStore =
@@ -164,6 +172,7 @@ public class DistributedDataStoreIntegrationTest {
                                 new JavaTestKit.EventFilter<Boolean>(
                                     Logging.Info.class
                                 ) {
+                                    @Override
                                     protected Boolean run() {
                                         return true;
                                     }
index 69590e62fb1b5886fc0b5fb1223706d02c1706cd..cb473cb9360e03656ea83d0212ef18b70237a92e 100644 (file)
@@ -3,6 +3,7 @@ package org.opendaylight.controller.cluster.datastore;
 import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
 import akka.actor.Props;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -63,12 +64,14 @@ public class DistributedDataStoreTest extends AbstractActorTest{
 
     }
 
+    @SuppressWarnings("resource")
     @Test
     public void testConstructor(){
         ActorSystem actorSystem = mock(ActorSystem.class);
 
         new DistributedDataStore(actorSystem, "config",
-            mock(ClusterWrapper.class), mock(Configuration.class), null);
+            mock(ClusterWrapper.class), mock(Configuration.class),
+            new DistributedDataStoreProperties());
 
         verify(actorSystem).actorOf(any(Props.class), eq("shardmanager-config"));
     }
index 499b4e1f3111d097cc0696aa7cd23367fc4c591d..1feefd1c1fbcde3381d91332bd8d977048e7e074 100644 (file)
@@ -42,11 +42,12 @@ public class ShardManagerTest {
         new JavaTestKit(system) {{
             final Props props = ShardManager
                 .props("config", new MockClusterWrapper(),
-                    new MockConfiguration(), null);
+                    new MockConfiguration(), new DatastoreContext());
             final TestActorRef<ShardManager> subject =
                 TestActorRef.create(system, props);
 
-            new Within(duration("1 seconds")) {
+            new Within(duration("10 seconds")) {
+                @Override
                 protected void run() {
 
                     subject.tell(new FindPrimary("inventory").toSerializable(), getRef());
@@ -66,11 +67,12 @@ public class ShardManagerTest {
         new JavaTestKit(system) {{
             final Props props = ShardManager
                 .props("config", new MockClusterWrapper(),
-                    new MockConfiguration(), null);
+                    new MockConfiguration(), new DatastoreContext());
             final TestActorRef<ShardManager> subject =
                 TestActorRef.create(system, props);
 
-            new Within(duration("1 seconds")) {
+            new Within(duration("10 seconds")) {
+                @Override
                 protected void run() {
 
                     subject.tell(new FindPrimary(Shard.DEFAULT_NAME).toSerializable(), getRef());
@@ -89,16 +91,18 @@ public class ShardManagerTest {
         new JavaTestKit(system) {{
             final Props props = ShardManager
                 .props("config", new MockClusterWrapper(),
-                    new MockConfiguration(), null);
+                    new MockConfiguration(), new DatastoreContext());
             final TestActorRef<ShardManager> subject =
                 TestActorRef.create(system, props);
 
-            new Within(duration("1 seconds")) {
+            new Within(duration("10 seconds")) {
+                @Override
                 protected void run() {
 
                     subject.tell(new FindLocalShard("inventory"), getRef());
 
-                    final String out = new ExpectMsg<String>(duration("1 seconds"), "find local") {
+                    final String out = new ExpectMsg<String>(duration("10 seconds"), "find local") {
+                        @Override
                         protected String match(Object in) {
                             if (in instanceof LocalShardNotFound) {
                                 return ((LocalShardNotFound) in).getShardName();
@@ -124,16 +128,18 @@ public class ShardManagerTest {
         new JavaTestKit(system) {{
             final Props props = ShardManager
                 .props("config", mockClusterWrapper,
-                    new MockConfiguration(), null);
+                    new MockConfiguration(), new DatastoreContext());
             final TestActorRef<ShardManager> subject =
                 TestActorRef.create(system, props);
 
-            new Within(duration("1 seconds")) {
+            new Within(duration("10 seconds")) {
+                @Override
                 protected void run() {
 
                     subject.tell(new FindLocalShard(Shard.DEFAULT_NAME), getRef());
 
-                    final ActorRef out = new ExpectMsg<ActorRef>(duration("1 seconds"), "find local") {
+                    final ActorRef out = new ExpectMsg<ActorRef>(duration("10 seconds"), "find local") {
+                        @Override
                         protected ActorRef match(Object in) {
                             if (in instanceof LocalShardFound) {
                                 return ((LocalShardFound) in).getPath();
@@ -158,12 +164,13 @@ public class ShardManagerTest {
         new JavaTestKit(system) {{
             final Props props = ShardManager
                 .props("config", new MockClusterWrapper(),
-                    new MockConfiguration(), null);
+                    new MockConfiguration(), new DatastoreContext());
             final TestActorRef<ShardManager> subject =
                 TestActorRef.create(system, props);
 
             // the run() method needs to finish within 3 seconds
-            new Within(duration("1 seconds")) {
+            new Within(duration("10 seconds")) {
+                @Override
                 protected void run() {
 
                     MockClusterWrapper.sendMemberUp(subject, "member-2", getRef().path().toString());
@@ -172,6 +179,7 @@ public class ShardManagerTest {
 
                     final String out = new ExpectMsg<String>(duration("1 seconds"), "primary found") {
                         // do not put code outside this method, will run afterwards
+                        @Override
                         protected String match(Object in) {
                             if (in.getClass().equals(PrimaryFound.SERIALIZABLE_CLASS)) {
                                 PrimaryFound f = PrimaryFound.fromSerializable(in);
@@ -196,12 +204,13 @@ public class ShardManagerTest {
         new JavaTestKit(system) {{
             final Props props = ShardManager
                 .props("config", new MockClusterWrapper(),
-                    new MockConfiguration(), null);
+                    new MockConfiguration(), new DatastoreContext());
             final TestActorRef<ShardManager> subject =
                 TestActorRef.create(system, props);
 
             // the run() method needs to finish within 3 seconds
-            new Within(duration("1 seconds")) {
+            new Within(duration("10 seconds")) {
+                @Override
                 protected void run() {
 
                     MockClusterWrapper.sendMemberUp(subject, "member-2", getRef().path().toString());
index 7740b8e667a974c10b53d0e436edb41455e40cf5..4466e50f96f53651be61a696deda5249692196e9 100644 (file)
@@ -4,7 +4,8 @@ import akka.actor.ActorRef;
 import akka.actor.Props;
 import akka.event.Logging;
 import akka.testkit.JavaTestKit;
-import junit.framework.Assert;
+
+import org.junit.Assert;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier;
 import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
@@ -28,11 +29,14 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
-import static junit.framework.Assert.assertFalse;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 public class ShardTest extends AbstractActorTest {
+
+    private static final DatastoreContext DATA_STORE_CONTEXT = new DatastoreContext();
+
     @Test
     public void testOnReceiveCreateTransactionChain() throws Exception {
         new JavaTestKit(getSystem()) {{
@@ -40,7 +44,7 @@ public class ShardTest extends AbstractActorTest {
                 ShardIdentifier.builder().memberName("member-1")
                     .shardName("inventory").type("config").build();
 
-            final Props props = Shard.props(identifier, Collections.EMPTY_MAP, null);
+            final Props props = Shard.props(identifier, Collections.EMPTY_MAP, DATA_STORE_CONTEXT);
             final ActorRef subject =
                 getSystem().actorOf(props, "testCreateTransactionChain");
 
@@ -49,6 +53,7 @@ public class ShardTest extends AbstractActorTest {
             final boolean result =
                 new JavaTestKit.EventFilter<Boolean>(Logging.Info.class
                 ) {
+                    @Override
                     protected Boolean run() {
                         return true;
                     }
@@ -58,13 +63,15 @@ public class ShardTest extends AbstractActorTest {
 
             Assert.assertEquals(true, result);
 
-            new Within(duration("1 seconds")) {
+            new Within(duration("3 seconds")) {
+                @Override
                 protected void run() {
 
                     subject.tell(new CreateTransactionChain().toSerializable(), getRef());
 
-                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
+                    final String out = new ExpectMsg<String>(duration("3 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
+                        @Override
                         protected String match(Object in) {
                             if (in.getClass().equals(CreateTransactionChainReply.SERIALIZABLE_CLASS)){
                                 CreateTransactionChainReply reply =
@@ -96,11 +103,12 @@ public class ShardTest extends AbstractActorTest {
                 ShardIdentifier.builder().memberName("member-1")
                     .shardName("inventory").type("config").build();
 
-            final Props props = Shard.props(identifier, Collections.EMPTY_MAP, null);
+            final Props props = Shard.props(identifier, Collections.EMPTY_MAP, DATA_STORE_CONTEXT);
             final ActorRef subject =
                 getSystem().actorOf(props, "testRegisterChangeListener");
 
-            new Within(duration("1 seconds")) {
+            new Within(duration("3 seconds")) {
+                @Override
                 protected void run() {
 
                     subject.tell(
@@ -111,8 +119,10 @@ public class ShardTest extends AbstractActorTest {
                         getRef().path(), AsyncDataBroker.DataChangeScope.BASE),
                         getRef());
 
-                    final Boolean notificationEnabled = new ExpectMsg<Boolean>("enable notification") {
+                    final Boolean notificationEnabled = new ExpectMsg<Boolean>(
+                                                   duration("3 seconds"), "enable notification") {
                         // do not put code outside this method, will run afterwards
+                        @Override
                         protected Boolean match(Object in) {
                             if(in instanceof EnableNotification){
                                 return ((EnableNotification) in).isEnabled();
@@ -124,8 +134,9 @@ public class ShardTest extends AbstractActorTest {
 
                     assertFalse(notificationEnabled);
 
-                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
+                    final String out = new ExpectMsg<String>(duration("3 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
+                        @Override
                         protected String match(Object in) {
                             if (in.getClass().equals(RegisterChangeListenerReply.class)) {
                                 RegisterChangeListenerReply reply =
@@ -154,15 +165,15 @@ public class ShardTest extends AbstractActorTest {
                 ShardIdentifier.builder().memberName("member-1")
                     .shardName("inventory").type("config").build();
 
-            final Props props = Shard.props(identifier, Collections.EMPTY_MAP, null);
+            final Props props = Shard.props(identifier, Collections.EMPTY_MAP, DATA_STORE_CONTEXT);
             final ActorRef subject =
                 getSystem().actorOf(props, "testCreateTransaction");
 
-
             // Wait for a specific log message to show up
             final boolean result =
                 new JavaTestKit.EventFilter<Boolean>(Logging.Info.class
                 ) {
+                    @Override
                     protected Boolean run() {
                         return true;
                     }
@@ -172,7 +183,8 @@ public class ShardTest extends AbstractActorTest {
 
             Assert.assertEquals(true, result);
 
-            new Within(duration("1 seconds")) {
+            new Within(duration("3 seconds")) {
+                @Override
                 protected void run() {
 
                     subject.tell(
@@ -182,8 +194,9 @@ public class ShardTest extends AbstractActorTest {
                     subject.tell(new CreateTransaction("txn-1", TransactionProxy.TransactionType.READ_ONLY.ordinal() ).toSerializable(),
                         getRef());
 
-                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
+                    final String out = new ExpectMsg<String>(duration("3 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
+                        @Override
                         protected String match(Object in) {
                             if (in instanceof CreateTransactionReply) {
                                 CreateTransactionReply reply =
@@ -200,8 +213,6 @@ public class ShardTest extends AbstractActorTest {
                         out.contains("akka://test/user/testCreateTransaction/shard-txn-1"));
                     expectNoMsg();
                 }
-
-
             };
         }};
     }
@@ -216,11 +227,12 @@ public class ShardTest extends AbstractActorTest {
                     .shardName("inventory").type("config").build();
 
             peerAddresses.put(identifier, null);
-            final Props props = Shard.props(identifier, peerAddresses, null);
+            final Props props = Shard.props(identifier, peerAddresses, DATA_STORE_CONTEXT);
             final ActorRef subject =
                 getSystem().actorOf(props, "testPeerAddressResolved");
 
-            new Within(duration("1 seconds")) {
+            new Within(duration("3 seconds")) {
+                @Override
                 protected void run() {
 
                     subject.tell(
@@ -229,8 +241,6 @@ public class ShardTest extends AbstractActorTest {
 
                     expectNoMsg();
                 }
-
-
             };
         }};
     }
index d468af6664981d08ad603b1a841fefbdaccc8d47..71eb1f1603a7b00dfc576ec43f8816a41ef2a1ed 100644 (file)
@@ -3,8 +3,11 @@ package org.opendaylight.controller.cluster.datastore;
 import akka.actor.ActorRef;
 import akka.actor.Props;
 import akka.testkit.JavaTestKit;
+
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
+
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionChain;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionChainReply;
@@ -12,87 +15,98 @@ import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply;
 import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 import static org.junit.Assert.assertEquals;
 
 public class ShardTransactionChainTest extends AbstractActorTest {
 
-  private static ListeningExecutorService storeExecutor = MoreExecutors.listeningDecorator(MoreExecutors.sameThreadExecutor());
-
-  private static final InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER", storeExecutor,
-          MoreExecutors.sameThreadExecutor());
-
-  static {
-    store.onGlobalContextUpdated(TestModel.createTestContext());
-  }
-  @Test
-  public void testOnReceiveCreateTransaction() throws Exception {
-    new JavaTestKit(getSystem()) {{
-      final Props props = ShardTransactionChain.props(store.createTransactionChain(), TestModel.createTestContext());
-      final ActorRef subject = getSystem().actorOf(props, "testCreateTransaction");
-
-     new Within(duration("1 seconds")) {
-        @Override
-        protected void run() {
-
-          subject.tell(new CreateTransaction("txn-1", TransactionProxy.TransactionType.READ_ONLY.ordinal() ).toSerializable(), getRef());
-
-          final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
-            // do not put code outside this method, will run afterwards
-            @Override
-            protected String match(Object in) {
-              if (in.getClass().equals(CreateTransactionReply.SERIALIZABLE_CLASS)) {
-                return CreateTransactionReply.fromSerializable(in).getTransactionPath();
-              }else{
-                throw noMatch();
-              }
-            }
-          }.get(); // this extracts the received message
-
-          assertEquals("Unexpected transaction path " + out,
-              "akka://test/user/testCreateTransaction/shard-txn-1",
-              out);
-
-          // Will wait for the rest of the 3 seconds
-          expectNoMsg();
-        }
-
-
-      };
-    }};
-  }
-
-  @Test
-  public void testOnReceiveCloseTransactionChain() throws Exception {
-    new JavaTestKit(getSystem()) {{
-      final Props props = ShardTransactionChain.props(store.createTransactionChain(), TestModel.createTestContext());
-      final ActorRef subject = getSystem().actorOf(props, "testCloseTransactionChain");
-
-      new Within(duration("1 seconds")) {
-        @Override
-        protected void run() {
-
-          subject.tell(new CloseTransactionChain().toSerializable(), getRef());
-
-          final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
-            // do not put code outside this method, will run afterwards
-            @Override
-            protected String match(Object in) {
-              if (in.getClass().equals(CloseTransactionChainReply.SERIALIZABLE_CLASS)) {
-                return "match";
-              } else {
-                throw noMatch();
-              }
-            }
-          }.get(); // this extracts the received message
-
-          assertEquals("match", out);
-          // Will wait for the rest of the 3 seconds
-          expectNoMsg();
-        }
-
-
-      };
-    }};
-  }
+    private static ListeningExecutorService storeExecutor = MoreExecutors.listeningDecorator(MoreExecutors.sameThreadExecutor());
+
+    private static final InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER", storeExecutor,
+            MoreExecutors.sameThreadExecutor());
+
+    private static final SchemaContext testSchemaContext = TestModel.createTestContext();
+
+    private static final DatastoreContext DATA_STORE_CONTEXT = new DatastoreContext();
+
+    private static final String mockShardName = "mockShardName";
+
+    @BeforeClass
+    public static void staticSetup() {
+        store.onGlobalContextUpdated(testSchemaContext);
+    }
+
+    @Test
+    public void testOnReceiveCreateTransaction() throws Exception {
+        new JavaTestKit(getSystem()) {{
+            final Props props = ShardTransactionChain.props(store.createTransactionChain(),
+                    testSchemaContext, DATA_STORE_CONTEXT, mockShardName);
+            final ActorRef subject = getSystem().actorOf(props, "testCreateTransaction");
+
+            new Within(duration("1 seconds")) {
+                @Override
+                protected void run() {
+
+                    subject.tell(new CreateTransaction("txn-1", TransactionProxy.TransactionType.READ_ONLY.ordinal() ).toSerializable(), getRef());
+
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
+                        // do not put code outside this method, will run afterwards
+                        @Override
+                        protected String match(Object in) {
+                            if (in.getClass().equals(CreateTransactionReply.SERIALIZABLE_CLASS)) {
+                                return CreateTransactionReply.fromSerializable(in).getTransactionPath();
+                            }else{
+                                throw noMatch();
+                            }
+                        }
+                    }.get(); // this extracts the received message
+
+                    assertEquals("Unexpected transaction path " + out,
+                            "akka://test/user/testCreateTransaction/shard-txn-1",
+                            out);
+
+                    // Will wait for the rest of the 3 seconds
+                    expectNoMsg();
+                }
+
+
+            };
+        }};
+    }
+
+    @Test
+    public void testOnReceiveCloseTransactionChain() throws Exception {
+        new JavaTestKit(getSystem()) {{
+            final Props props = ShardTransactionChain.props(store.createTransactionChain(),
+                    testSchemaContext, DATA_STORE_CONTEXT,mockShardName );
+            final ActorRef subject = getSystem().actorOf(props, "testCloseTransactionChain");
+
+            new Within(duration("1 seconds")) {
+                @Override
+                protected void run() {
+
+                    subject.tell(new CloseTransactionChain().toSerializable(), getRef());
+
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
+                        // do not put code outside this method, will run afterwards
+                        @Override
+                        protected String match(Object in) {
+                            if (in.getClass().equals(CloseTransactionChainReply.SERIALIZABLE_CLASS)) {
+                                return "match";
+                            } else {
+                                throw noMatch();
+                            }
+                        }
+                    }.get(); // this extracts the received message
+
+                    assertEquals("match", out);
+                    // Will wait for the rest of the 3 seconds
+                    expectNoMsg();
+                }
+
+
+            };
+        }};
+    }
 }
index 16b73040a5b6e5375a24570fb5b1617240eadb04..4fe60f6467d2dab4db24dd34df03b4b6d9c9c7d8 100644 (file)
@@ -13,23 +13,29 @@ package org.opendaylight.controller.cluster.datastore;
 import akka.actor.ActorRef;
 import akka.actor.Props;
 import akka.testkit.TestActorRef;
+
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
+
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier;
+import org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeSerializer;
 import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
 import org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
 import scala.concurrent.Await;
 import scala.concurrent.Future;
 import scala.concurrent.duration.Duration;
 
 import java.util.Collections;
-
-import static org.junit.Assert.assertTrue;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Covers negative test cases
@@ -51,20 +57,21 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
         ShardIdentifier.builder().memberName("member-1")
             .shardName("inventory").type("operational").build();
 
-    static {
+    private final DatastoreContext datastoreContext = new DatastoreContext();
+
+    @BeforeClass
+    public static void staticSetup() {
         store.onGlobalContextUpdated(testSchemaContext);
     }
 
-
     @Test(expected = ReadFailedException.class)
     public void testNegativeReadWithReadOnlyTransactionClosed()
         throws Throwable {
 
         final ActorRef shard =
-            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
-        final Props props =
-            ShardTransaction.props(store.newReadOnlyTransaction(), shard,
-                TestModel.createTestContext());
+            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, new DatastoreContext()));
+        final Props props = ShardTransaction.props(store.newReadOnlyTransaction(), shard,
+                testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString());
 
         final TestActorRef<ShardTransaction> subject = TestActorRef
             .create(getSystem(), props,
@@ -78,32 +85,27 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
                 ).build();
         Future<Object> future =
             akka.pattern.Patterns.ask(subject, readData, 3000);
-        assertTrue(future.isCompleted());
-        Await.result(future, Duration.Zero());
+        Await.result(future, Duration.create(3, TimeUnit.SECONDS));
 
-        ((ShardReadTransaction) subject.underlyingActor())
-            .forUnitTestOnlyExplicitTransactionClose();
+        subject.underlyingActor().getDOMStoreTransaction().close();
 
         future = akka.pattern.Patterns.ask(subject, readData, 3000);
-        Await.result(future, Duration.Zero());
-
-
+        Await.result(future, Duration.create(3, TimeUnit.SECONDS));
     }
 
 
     @Test(expected = ReadFailedException.class)
-    public void testNegativeReadWithReadWriteOnlyTransactionClosed()
+    public void testNegativeReadWithReadWriteTransactionClosed()
         throws Throwable {
 
         final ActorRef shard =
-            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP,null));
-        final Props props =
-            ShardTransaction.props(store.newReadWriteTransaction(), shard,
-                TestModel.createTestContext());
+            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, new DatastoreContext()));
+        final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard,
+                testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString());
 
         final TestActorRef<ShardTransaction> subject = TestActorRef
             .create(getSystem(), props,
-                "testNegativeReadWithReadWriteOnlyTransactionClosed");
+                "testNegativeReadWithReadWriteTransactionClosed");
 
         ShardTransactionMessages.ReadData readData =
             ShardTransactionMessages.ReadData.newBuilder()
@@ -111,33 +113,29 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
                     NormalizedNodeMessages.InstanceIdentifier.newBuilder()
                         .build()
                 ).build();
+
         Future<Object> future =
             akka.pattern.Patterns.ask(subject, readData, 3000);
-        assertTrue(future.isCompleted());
-        Await.result(future, Duration.Zero());
+        Await.result(future, Duration.create(3, TimeUnit.SECONDS));
 
-        ((ShardReadWriteTransaction) subject.underlyingActor())
-            .forUnitTestOnlyExplicitTransactionClose();
+        subject.underlyingActor().getDOMStoreTransaction().close();
 
         future = akka.pattern.Patterns.ask(subject, readData, 3000);
-        Await.result(future, Duration.Zero());
-
-
+        Await.result(future, Duration.create(3, TimeUnit.SECONDS));
     }
 
     @Test(expected = ReadFailedException.class)
-    public void testNegativeExistsWithReadWriteOnlyTransactionClosed()
+    public void testNegativeExistsWithReadWriteTransactionClosed()
         throws Throwable {
 
         final ActorRef shard =
-            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP,null));
-        final Props props =
-            ShardTransaction.props(store.newReadWriteTransaction(), shard,
-                TestModel.createTestContext());
+            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, new DatastoreContext()));
+        final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard,
+                testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString());
 
         final TestActorRef<ShardTransaction> subject = TestActorRef
             .create(getSystem(), props,
-                "testNegativeExistsWithReadWriteOnlyTransactionClosed");
+                "testNegativeExistsWithReadWriteTransactionClosed");
 
         ShardTransactionMessages.DataExists dataExists =
             ShardTransactionMessages.DataExists.newBuilder()
@@ -148,16 +146,12 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
 
         Future<Object> future =
             akka.pattern.Patterns.ask(subject, dataExists, 3000);
-        assertTrue(future.isCompleted());
-        Await.result(future, Duration.Zero());
+        Await.result(future, Duration.create(3, TimeUnit.SECONDS));
 
-        ((ShardReadWriteTransaction) subject.underlyingActor())
-            .forUnitTestOnlyExplicitTransactionClose();
+        subject.underlyingActor().getDOMStoreTransaction().close();
 
         future = akka.pattern.Patterns.ask(subject, dataExists, 3000);
-        Await.result(future, Duration.Zero());
-
-
+        Await.result(future, Duration.create(3, TimeUnit.SECONDS));
     }
 
     @Test(expected = IllegalStateException.class)
@@ -165,10 +159,9 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
 
 
         final ActorRef shard =
-            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP,null));
-        final Props props =
-            ShardTransaction.props(store.newWriteOnlyTransaction(), shard,
-                TestModel.createTestContext());
+            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, new DatastoreContext()));
+        final Props props = ShardTransaction.props(store.newWriteOnlyTransaction(), shard,
+                testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString());
 
         final TestActorRef<ShardTransaction> subject = TestActorRef
             .create(getSystem(), props,
@@ -179,35 +172,29 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
 
         Future<Object> future =
             akka.pattern.Patterns.ask(subject, readyTransaction, 3000);
-        assertTrue(future.isCompleted());
-        Await.result(future, Duration.Zero());
+        Await.result(future, Duration.create(3, TimeUnit.SECONDS));
 
         ShardTransactionMessages.WriteData writeData =
             ShardTransactionMessages.WriteData.newBuilder()
                 .setInstanceIdentifierPathArguments(
                     NormalizedNodeMessages.InstanceIdentifier.newBuilder()
                         .build()).setNormalizedNode(
-                NormalizedNodeMessages.Node.newBuilder().build()
+                buildNormalizedNode()
 
             ).build();
 
         future = akka.pattern.Patterns.ask(subject, writeData, 3000);
-        assertTrue(future.isCompleted());
-        Await.result(future, Duration.Zero());
-
-
+        Await.result(future, Duration.create(3, TimeUnit.SECONDS));
     }
 
-
     @Test(expected = IllegalStateException.class)
     public void testNegativeReadWriteWithTransactionReady() throws Exception {
 
 
         final ActorRef shard =
-            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP,null));
-        final Props props =
-            ShardTransaction.props(store.newReadWriteTransaction(), shard,
-                TestModel.createTestContext());
+            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, new DatastoreContext()));
+        final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard,
+                testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString());
 
         final TestActorRef<ShardTransaction> subject = TestActorRef
             .create(getSystem(), props,
@@ -218,23 +205,24 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
 
         Future<Object> future =
             akka.pattern.Patterns.ask(subject, readyTransaction, 3000);
-        assertTrue(future.isCompleted());
-        Await.result(future, Duration.Zero());
+        Await.result(future, Duration.create(3, TimeUnit.SECONDS));
 
         ShardTransactionMessages.WriteData writeData =
             ShardTransactionMessages.WriteData.newBuilder()
                 .setInstanceIdentifierPathArguments(
                     NormalizedNodeMessages.InstanceIdentifier.newBuilder()
-                        .build()).setNormalizedNode(
-                NormalizedNodeMessages.Node.newBuilder().build()
-
-            ).build();
+                        .build()
+                )
+                .setNormalizedNode(buildNormalizedNode())
+                .build();
 
         future = akka.pattern.Patterns.ask(subject, writeData, 3000);
-        assertTrue(future.isCompleted());
-        Await.result(future, Duration.Zero());
-
+        Await.result(future, Duration.create(3, TimeUnit.SECONDS));
+    }
 
+    private NormalizedNodeMessages.Node buildNormalizedNode() {
+        return NormalizedNodeSerializer
+            .serialize(Builders.containerBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TestModel.TEST_QNAME)).build());
     }
 
     @Test(expected = IllegalStateException.class)
@@ -242,10 +230,9 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
 
 
         final ActorRef shard =
-            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP,null));
-        final Props props =
-            ShardTransaction.props(store.newReadWriteTransaction(), shard,
-                TestModel.createTestContext());
+            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, new DatastoreContext()));
+        final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard,
+                testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString());
 
         final TestActorRef<ShardTransaction> subject = TestActorRef
             .create(getSystem(), props, "testNegativeMergeTransactionReady");
@@ -255,23 +242,19 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
 
         Future<Object> future =
             akka.pattern.Patterns.ask(subject, readyTransaction, 3000);
-        assertTrue(future.isCompleted());
-        Await.result(future, Duration.Zero());
+        Await.result(future, Duration.create(3, TimeUnit.SECONDS));
 
         ShardTransactionMessages.MergeData mergeData =
             ShardTransactionMessages.MergeData.newBuilder()
                 .setInstanceIdentifierPathArguments(
                     NormalizedNodeMessages.InstanceIdentifier.newBuilder()
                         .build()).setNormalizedNode(
-                NormalizedNodeMessages.Node.newBuilder().build()
+                buildNormalizedNode()
 
             ).build();
 
         future = akka.pattern.Patterns.ask(subject, mergeData, 3000);
-        assertTrue(future.isCompleted());
-        Await.result(future, Duration.Zero());
-
-
+        Await.result(future, Duration.create(3, TimeUnit.SECONDS));
     }
 
 
@@ -280,10 +263,9 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
 
 
         final ActorRef shard =
-            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP,null));
-        final Props props =
-            ShardTransaction.props(store.newReadWriteTransaction(), shard,
-                TestModel.createTestContext());
+            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, new DatastoreContext()));
+        final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard,
+                testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString());
 
         final TestActorRef<ShardTransaction> subject = TestActorRef
             .create(getSystem(), props,
@@ -294,8 +276,7 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
 
         Future<Object> future =
             akka.pattern.Patterns.ask(subject, readyTransaction, 3000);
-        assertTrue(future.isCompleted());
-        Await.result(future, Duration.Zero());
+        Await.result(future, Duration.create(3, TimeUnit.SECONDS));
 
         ShardTransactionMessages.DeleteData deleteData =
             ShardTransactionMessages.DeleteData.newBuilder()
@@ -304,9 +285,6 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
                         .build()).build();
 
         future = akka.pattern.Patterns.ask(subject, deleteData, 3000);
-        assertTrue(future.isCompleted());
-        Await.result(future, Duration.Zero());
-
-
+        Await.result(future, Duration.create(3, TimeUnit.SECONDS));
     }
 }
index 8f5d0c28d603c39a008f9638ece377aacdf6f1f8..ff2ee08f94ee610afeef6a0f8d069d7adfe79952 100644 (file)
@@ -5,9 +5,11 @@ 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.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.exceptions.UnknownMessageException;
 import org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier;
@@ -32,11 +34,15 @@ import org.opendaylight.controller.cluster.datastore.modification.Modification;
 import org.opendaylight.controller.cluster.datastore.modification.WriteModification;
 import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreConfigProperties;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
+import scala.concurrent.duration.Duration;
+
 import java.util.Collections;
+import java.util.concurrent.TimeUnit;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -54,17 +60,20 @@ public class ShardTransactionTest extends AbstractActorTest {
         ShardIdentifier.builder().memberName("member-1")
             .shardName("inventory").type("config").build();
 
+    private DatastoreContext datastoreContext = new DatastoreContext();
 
-    static {
+    @BeforeClass
+    public static void staticSetup() {
         store.onGlobalContextUpdated(testSchemaContext);
     }
 
     @Test
     public void testOnReceiveReadData() throws Exception {
         new JavaTestKit(getSystem()) {{
-            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
-            final Props props =
-                ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
+            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER,
+                    Collections.EMPTY_MAP, new DatastoreContext()));
+            final Props props = ShardTransaction.props(store.newReadOnlyTransaction(), shard,
+                    testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString());
             final ActorRef subject = getSystem().actorOf(props, "testReadData");
 
             new Within(duration("1 seconds")) {
@@ -104,9 +113,10 @@ public class ShardTransactionTest extends AbstractActorTest {
     @Test
     public void testOnReceiveReadDataWhenDataNotFound() throws Exception {
         new JavaTestKit(getSystem()) {{
-            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
-            final Props props =
-                ShardTransaction.props( store.newReadOnlyTransaction(), shard, testSchemaContext);
+            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER,
+                    Collections.EMPTY_MAP, new DatastoreContext()));
+            final Props props = ShardTransaction.props( store.newReadOnlyTransaction(), shard,
+                    testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString());
             final ActorRef subject = getSystem().actorOf(props, "testReadDataWhenDataNotFound");
 
             new Within(duration("1 seconds")) {
@@ -147,9 +157,10 @@ public class ShardTransactionTest extends AbstractActorTest {
     @Test
     public void testOnReceiveDataExistsPositive() throws Exception {
         new JavaTestKit(getSystem()) {{
-            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
-            final Props props =
-                ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
+            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER,
+                    Collections.EMPTY_MAP, new DatastoreContext()));
+            final Props props = ShardTransaction.props(store.newReadOnlyTransaction(), shard,
+                    testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString());
             final ActorRef subject = getSystem().actorOf(props, "testDataExistsPositive");
 
             new Within(duration("1 seconds")) {
@@ -190,9 +201,9 @@ public class ShardTransactionTest extends AbstractActorTest {
     public void testOnReceiveDataExistsNegative() throws Exception {
         new JavaTestKit(getSystem()) {{
             final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER,
-                    Collections.EMPTY_MAP, null));
-            final Props props =
-                ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
+                    Collections.EMPTY_MAP, new DatastoreContext()));
+            final Props props = ShardTransaction.props(store.newReadOnlyTransaction(), shard,
+                    testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString());
             final ActorRef subject = getSystem().actorOf(props, "testDataExistsNegative");
 
             new Within(duration("1 seconds")) {
@@ -267,9 +278,10 @@ public class ShardTransactionTest extends AbstractActorTest {
     @Test
     public void testOnReceiveWriteData() throws Exception {
         new JavaTestKit(getSystem()) {{
-            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
-            final Props props =
-                ShardTransaction.props(store.newWriteOnlyTransaction(), shard, TestModel.createTestContext());
+            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER,
+                    Collections.EMPTY_MAP, new DatastoreContext()));
+            final Props props = ShardTransaction.props(store.newWriteOnlyTransaction(), shard,
+                    testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString());
             final ActorRef subject =
                 getSystem().actorOf(props, "testWriteData");
 
@@ -307,9 +319,10 @@ public class ShardTransactionTest extends AbstractActorTest {
     @Test
     public void testOnReceiveMergeData() throws Exception {
         new JavaTestKit(getSystem()) {{
-            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
-            final Props props =
-                ShardTransaction.props(store.newReadWriteTransaction(), shard, testSchemaContext);
+            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER,
+                    Collections.EMPTY_MAP, new DatastoreContext()));
+            final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard,
+                    testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString());
             final ActorRef subject =
                 getSystem().actorOf(props, "testMergeData");
 
@@ -348,9 +361,10 @@ public class ShardTransactionTest extends AbstractActorTest {
     @Test
     public void testOnReceiveDeleteData() throws Exception {
         new JavaTestKit(getSystem()) {{
-            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
-            final Props props =
-                ShardTransaction.props( store.newWriteOnlyTransaction(), shard, TestModel.createTestContext());
+            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER,
+                    Collections.EMPTY_MAP, new DatastoreContext()));
+            final Props props = ShardTransaction.props( store.newWriteOnlyTransaction(), shard,
+                    testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString());
             final ActorRef subject =
                 getSystem().actorOf(props, "testDeleteData");
 
@@ -387,9 +401,10 @@ public class ShardTransactionTest extends AbstractActorTest {
     @Test
     public void testOnReceiveReadyTransaction() throws Exception {
         new JavaTestKit(getSystem()) {{
-            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
-            final Props props =
-                ShardTransaction.props( store.newReadWriteTransaction(), shard, TestModel.createTestContext());
+            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER,
+                    Collections.EMPTY_MAP, new DatastoreContext()));
+            final Props props = ShardTransaction.props( store.newReadWriteTransaction(), shard,
+                    testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString());
             final ActorRef subject =
                 getSystem().actorOf(props, "testReadyTransaction");
 
@@ -425,24 +440,26 @@ public class ShardTransactionTest extends AbstractActorTest {
     @Test
     public void testOnReceiveCloseTransaction() throws Exception {
         new JavaTestKit(getSystem()) {{
-            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
-            final Props props =
-                ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
+            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER,
+                    Collections.EMPTY_MAP, new DatastoreContext()));
+            final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard,
+                    testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString());
             final ActorRef subject =
                 getSystem().actorOf(props, "testCloseTransaction");
 
             watch(subject);
 
-            new Within(duration("2 seconds")) {
+            new Within(duration("6 seconds")) {
                 @Override
                 protected void run() {
 
                     subject.tell(new CloseTransaction().toSerializable(), getRef());
 
-                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
+                    final String out = new ExpectMsg<String>(duration("3 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         @Override
                         protected String match(Object in) {
+                            System.out.println("!!!IN match 1: "+(in!=null?in.getClass():"NULL"));
                             if (in.getClass().equals(CloseTransactionReply.SERIALIZABLE_CLASS)) {
                                 return "match";
                             } else {
@@ -453,10 +470,11 @@ public class ShardTransactionTest extends AbstractActorTest {
 
                     assertEquals("match", out);
 
-                    final String termination = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
+                    final String termination = new ExpectMsg<String>(duration("3 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         @Override
                         protected String match(Object in) {
+                            System.out.println("!!!IN match 2: "+(in!=null?in.getClass():"NULL"));
                             if (in instanceof Terminated) {
                                 return "match";
                             } else {
@@ -465,33 +483,54 @@ public class ShardTransactionTest extends AbstractActorTest {
                         }
                     }.get(); // this extracts the received message
 
-
-                    expectNoMsg();
+                    assertEquals("match", termination);
                 }
-
-
             };
         }};
+    }
 
+    @Test(expected=UnknownMessageException.class)
+    public void testNegativePerformingWriteOperationOnReadTransaction() throws Exception {
+        final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER,
+                Collections.EMPTY_MAP, new DatastoreContext()));
+        final Props props = ShardTransaction.props(store.newReadOnlyTransaction(), shard,
+                testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString());
+        final TestActorRef subject = TestActorRef.apply(props,getSystem());
+
+        subject.receive(new DeleteData(TestModel.TEST_PATH).toSerializable(), ActorRef.noSender());
     }
 
+    @Test
+    public void testShardTransactionInactivity() {
+
+        datastoreContext = new DatastoreContext(InMemoryDOMDataStoreConfigProperties.getDefault(),
+                Duration.create(500, TimeUnit.MILLISECONDS));
 
-  @Test
-  public void testNegativePerformingWriteOperationOnReadTransaction() throws Exception {
-    try {
+        new JavaTestKit(getSystem()) {{
+            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER,
+                    Collections.EMPTY_MAP, new DatastoreContext()));
+            final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard,
+                    testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString());
+            final ActorRef subject =
+                getSystem().actorOf(props, "testShardTransactionInactivity");
 
-        final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
-        final Props props =
-            ShardTransaction.props(store.newReadOnlyTransaction(), shard, TestModel.createTestContext());
-         final TestActorRef subject = TestActorRef.apply(props,getSystem());
+            watch(subject);
 
-        subject.receive(new DeleteData(TestModel.TEST_PATH).toSerializable(), ActorRef.noSender());
-        Assert.assertFalse(true);
+            // The shard Tx actor should receive a ReceiveTimeout message and self-destruct.
 
+            final String termination = new ExpectMsg<String>(duration("3 seconds"), "match hint") {
+                // do not put code outside this method, will run afterwards
+                @Override
+                protected String match(Object in) {
+                    if (in instanceof Terminated) {
+                        return "match";
+                    } else {
+                        throw noMatch();
+                    }
+                }
+            }.get(); // this extracts the received message
 
-    } catch (Exception cs) {
-      assertEquals(UnknownMessageException.class.getSimpleName(), cs.getClass().getSimpleName());
-      assertTrue(cs.getMessage(), cs.getMessage().startsWith("Unknown message received "));
+            assertEquals("match", termination);
+        }};
     }
-  }
 }
index 34697977a5a4639e4b507dde478302834eae5ad5..e10570cd158bdfc4a1d98132788cd89f47cddc15 100644 (file)
@@ -13,9 +13,12 @@ package org.opendaylight.controller.cluster.datastore;
 import akka.actor.ActorRef;
 import akka.actor.Props;
 import akka.testkit.TestActorRef;
+
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
+
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.Mockito;
 import org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier;
@@ -31,6 +34,7 @@ import org.opendaylight.controller.protobuff.messages.persistent.PersistentMessa
 import org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
 import scala.concurrent.Await;
 import scala.concurrent.Future;
 import scala.concurrent.duration.Duration;
@@ -59,25 +63,28 @@ public class ThreePhaseCommitCohortFailureTest extends AbstractActorTest {
         ShardIdentifier.builder().memberName("member-1")
             .shardName("inventory").type("config").build();
 
-    static {
+    private final DatastoreContext datastoreContext = new DatastoreContext();
+
+
+    @BeforeClass
+    public static void staticSetup() {
         store.onGlobalContextUpdated(testSchemaContext);
     }
 
-    private FiniteDuration ASK_RESULT_DURATION = Duration.create(5000, TimeUnit.MILLISECONDS);
+    private final FiniteDuration ASK_RESULT_DURATION = Duration.create(5000, TimeUnit.MILLISECONDS);
 
 
     @Test(expected = TestException.class)
     public void testNegativeAbortResultsInException() throws Exception {
 
-        final ActorRef shard =
-            getSystem()
-                .actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP,null));
+        final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER,
+                Collections.EMPTY_MAP, datastoreContext));
         final DOMStoreThreePhaseCommitCohort mockCohort = Mockito
             .mock(DOMStoreThreePhaseCommitCohort.class);
         final CompositeModification mockComposite =
             Mockito.mock(CompositeModification.class);
         final Props props =
-            ThreePhaseCommitCohort.props(mockCohort, shard, mockComposite);
+            ThreePhaseCommitCohort.props(mockCohort, shard, mockComposite,SHARD_IDENTIFIER.toString());
 
         final TestActorRef<ThreePhaseCommitCohort> subject = TestActorRef
             .create(getSystem(), props,
@@ -93,24 +100,20 @@ public class ThreePhaseCommitCohortFailureTest extends AbstractActorTest {
         assertTrue(future.isCompleted());
 
         Await.result(future, ASK_RESULT_DURATION);
-
-
-
     }
 
 
     @Test(expected = OptimisticLockFailedException.class)
     public void testNegativeCanCommitResultsInException() throws Exception {
 
-        final ActorRef shard =
-            getSystem()
-                .actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP,null));
+        final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER,
+                Collections.EMPTY_MAP, datastoreContext));
         final DOMStoreThreePhaseCommitCohort mockCohort = Mockito
             .mock(DOMStoreThreePhaseCommitCohort.class);
         final CompositeModification mockComposite =
             Mockito.mock(CompositeModification.class);
         final Props props =
-            ThreePhaseCommitCohort.props(mockCohort, shard, mockComposite);
+            ThreePhaseCommitCohort.props(mockCohort, shard, mockComposite,SHARD_IDENTIFIER.toString());
 
         final TestActorRef<ThreePhaseCommitCohort> subject = TestActorRef
             .create(getSystem(), props,
@@ -135,15 +138,14 @@ public class ThreePhaseCommitCohortFailureTest extends AbstractActorTest {
     @Test(expected = TestException.class)
     public void testNegativePreCommitResultsInException() throws Exception {
 
-        final ActorRef shard =
-            getSystem()
-                .actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP,null));
+        final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER,
+                Collections.EMPTY_MAP, datastoreContext));
         final DOMStoreThreePhaseCommitCohort mockCohort = Mockito
             .mock(DOMStoreThreePhaseCommitCohort.class);
         final CompositeModification mockComposite =
             Mockito.mock(CompositeModification.class);
         final Props props =
-            ThreePhaseCommitCohort.props(mockCohort, shard, mockComposite);
+            ThreePhaseCommitCohort.props(mockCohort, shard, mockComposite,SHARD_IDENTIFIER.toString());
 
         final TestActorRef<ThreePhaseCommitCohort> subject = TestActorRef
             .create(getSystem(), props,
@@ -166,15 +168,13 @@ public class ThreePhaseCommitCohortFailureTest extends AbstractActorTest {
     @Test(expected = TestException.class)
     public void testNegativeCommitResultsInException() throws Exception {
 
-        final TestActorRef<Shard> subject = TestActorRef
-            .create(getSystem(),
-                Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP,null),
+        final TestActorRef<Shard> subject = TestActorRef.create(getSystem(),
+                Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, datastoreContext),
                 "testNegativeCommitResultsInException");
 
         final ActorRef shardTransaction =
-            getSystem().actorOf(
-                ShardTransaction.props(store.newReadWriteTransaction(), subject,
-                    TestModel.createTestContext()));
+            getSystem().actorOf(ShardTransaction.props(store.newReadWriteTransaction(), subject,
+                    testSchemaContext, datastoreContext,SHARD_IDENTIFIER.toString()));
 
         ShardTransactionMessages.WriteData writeData =
             ShardTransactionMessages.WriteData.newBuilder()
@@ -221,12 +221,8 @@ public class ThreePhaseCommitCohortFailureTest extends AbstractActorTest {
                 mockForwardCommitTransaction
                 , 3000);
         Await.result(future, ASK_RESULT_DURATION);
-
-
     }
 
     private class TestException extends Exception {
     }
-
-
 }
index 87231f08849ed02398472bb792a40a48753a96be..adb12b298e99260b6f33a6c309f3c6eb16ca78bb 100644 (file)
@@ -7,8 +7,9 @@ import akka.dispatch.Futures;
 
 import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.ListenableFuture;
+
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.isA;
@@ -31,14 +32,21 @@ import org.opendaylight.controller.cluster.datastore.messages.PreCommitTransacti
 import org.opendaylight.controller.cluster.datastore.messages.PreCommitTransactionReply;
 import org.opendaylight.controller.cluster.datastore.messages.SerializableMessage;
 import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
-import org.opendaylight.controller.cluster.datastore.utils.MessageCollectorActor;
+import org.opendaylight.controller.cluster.datastore.utils.DoNothingActor;
+
+import scala.concurrent.Future;
 import scala.concurrent.duration.FiniteDuration;
 
 import java.util.List;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 
 public class ThreePhaseCommitCohortProxyTest extends AbstractActorTest {
 
+    @SuppressWarnings("serial")
+    static class TestException extends RuntimeException {
+    }
+
     @Mock
     private ActorContext actorContext;
 
@@ -49,15 +57,28 @@ public class ThreePhaseCommitCohortProxyTest extends AbstractActorTest {
         doReturn(getSystem()).when(actorContext).getActorSystem();
     }
 
-    private ThreePhaseCommitCohortProxy setupProxy(int nCohorts) {
-        List<ActorPath> cohorts = Lists.newArrayList();
+    private Future<ActorPath> newCohortPath() {
+        ActorPath path = getSystem().actorOf(Props.create(DoNothingActor.class)).path();
+        doReturn(mock(ActorSelection.class)).when(actorContext).actorSelection(path);
+        return Futures.successful(path);
+    }
+
+    private final ThreePhaseCommitCohortProxy setupProxy(int nCohorts) throws Exception {
+        List<Future<ActorPath>> cohortPathFutures = Lists.newArrayList();
         for(int i = 1; i <= nCohorts; i++) {
-            ActorPath path = getSystem().actorOf(Props.create(MessageCollectorActor.class)).path();
-            cohorts.add(path);
-            doReturn(mock(ActorSelection.class)).when(actorContext).actorSelection(path);
+            cohortPathFutures.add(newCohortPath());
         }
 
-        return new ThreePhaseCommitCohortProxy(actorContext, cohorts, "txn-1");
+        return new ThreePhaseCommitCohortProxy(actorContext, cohortPathFutures, "txn-1");
+    }
+
+    private ThreePhaseCommitCohortProxy setupProxyWithFailedCohortPath()
+            throws Exception {
+        List<Future<ActorPath>> cohortPathFutures = Lists.newArrayList();
+        cohortPathFutures.add(newCohortPath());
+        cohortPathFutures.add(Futures.<ActorPath>failed(new TestException()));
+
+        return new ThreePhaseCommitCohortProxy(actorContext, cohortPathFutures, "txn-1");
     }
 
     private void setupMockActorContext(Class<?> requestType, Object... responses) {
@@ -80,6 +101,16 @@ public class ThreePhaseCommitCohortProxyTest extends AbstractActorTest {
                 any(ActorSelection.class), isA(requestType), any(FiniteDuration.class));
     }
 
+    private void propagateExecutionExceptionCause(ListenableFuture<?> future) throws Throwable {
+
+        try {
+            future.get(5, TimeUnit.SECONDS);
+            fail("Expected ExecutionException");
+        } catch(ExecutionException e) {
+            throw e.getCause();
+        }
+    }
+
     @Test
     public void testCanCommitWithOneCohort() throws Exception {
 
@@ -90,14 +121,14 @@ public class ThreePhaseCommitCohortProxyTest extends AbstractActorTest {
 
         ListenableFuture<Boolean> future = proxy.canCommit();
 
-        assertEquals("canCommit", true, future.get());
+        assertEquals("canCommit", true, future.get(5, TimeUnit.SECONDS));
 
         setupMockActorContext(CanCommitTransaction.SERIALIZABLE_CLASS,
                 new CanCommitTransactionReply(false));
 
         future = proxy.canCommit();
 
-        assertEquals("canCommit", false, future.get());
+        assertEquals("canCommit", false, future.get(5, TimeUnit.SECONDS));
 
         verifyCohortInvocations(2, CanCommitTransaction.SERIALIZABLE_CLASS);
     }
@@ -112,7 +143,7 @@ public class ThreePhaseCommitCohortProxyTest extends AbstractActorTest {
 
         ListenableFuture<Boolean> future = proxy.canCommit();
 
-        assertEquals("canCommit", true, future.get());
+        assertEquals("canCommit", true, future.get(5, TimeUnit.SECONDS));
 
         verifyCohortInvocations(2, CanCommitTransaction.SERIALIZABLE_CLASS);
     }
@@ -128,19 +159,19 @@ public class ThreePhaseCommitCohortProxyTest extends AbstractActorTest {
 
         ListenableFuture<Boolean> future = proxy.canCommit();
 
-        assertEquals("canCommit", false, future.get());
+        assertEquals("canCommit", false, future.get(5, TimeUnit.SECONDS));
 
         verifyCohortInvocations(3, CanCommitTransaction.SERIALIZABLE_CLASS);
     }
 
-    @Test(expected = ExecutionException.class)
-    public void testCanCommitWithExceptionFailure() throws Exception {
+    @Test(expected = TestException.class)
+    public void testCanCommitWithExceptionFailure() throws Throwable {
 
         ThreePhaseCommitCohortProxy proxy = setupProxy(1);
 
-        setupMockActorContext(CanCommitTransaction.SERIALIZABLE_CLASS, new RuntimeException("mock"));
+        setupMockActorContext(CanCommitTransaction.SERIALIZABLE_CLASS, new TestException());
 
-        proxy.canCommit().get();
+        propagateExecutionExceptionCause(proxy.canCommit());
     }
 
     @Test(expected = ExecutionException.class)
@@ -151,7 +182,19 @@ public class ThreePhaseCommitCohortProxyTest extends AbstractActorTest {
         setupMockActorContext(CanCommitTransaction.SERIALIZABLE_CLASS,
                 new PreCommitTransactionReply());
 
-        proxy.canCommit().get();
+        proxy.canCommit().get(5, TimeUnit.SECONDS);
+    }
+
+    @Test(expected = TestException.class)
+    public void testCanCommitWithFailedCohortPath() throws Throwable {
+
+        ThreePhaseCommitCohortProxy proxy = setupProxyWithFailedCohortPath();
+
+        try {
+            propagateExecutionExceptionCause(proxy.canCommit());
+        } finally {
+            verifyCohortInvocations(0, CanCommitTransaction.SERIALIZABLE_CLASS);
+        }
     }
 
     @Test
@@ -161,7 +204,7 @@ public class ThreePhaseCommitCohortProxyTest extends AbstractActorTest {
         setupMockActorContext(PreCommitTransaction.SERIALIZABLE_CLASS,
                 new PreCommitTransactionReply());
 
-        proxy.preCommit().get();
+        proxy.preCommit().get(5, TimeUnit.SECONDS);
 
         verifyCohortInvocations(1, PreCommitTransaction.SERIALIZABLE_CLASS);
     }
@@ -173,7 +216,7 @@ public class ThreePhaseCommitCohortProxyTest extends AbstractActorTest {
         setupMockActorContext(PreCommitTransaction.SERIALIZABLE_CLASS,
                 new PreCommitTransactionReply(), new RuntimeException("mock"));
 
-        proxy.preCommit().get();
+        proxy.preCommit().get(5, TimeUnit.SECONDS);
     }
 
     @Test
@@ -182,7 +225,7 @@ public class ThreePhaseCommitCohortProxyTest extends AbstractActorTest {
 
         setupMockActorContext(AbortTransaction.SERIALIZABLE_CLASS, new AbortTransactionReply());
 
-        proxy.abort().get();
+        proxy.abort().get(5, TimeUnit.SECONDS);
 
         verifyCohortInvocations(1, AbortTransaction.SERIALIZABLE_CLASS);
     }
@@ -194,11 +237,22 @@ public class ThreePhaseCommitCohortProxyTest extends AbstractActorTest {
         setupMockActorContext(AbortTransaction.SERIALIZABLE_CLASS, new RuntimeException("mock"));
 
         // The exception should not get propagated.
-        proxy.abort().get();
+        proxy.abort().get(5, TimeUnit.SECONDS);
 
         verifyCohortInvocations(1, AbortTransaction.SERIALIZABLE_CLASS);
     }
 
+    @Test
+    public void testAbortWithFailedCohortPath() throws Throwable {
+
+        ThreePhaseCommitCohortProxy proxy = setupProxyWithFailedCohortPath();
+
+        // The exception should not get propagated.
+        proxy.abort().get(5, TimeUnit.SECONDS);
+
+        verifyCohortInvocations(0, AbortTransaction.SERIALIZABLE_CLASS);
+    }
+
     @Test
     public void testCommit() throws Exception {
 
@@ -207,39 +261,64 @@ public class ThreePhaseCommitCohortProxyTest extends AbstractActorTest {
         setupMockActorContext(CommitTransaction.SERIALIZABLE_CLASS, new CommitTransactionReply(),
                 new CommitTransactionReply());
 
-        proxy.commit().get();
+        proxy.commit().get(5, TimeUnit.SECONDS);
 
         verifyCohortInvocations(2, CommitTransaction.SERIALIZABLE_CLASS);
     }
 
-    @Test(expected = ExecutionException.class)
-    public void testCommitWithFailure() throws Exception {
+    @Test(expected = TestException.class)
+    public void testCommitWithFailure() throws Throwable {
 
         ThreePhaseCommitCohortProxy proxy = setupProxy(2);
 
         setupMockActorContext(CommitTransaction.SERIALIZABLE_CLASS, new CommitTransactionReply(),
-                new RuntimeException("mock"));
+                new TestException());
 
-        proxy.commit().get();
+        propagateExecutionExceptionCause(proxy.commit());
     }
 
     @Test(expected = ExecutionException.class)
-    public void teseCommitWithInvalidResponseType() throws Exception {
+    public void testCommitWithInvalidResponseType() throws Exception {
 
         ThreePhaseCommitCohortProxy proxy = setupProxy(1);
 
         setupMockActorContext(CommitTransaction.SERIALIZABLE_CLASS, new PreCommitTransactionReply());
 
-        proxy.commit().get();
+        proxy.commit().get(5, TimeUnit.SECONDS);
+    }
+
+    @Test(expected = TestException.class)
+    public void testCommitWithFailedCohortPath() throws Throwable {
+
+        ThreePhaseCommitCohortProxy proxy = setupProxyWithFailedCohortPath();
+
+        try {
+            propagateExecutionExceptionCause(proxy.commit());
+        } finally {
+            verifyCohortInvocations(0, CommitTransaction.SERIALIZABLE_CLASS);
+        }
     }
 
     @Test
-    public void testGetCohortPaths() {
+    public void testAllThreePhasesSuccessful() throws Exception {
 
         ThreePhaseCommitCohortProxy proxy = setupProxy(2);
 
-        List<ActorPath> paths = proxy.getCohortPaths();
-        assertNotNull("getCohortPaths returned null", paths);
-        assertEquals("getCohortPaths size", 2, paths.size());
+        setupMockActorContext(CanCommitTransaction.SERIALIZABLE_CLASS,
+                new CanCommitTransactionReply(true), new CanCommitTransactionReply(true));
+
+        setupMockActorContext(PreCommitTransaction.SERIALIZABLE_CLASS,
+                new PreCommitTransactionReply(), new PreCommitTransactionReply());
+
+        setupMockActorContext(CommitTransaction.SERIALIZABLE_CLASS,
+                new CommitTransactionReply(), new CommitTransactionReply());
+
+        proxy.canCommit().get(5, TimeUnit.SECONDS);
+        proxy.preCommit().get(5, TimeUnit.SECONDS);
+        proxy.commit().get(5, TimeUnit.SECONDS);
+
+        verifyCohortInvocations(2, CanCommitTransaction.SERIALIZABLE_CLASS);
+        verifyCohortInvocations(2, PreCommitTransaction.SERIALIZABLE_CLASS);
+        verifyCohortInvocations(2, CommitTransaction.SERIALIZABLE_CLASS);
     }
 }
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/TransactionChainProxyTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/TransactionChainProxyTest.java
new file mode 100644 (file)
index 0000000..93145bd
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *
+ *  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 static org.mockito.Mockito.doReturn;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
+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.DOMStoreTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class TransactionChainProxyTest {
+    ActorContext actorContext = Mockito.mock(ActorContext.class);
+    SchemaContext schemaContext = Mockito.mock(SchemaContext.class);
+
+    @Before
+    public void setUp() {
+        doReturn(schemaContext).when(actorContext).getSchemaContext();
+    }
+
+    @SuppressWarnings("resource")
+    @Test
+    public void testNewReadOnlyTransaction() throws Exception {
+
+     DOMStoreTransaction dst = new TransactionChainProxy(actorContext).newReadOnlyTransaction();
+         Assert.assertTrue(dst instanceof DOMStoreReadTransaction);
+
+    }
+
+    @SuppressWarnings("resource")
+    @Test
+    public void testNewReadWriteTransaction() throws Exception {
+        DOMStoreTransaction dst = new TransactionChainProxy(actorContext).newReadWriteTransaction();
+        Assert.assertTrue(dst instanceof DOMStoreReadWriteTransaction);
+
+    }
+
+    @SuppressWarnings("resource")
+    @Test
+    public void testNewWriteOnlyTransaction() throws Exception {
+        DOMStoreTransaction dst = new TransactionChainProxy(actorContext).newWriteOnlyTransaction();
+        Assert.assertTrue(dst instanceof DOMStoreWriteTransaction);
+
+    }
+
+    @Test(expected=UnsupportedOperationException.class)
+    public void testClose() throws Exception {
+        new TransactionChainProxy(actorContext).close();
+    }
+}
index 14696f786e7e36888be3b5517c14ae4b9779340f..f69ae88ec873ed044ab40c36a63e6f0b68b9db67 100644 (file)
@@ -9,7 +9,9 @@ import akka.actor.ActorRef;
 import akka.actor.ActorSelection;
 import akka.actor.Props;
 import akka.dispatch.Futures;
+
 import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -29,12 +31,15 @@ import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.DataExists;
 import org.opendaylight.controller.cluster.datastore.messages.DataExistsReply;
 import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
+import org.opendaylight.controller.cluster.datastore.messages.DeleteDataReply;
 import org.opendaylight.controller.cluster.datastore.messages.MergeData;
+import org.opendaylight.controller.cluster.datastore.messages.MergeDataReply;
 import org.opendaylight.controller.cluster.datastore.messages.ReadData;
 import org.opendaylight.controller.cluster.datastore.messages.ReadDataReply;
 import org.opendaylight.controller.cluster.datastore.messages.ReadyTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.ReadyTransactionReply;
 import org.opendaylight.controller.cluster.datastore.messages.WriteData;
+import org.opendaylight.controller.cluster.datastore.messages.WriteDataReply;
 import org.opendaylight.controller.cluster.datastore.shardstrategy.DefaultShardStrategy;
 import org.opendaylight.controller.cluster.datastore.shardstrategy.ShardStrategyFactory;
 import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
@@ -48,10 +53,12 @@ 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 scala.concurrent.Await;
 import scala.concurrent.Future;
+import scala.concurrent.duration.Duration;
 import scala.concurrent.duration.FiniteDuration;
 
-import java.util.Arrays;
+import java.util.List;
 import java.util.concurrent.TimeUnit;
 
 import static org.mockito.Matchers.any;
@@ -62,6 +69,7 @@ import static org.mockito.Mockito.argThat;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.isA;
+import static org.mockito.Mockito.times;
 
 @SuppressWarnings("resource")
 public class TransactionProxyTest extends AbstractActorTest {
@@ -71,7 +79,7 @@ public class TransactionProxyTest extends AbstractActorTest {
     }
 
     static interface Invoker {
-        void invoke(TransactionProxy proxy) throws Exception;
+        CheckedFuture<?, ReadFailedException> invoke(TransactionProxy proxy) throws Exception;
     }
 
     private final Configuration configuration = new MockConfiguration();
@@ -90,6 +98,8 @@ public class TransactionProxyTest extends AbstractActorTest {
         schemaContext = TestModel.createTestContext();
 
         doReturn(getSystem()).when(mockActorContext).getActorSystem();
+        doReturn(memberName).when(mockActorContext).getCurrentMemberName();
+        doReturn(schemaContext).when(mockActorContext).getSchemaContext();
 
         ShardStrategyFactory.setConfiguration(configuration);
     }
@@ -112,8 +122,8 @@ public class TransactionProxyTest extends AbstractActorTest {
         ArgumentMatcher<DataExists> matcher = new ArgumentMatcher<DataExists>() {
             @Override
             public boolean matches(Object argument) {
-                DataExists obj = DataExists.fromSerializable(argument);
-                return obj.getPath().equals(TestModel.TEST_PATH);
+                return DataExists.SERIALIZABLE_CLASS.equals(argument.getClass()) &&
+                       DataExists.fromSerializable(argument).getPath().equals(TestModel.TEST_PATH);
             }
         };
 
@@ -124,8 +134,8 @@ public class TransactionProxyTest extends AbstractActorTest {
         ArgumentMatcher<ReadData> matcher = new ArgumentMatcher<ReadData>() {
             @Override
             public boolean matches(Object argument) {
-                ReadData obj = ReadData.fromSerializable(argument);
-                return obj.getPath().equals(TestModel.TEST_PATH);
+                return ReadData.SERIALIZABLE_CLASS.equals(argument.getClass()) &&
+                       ReadData.fromSerializable(argument).getPath().equals(TestModel.TEST_PATH);
             }
         };
 
@@ -136,6 +146,10 @@ public class TransactionProxyTest extends AbstractActorTest {
         ArgumentMatcher<WriteData> matcher = new ArgumentMatcher<WriteData>() {
             @Override
             public boolean matches(Object argument) {
+                if(!WriteData.SERIALIZABLE_CLASS.equals(argument.getClass())) {
+                    return false;
+                }
+
                 WriteData obj = WriteData.fromSerializable(argument, schemaContext);
                 return obj.getPath().equals(TestModel.TEST_PATH) &&
                        obj.getData().equals(nodeToWrite);
@@ -149,6 +163,10 @@ public class TransactionProxyTest extends AbstractActorTest {
         ArgumentMatcher<MergeData> matcher = new ArgumentMatcher<MergeData>() {
             @Override
             public boolean matches(Object argument) {
+                if(!MergeData.SERIALIZABLE_CLASS.equals(argument.getClass())) {
+                    return false;
+                }
+
                 MergeData obj = MergeData.fromSerializable(argument, schemaContext);
                 return obj.getPath().equals(TestModel.TEST_PATH) &&
                        obj.getData().equals(nodeToWrite);
@@ -162,27 +180,38 @@ public class TransactionProxyTest extends AbstractActorTest {
         ArgumentMatcher<DeleteData> matcher = new ArgumentMatcher<DeleteData>() {
             @Override
             public boolean matches(Object argument) {
-                DeleteData obj = DeleteData.fromSerializable(argument);
-                return obj.getPath().equals(TestModel.TEST_PATH);
+                return DeleteData.SERIALIZABLE_CLASS.equals(argument.getClass()) &&
+                       DeleteData.fromSerializable(argument).getPath().equals(TestModel.TEST_PATH);
             }
         };
 
         return argThat(matcher);
     }
 
-    private Object readyTxReply(ActorPath path) {
-        return new ReadyTransactionReply(path).toSerializable();
+    private Future<Object> readyTxReply(ActorPath path) {
+        return Futures.successful((Object)new ReadyTransactionReply(path).toSerializable());
     }
 
     private Future<Object> readDataReply(NormalizedNode<?, ?> data) {
-        return Futures.successful(new ReadDataReply(schemaContext, data)
-                .toSerializable());
+        return Futures.successful(new ReadDataReply(schemaContext, data).toSerializable());
     }
 
     private Future<Object> dataExistsReply(boolean exists) {
         return Futures.successful(new DataExistsReply(exists).toSerializable());
     }
 
+    private Future<Object> writeDataReply() {
+        return Futures.successful(new WriteDataReply().toSerializable());
+    }
+
+    private Future<Object> mergeDataReply() {
+        return Futures.successful(new MergeDataReply().toSerializable());
+    }
+
+    private Future<Object> deleteDataReply() {
+        return Futures.successful(new DeleteDataReply().toSerializable());
+    }
+
     private ActorSelection actorSelection(ActorRef actorRef) {
         return getSystem().actorSelection(actorRef.path());
     }
@@ -201,7 +230,6 @@ public class TransactionProxyTest extends AbstractActorTest {
         ActorRef actorRef = getSystem().actorOf(Props.create(DoNothingActor.class));
         doReturn(getSystem().actorSelection(actorRef.path())).
                 when(mockActorContext).actorSelection(actorRef.path().toString());
-        doReturn(memberName).when(mockActorContext).getCurrentMemberName();
         doReturn(createTransactionReply(actorRef)).when(mockActorContext).
                 executeShardOperation(eq(DefaultShardStrategy.DEFAULT_SHARD),
                         eqCreateTransaction(memberName, type), anyDuration());
@@ -212,12 +240,23 @@ public class TransactionProxyTest extends AbstractActorTest {
         return actorRef;
     }
 
+    private void propagateReadFailedExceptionCause(CheckedFuture<?, ReadFailedException> future)
+            throws Throwable {
+
+        try {
+            future.checkedGet(5, TimeUnit.SECONDS);
+            fail("Expected ReadFailedException");
+        } catch(ReadFailedException e) {
+            throw e.getCause();
+        }
+    }
+
     @Test
     public void testRead() throws Exception {
         ActorRef actorRef = setupActorContextWithInitialCreateTransaction(READ_ONLY);
 
         TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
-                READ_ONLY, schemaContext);
+                READ_ONLY);
 
         doReturn(readDataReply(null)).when(mockActorContext).executeRemoteOperationAsync(
                 eq(actorSelection(actorRef)), eqReadData(), anyDuration());
@@ -240,14 +279,14 @@ public class TransactionProxyTest extends AbstractActorTest {
     }
 
     @Test(expected = ReadFailedException.class)
-    public void testReadWhenAnInvalidMessageIsSentInReply() throws Exception {
+    public void testReadWithInvalidReplyMessageType() throws Exception {
         setupActorContextWithInitialCreateTransaction(READ_ONLY);
 
         doReturn(Futures.successful(new Object())).when(mockActorContext).
                 executeRemoteOperationAsync(any(ActorSelection.class), any(), anyDuration());
 
         TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
-                READ_ONLY, schemaContext);
+                READ_ONLY);
 
         transactionProxy.read(TestModel.TEST_PATH).checkedGet(5, TimeUnit.SECONDS);
     }
@@ -256,19 +295,13 @@ public class TransactionProxyTest extends AbstractActorTest {
     public void testReadWithAsyncRemoteOperatonFailure() throws Throwable {
         setupActorContextWithInitialCreateTransaction(READ_ONLY);
 
-        doThrow(new TestException()).when(mockActorContext).
+        doReturn(Futures.failed(new TestException())).when(mockActorContext).
                 executeRemoteOperationAsync(any(ActorSelection.class), any(), anyDuration());
 
         TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
-                READ_ONLY, schemaContext);
+                READ_ONLY);
 
-        try {
-            transactionProxy.read(TestModel.TEST_PATH).checkedGet(5, TimeUnit.SECONDS);
-            fail("Expected ReadFailedException");
-        } catch(ReadFailedException e) {
-            // Expected - throw cause - expects TestException.
-            throw e.getCause();
-        }
+        propagateReadFailedExceptionCause(transactionProxy.read(TestModel.TEST_PATH));
     }
 
     private void testExceptionOnInitialCreateTransaction(Exception exToThrow, Invoker invoker)
@@ -278,22 +311,16 @@ public class TransactionProxyTest extends AbstractActorTest {
                 anyString(), any(), anyDuration());
 
         TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
-                READ_ONLY, schemaContext);
+                READ_ONLY);
 
-        try {
-            invoker.invoke(transactionProxy);
-            fail("Expected ReadFailedException");
-        } catch(ReadFailedException e) {
-            // Expected - throw cause - expects TestException.
-            throw e.getCause();
-        }
+        propagateReadFailedExceptionCause(invoker.invoke(transactionProxy));
     }
 
     private void testReadWithExceptionOnInitialCreateTransaction(Exception exToThrow) throws Throwable {
         testExceptionOnInitialCreateTransaction(exToThrow, new Invoker() {
             @Override
-            public void invoke(TransactionProxy proxy) throws Exception {
-                proxy.read(TestModel.TEST_PATH).checkedGet(5, TimeUnit.SECONDS);
+            public CheckedFuture<?, ReadFailedException> invoke(TransactionProxy proxy) throws Exception {
+                return proxy.read(TestModel.TEST_PATH);
             }
         });
     }
@@ -314,12 +341,77 @@ public class TransactionProxyTest extends AbstractActorTest {
         testReadWithExceptionOnInitialCreateTransaction(new TestException());
     }
 
+    @Test(expected = TestException.class)
+    public void testReadWithPriorRecordingOperationFailure() throws Throwable {
+        ActorRef actorRef = setupActorContextWithInitialCreateTransaction(READ_WRITE);
+
+        NormalizedNode<?, ?> nodeToWrite = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
+
+        doReturn(writeDataReply()).when(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), eqWriteData(nodeToWrite), anyDuration());
+
+        doReturn(Futures.failed(new TestException())).when(mockActorContext).
+                executeRemoteOperationAsync(eq(actorSelection(actorRef)), eqDeleteData(),
+                        anyDuration());
+
+        doReturn(readDataReply(null)).when(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), eqReadData(), anyDuration());
+
+        TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
+                READ_WRITE);
+
+        transactionProxy.write(TestModel.TEST_PATH, nodeToWrite);
+
+        transactionProxy.delete(TestModel.TEST_PATH);
+
+        try {
+            propagateReadFailedExceptionCause(transactionProxy.read(TestModel.TEST_PATH));
+        } finally {
+            verify(mockActorContext, times(0)).executeRemoteOperationAsync(
+                    eq(actorSelection(actorRef)), eqReadData(), anyDuration());
+        }
+    }
+
+    @Test
+    public void testReadWithPriorRecordingOperationSuccessful() throws Throwable {
+        ActorRef actorRef = setupActorContextWithInitialCreateTransaction(READ_WRITE);
+
+        NormalizedNode<?, ?> expectedNode = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
+
+        doReturn(writeDataReply()).when(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), eqWriteData(expectedNode), anyDuration());
+
+        doReturn(readDataReply(expectedNode)).when(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), eqReadData(), anyDuration());
+
+        TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
+                READ_WRITE);
+
+        transactionProxy.write(TestModel.TEST_PATH, expectedNode);
+
+        Optional<NormalizedNode<?, ?>> readOptional = transactionProxy.read(
+                TestModel.TEST_PATH).get(5, TimeUnit.SECONDS);
+
+        assertEquals("NormalizedNode isPresent", true, readOptional.isPresent());
+
+        assertEquals("Response NormalizedNode", expectedNode, readOptional.get());
+    }
+
+    @Test(expected=IllegalStateException.class)
+    public void testReadPreConditionCheck() {
+
+        TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
+                WRITE_ONLY);
+
+        transactionProxy.read(TestModel.TEST_PATH);
+    }
+
     @Test
     public void testExists() throws Exception {
         ActorRef actorRef = setupActorContextWithInitialCreateTransaction(READ_ONLY);
 
         TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
-                READ_ONLY, schemaContext);
+                READ_ONLY);
 
         doReturn(dataExistsReply(false)).when(mockActorContext).executeRemoteOperationAsync(
                 eq(actorSelection(actorRef)), eqDataExists(), anyDuration());
@@ -340,21 +432,21 @@ public class TransactionProxyTest extends AbstractActorTest {
     public void testExistsWhenAPrimaryNotFoundExceptionIsThrown() throws Throwable {
         testExceptionOnInitialCreateTransaction(new PrimaryNotFoundException("test"), new Invoker() {
             @Override
-            public void invoke(TransactionProxy proxy) throws Exception {
-                proxy.exists(TestModel.TEST_PATH).checkedGet(5, TimeUnit.SECONDS);
+            public CheckedFuture<?, ReadFailedException> invoke(TransactionProxy proxy) throws Exception {
+                return proxy.exists(TestModel.TEST_PATH);
             }
         });
     }
 
     @Test(expected = ReadFailedException.class)
-    public void testExistsWhenAnInvalidMessageIsSentInReply() throws Exception {
+    public void testExistsWithInvalidReplyMessageType() throws Exception {
         setupActorContextWithInitialCreateTransaction(READ_ONLY);
 
         doReturn(Futures.successful(new Object())).when(mockActorContext).
                 executeRemoteOperationAsync(any(ActorSelection.class), any(), anyDuration());
 
         TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
-                READ_ONLY, schemaContext);
+                READ_ONLY);
 
         transactionProxy.exists(TestModel.TEST_PATH).checkedGet(5, TimeUnit.SECONDS);
     }
@@ -363,62 +455,206 @@ public class TransactionProxyTest extends AbstractActorTest {
     public void testExistsWithAsyncRemoteOperatonFailure() throws Throwable {
         setupActorContextWithInitialCreateTransaction(READ_ONLY);
 
-        doThrow(new TestException()).when(mockActorContext).
+        doReturn(Futures.failed(new TestException())).when(mockActorContext).
                 executeRemoteOperationAsync(any(ActorSelection.class), any(), anyDuration());
 
         TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
-                READ_ONLY, schemaContext);
+                READ_ONLY);
+
+        propagateReadFailedExceptionCause(transactionProxy.exists(TestModel.TEST_PATH));
+    }
+
+    @Test(expected = TestException.class)
+    public void testExistsWithPriorRecordingOperationFailure() throws Throwable {
+        ActorRef actorRef = setupActorContextWithInitialCreateTransaction(READ_WRITE);
+
+        NormalizedNode<?, ?> nodeToWrite = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
+
+        doReturn(writeDataReply()).when(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), eqWriteData(nodeToWrite), anyDuration());
+
+        doReturn(Futures.failed(new TestException())).when(mockActorContext).
+                executeRemoteOperationAsync(eq(actorSelection(actorRef)), eqDeleteData(),
+                        anyDuration());
+
+        doReturn(dataExistsReply(false)).when(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), eqDataExists(), anyDuration());
+
+        TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
+                READ_WRITE);
+
+        transactionProxy.write(TestModel.TEST_PATH, nodeToWrite);
+
+        transactionProxy.delete(TestModel.TEST_PATH);
 
         try {
-            transactionProxy.exists(TestModel.TEST_PATH).checkedGet(5, TimeUnit.SECONDS);
-            fail("Expected ReadFailedException");
-        } catch(ReadFailedException e) {
-            // Expected - throw cause - expects TestException.
-            throw e.getCause();
+            propagateReadFailedExceptionCause(transactionProxy.exists(TestModel.TEST_PATH));
+        } finally {
+            verify(mockActorContext, times(0)).executeRemoteOperationAsync(
+                    eq(actorSelection(actorRef)), eqDataExists(), anyDuration());
         }
     }
 
     @Test
-    public void testWrite() throws Exception {
-        ActorRef actorRef = setupActorContextWithInitialCreateTransaction(WRITE_ONLY);
+    public void testExistsWithPriorRecordingOperationSuccessful() throws Throwable {
+        ActorRef actorRef = setupActorContextWithInitialCreateTransaction(READ_WRITE);
+
+        NormalizedNode<?, ?> nodeToWrite = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
+
+        doReturn(writeDataReply()).when(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), eqWriteData(nodeToWrite), anyDuration());
+
+        doReturn(dataExistsReply(true)).when(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), eqDataExists(), anyDuration());
+
+        TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
+                READ_WRITE);
+
+        transactionProxy.write(TestModel.TEST_PATH, nodeToWrite);
+
+        Boolean exists = transactionProxy.exists(TestModel.TEST_PATH).checkedGet();
+
+        assertEquals("Exists response", true, exists);
+    }
+
+    @Test(expected=IllegalStateException.class)
+    public void testxistsPreConditionCheck() {
 
         TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
-                WRITE_ONLY, schemaContext);
+                WRITE_ONLY);
+
+        transactionProxy.exists(TestModel.TEST_PATH);
+    }
+
+    private void verifyRecordingOperationFutures(List<Future<Object>> futures,
+            Class<?>... expResultTypes) throws Exception {
+        assertEquals("getRecordingOperationFutures size", expResultTypes.length, futures.size());
+
+        int i = 0;
+        for( Future<Object> future: futures) {
+            assertNotNull("Recording operation Future is null", future);
+
+            Class<?> expResultType = expResultTypes[i++];
+            if(Throwable.class.isAssignableFrom(expResultType)) {
+                try {
+                    Await.result(future, Duration.create(5, TimeUnit.SECONDS));
+                    fail("Expected exception from recording operation Future");
+                } catch(Exception e) {
+                    // Expected
+                }
+            } else {
+                assertEquals("Recording operation Future result type", expResultType,
+                             Await.result(future, Duration.create(5, TimeUnit.SECONDS)).getClass());
+            }
+        }
+    }
+
+    @Test
+    public void testWrite() throws Exception {
+        ActorRef actorRef = setupActorContextWithInitialCreateTransaction(WRITE_ONLY);
 
         NormalizedNode<?, ?> nodeToWrite = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
 
+        doReturn(writeDataReply()).when(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), eqWriteData(nodeToWrite), anyDuration());
+
+        TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
+                WRITE_ONLY);
+
         transactionProxy.write(TestModel.TEST_PATH, nodeToWrite);
 
-        verify(mockActorContext).sendRemoteOperationAsync(
-                eq(actorSelection(actorRef)), eqWriteData(nodeToWrite));
+        verify(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), eqWriteData(nodeToWrite), anyDuration());
+
+        verifyRecordingOperationFutures(transactionProxy.getRecordedOperationFutures(),
+                WriteDataReply.SERIALIZABLE_CLASS);
+    }
+
+    @Test(expected=IllegalStateException.class)
+    public void testWritePreConditionCheck() {
+
+        TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
+                READ_ONLY);
+
+        transactionProxy.write(TestModel.TEST_PATH,
+                ImmutableNodes.containerNode(TestModel.TEST_QNAME));
+    }
+
+    @Test(expected=IllegalStateException.class)
+    public void testWriteAfterReadyPreConditionCheck() {
+
+        TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
+                WRITE_ONLY);
+
+        transactionProxy.ready();
+
+        transactionProxy.write(TestModel.TEST_PATH,
+                ImmutableNodes.containerNode(TestModel.TEST_QNAME));
     }
 
     @Test
     public void testMerge() throws Exception {
         ActorRef actorRef = setupActorContextWithInitialCreateTransaction(WRITE_ONLY);
 
-        TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
-                WRITE_ONLY, schemaContext);
-
         NormalizedNode<?, ?> nodeToWrite = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
 
+        doReturn(mergeDataReply()).when(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), eqMergeData(nodeToWrite), anyDuration());
+
+        TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
+                WRITE_ONLY);
+
         transactionProxy.merge(TestModel.TEST_PATH, nodeToWrite);
 
-        verify(mockActorContext).sendRemoteOperationAsync(
-                eq(actorSelection(actorRef)), eqMergeData(nodeToWrite));
+        verify(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), eqMergeData(nodeToWrite), anyDuration());
+
+        verifyRecordingOperationFutures(transactionProxy.getRecordedOperationFutures(),
+                MergeDataReply.SERIALIZABLE_CLASS);
     }
 
     @Test
     public void testDelete() throws Exception {
         ActorRef actorRef = setupActorContextWithInitialCreateTransaction(WRITE_ONLY);
 
+        doReturn(deleteDataReply()).when(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), eqDeleteData(), anyDuration());
+
         TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
-                WRITE_ONLY, schemaContext);
+                WRITE_ONLY);
 
         transactionProxy.delete(TestModel.TEST_PATH);
 
-        verify(mockActorContext).sendRemoteOperationAsync(
-                eq(actorSelection(actorRef)), eqDeleteData());
+        verify(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), eqDeleteData(), anyDuration());
+
+        verifyRecordingOperationFutures(transactionProxy.getRecordedOperationFutures(),
+                DeleteDataReply.SERIALIZABLE_CLASS);
+    }
+
+    private void verifyCohortPathFutures(ThreePhaseCommitCohortProxy proxy,
+            Object... expReplies) throws Exception {
+        assertEquals("getReadyOperationFutures size", expReplies.length,
+                proxy.getCohortPathFutures().size());
+
+        int i = 0;
+        for( Future<ActorPath> future: proxy.getCohortPathFutures()) {
+            assertNotNull("Ready operation Future is null", future);
+
+            Object expReply = expReplies[i++];
+            if(expReply instanceof ActorPath) {
+                ActorPath actual = Await.result(future, Duration.create(5, TimeUnit.SECONDS));
+                assertEquals("Cohort actor path", expReply, actual);
+            } else {
+                // Expecting exception.
+                try {
+                    Await.result(future, Duration.create(5, TimeUnit.SECONDS));
+                    fail("Expected exception from ready operation Future");
+                } catch(Exception e) {
+                    // Expected
+                }
+            }
+        }
     }
 
     @SuppressWarnings("unchecked")
@@ -426,31 +662,162 @@ public class TransactionProxyTest extends AbstractActorTest {
     public void testReady() throws Exception {
         ActorRef actorRef = setupActorContextWithInitialCreateTransaction(READ_WRITE);
 
+        NormalizedNode<?, ?> nodeToWrite = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
+
         doReturn(readDataReply(null)).when(mockActorContext).executeRemoteOperationAsync(
                 eq(actorSelection(actorRef)), eqReadData(), anyDuration());
 
-        doReturn(readyTxReply(actorRef.path())).when(mockActorContext).executeRemoteOperation(
+        doReturn(writeDataReply()).when(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), eqWriteData(nodeToWrite), anyDuration());
+
+        doReturn(readyTxReply(actorRef.path())).when(mockActorContext).executeRemoteOperationAsync(
                 eq(actorSelection(actorRef)), isA(ReadyTransaction.SERIALIZABLE_CLASS), anyDuration());
 
         TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
-                READ_WRITE, schemaContext);
+                READ_WRITE);
 
         transactionProxy.read(TestModel.TEST_PATH);
 
+        transactionProxy.write(TestModel.TEST_PATH, nodeToWrite);
+
+        DOMStoreThreePhaseCommitCohort ready = transactionProxy.ready();
+
+        assertTrue(ready instanceof ThreePhaseCommitCohortProxy);
+
+        ThreePhaseCommitCohortProxy proxy = (ThreePhaseCommitCohortProxy) ready;
+
+        verifyRecordingOperationFutures(transactionProxy.getRecordedOperationFutures(),
+                WriteDataReply.SERIALIZABLE_CLASS);
+
+        verifyCohortPathFutures(proxy, actorRef.path());
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testReadyWithRecordingOperationFailure() throws Exception {
+        ActorRef actorRef = setupActorContextWithInitialCreateTransaction(WRITE_ONLY);
+
+        NormalizedNode<?, ?> nodeToWrite = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
+
+        doReturn(mergeDataReply()).when(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), eqMergeData(nodeToWrite), anyDuration());
+
+        doReturn(Futures.failed(new TestException())).when(mockActorContext).
+                executeRemoteOperationAsync(eq(actorSelection(actorRef)), eqWriteData(nodeToWrite),
+                        anyDuration());
+
+        doReturn(readyTxReply(actorRef.path())).when(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), isA(ReadyTransaction.SERIALIZABLE_CLASS), anyDuration());
+
+        TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
+                WRITE_ONLY);
+
+        transactionProxy.merge(TestModel.TEST_PATH, nodeToWrite);
+
+        transactionProxy.write(TestModel.TEST_PATH, nodeToWrite);
+
+        DOMStoreThreePhaseCommitCohort ready = transactionProxy.ready();
+
+        assertTrue(ready instanceof ThreePhaseCommitCohortProxy);
+
+        ThreePhaseCommitCohortProxy proxy = (ThreePhaseCommitCohortProxy) ready;
+
+        verifyRecordingOperationFutures(transactionProxy.getRecordedOperationFutures(),
+                MergeDataReply.SERIALIZABLE_CLASS, TestException.class);
+
+        verifyCohortPathFutures(proxy, TestException.class);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testReadyWithReplyFailure() throws Exception {
+        ActorRef actorRef = setupActorContextWithInitialCreateTransaction(WRITE_ONLY);
+
+        NormalizedNode<?, ?> nodeToWrite = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
+
+        doReturn(mergeDataReply()).when(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), eqMergeData(nodeToWrite), anyDuration());
+
+        doReturn(Futures.failed(new TestException())).when(mockActorContext).
+                executeRemoteOperationAsync(eq(actorSelection(actorRef)),
+                        isA(ReadyTransaction.SERIALIZABLE_CLASS), anyDuration());
+
+        TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
+                WRITE_ONLY);
+
+        transactionProxy.merge(TestModel.TEST_PATH, nodeToWrite);
+
+        DOMStoreThreePhaseCommitCohort ready = transactionProxy.ready();
+
+        assertTrue(ready instanceof ThreePhaseCommitCohortProxy);
+
+        ThreePhaseCommitCohortProxy proxy = (ThreePhaseCommitCohortProxy) ready;
+
+        verifyRecordingOperationFutures(transactionProxy.getRecordedOperationFutures(),
+                MergeDataReply.SERIALIZABLE_CLASS);
+
+        verifyCohortPathFutures(proxy, TestException.class);
+    }
+
+    @Test
+    public void testReadyWithInitialCreateTransactionFailure() throws Exception {
+
+        doThrow(new PrimaryNotFoundException("mock")).when(mockActorContext).executeShardOperation(
+                anyString(), any(), anyDuration());
+
+        TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
+                WRITE_ONLY);
+
+        NormalizedNode<?, ?> nodeToWrite = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
+
+        transactionProxy.merge(TestModel.TEST_PATH, nodeToWrite);
+
+        transactionProxy.write(TestModel.TEST_PATH, nodeToWrite);
+
+        transactionProxy.delete(TestModel.TEST_PATH);
+
+        DOMStoreThreePhaseCommitCohort ready = transactionProxy.ready();
+
+        assertTrue(ready instanceof ThreePhaseCommitCohortProxy);
+
+        ThreePhaseCommitCohortProxy proxy = (ThreePhaseCommitCohortProxy) ready;
+
+        verifyCohortPathFutures(proxy, PrimaryNotFoundException.class);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testReadyWithInvalidReplyMessageType() throws Exception {
+        ActorRef actorRef = setupActorContextWithInitialCreateTransaction(WRITE_ONLY);
+
+        NormalizedNode<?, ?> nodeToWrite = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
+
+        doReturn(writeDataReply()).when(mockActorContext).executeRemoteOperationAsync(
+                eq(actorSelection(actorRef)), eqWriteData(nodeToWrite), anyDuration());
+
+        doReturn(Futures.successful(new Object())).when(mockActorContext).
+                executeRemoteOperationAsync(eq(actorSelection(actorRef)),
+                        isA(ReadyTransaction.SERIALIZABLE_CLASS), anyDuration());
+
+        TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
+                WRITE_ONLY);
+
+        transactionProxy.write(TestModel.TEST_PATH, nodeToWrite);
+
         DOMStoreThreePhaseCommitCohort ready = transactionProxy.ready();
 
         assertTrue(ready instanceof ThreePhaseCommitCohortProxy);
 
         ThreePhaseCommitCohortProxy proxy = (ThreePhaseCommitCohortProxy) ready;
 
-        assertEquals("getCohortPaths", Arrays.asList(actorRef.path()), proxy.getCohortPaths());
+        verifyCohortPathFutures(proxy, IllegalArgumentException.class);
     }
 
     @Test
     public void testGetIdentifier() {
         setupActorContextWithInitialCreateTransaction(READ_ONLY);
         TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
-                TransactionProxy.TransactionType.READ_ONLY, schemaContext);
+                TransactionProxy.TransactionType.READ_ONLY);
 
         Object id = transactionProxy.getIdentifier();
         assertNotNull("getIdentifier returned null", id);
@@ -466,7 +833,7 @@ public class TransactionProxyTest extends AbstractActorTest {
                 eq(actorSelection(actorRef)), eqReadData(), anyDuration());
 
         TransactionProxy transactionProxy = new TransactionProxy(mockActorContext,
-                READ_WRITE, schemaContext);
+                READ_WRITE);
 
         transactionProxy.read(TestModel.TEST_PATH);
 
index 41adcc55b188296f899b1569e98276906b233c1e..c4d0b85fb54546faa5e0667e58e472d549d5836f 100644 (file)
@@ -1,3 +1,10 @@
+/*
+ * 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.jmx.mbeans.shard;
 
 import org.junit.After;
@@ -86,7 +93,69 @@ public class ShardStatsTest {
         Object attribute =
             mbeanServer.getAttribute(testMBeanName, "FailedTransactionsCount");
         Assert.assertEquals((Long) attribute, (Long) 2L);
+    }
+
+    @Test
+    public void testGetAbortTransactionsCount() throws Exception {
+        //let us increment AbortTransactions count and then check
+        shardStats.incrementAbortTransactionsCount();
+        shardStats.incrementAbortTransactionsCount();
+
+
+        //now let us get from MBeanServer what is the transaction count.
+        Object attribute =
+            mbeanServer.getAttribute(testMBeanName, "AbortTransactionsCount");
+        Assert.assertEquals((Long) attribute, (Long) 2L);
+    }
+
+    @Test
+    public void testGetFailedReadTransactionsCount() throws Exception {
+        //let us increment FailedReadTransactions count and then check
+        shardStats.incrementFailedReadTransactionsCount();
+        shardStats.incrementFailedReadTransactionsCount();
+
+
+        //now let us get from MBeanServer what is the transaction count.
+        Object attribute =
+            mbeanServer.getAttribute(testMBeanName, "FailedReadTransactionsCount");
+        Assert.assertEquals((Long) attribute, (Long) 2L);
+    }
+
+    @Test
+    public void testResetTransactionCounters() throws Exception {
+
+        //let us increment committed transactions count and then check
+        shardStats.incrementCommittedTransactionCount();
+        shardStats.incrementCommittedTransactionCount();
+        shardStats.incrementCommittedTransactionCount();
+
+        //now let us get from MBeanServer what is the transaction count.
+        Object attribute = mbeanServer.getAttribute(testMBeanName,
+            "CommittedTransactionsCount");
+        Assert.assertEquals((Long) attribute, (Long) 3L);
+
+        //let us increment FailedReadTransactions count and then check
+        shardStats.incrementFailedReadTransactionsCount();
+        shardStats.incrementFailedReadTransactionsCount();
+
+
+        //now let us get from MBeanServer what is the transaction count.
+        attribute =
+            mbeanServer.getAttribute(testMBeanName, "FailedReadTransactionsCount");
+        Assert.assertEquals((Long) attribute, (Long) 2L);
+
+
+        //here we will reset the counters and check the above ones are 0 after reset
+        mbeanServer.invoke(testMBeanName, "resetTransactionCounters", null, null);
+
+        //now let us get from MBeanServer what is the transaction count.
+        attribute = mbeanServer.getAttribute(testMBeanName,
+            "CommittedTransactionsCount");
+        Assert.assertEquals((Long) attribute, (Long) 0L);
 
+        attribute =
+            mbeanServer.getAttribute(testMBeanName, "FailedReadTransactionsCount");
+        Assert.assertEquals((Long) attribute, (Long) 0L);
 
 
     }
index 27b0374bacbaa6b224c52ceaf7d33a83ffa554fb..6851b1b72ce39d4c011cb0771b95014bb31ade32 100644 (file)
@@ -14,3 +14,8 @@ akka {
         }
     }
 }
+bounded-mailbox {
+  mailbox-type = "org.opendaylight.controller.common.actor.MeteredBoundedMailbox"
+  mailbox-capacity = 1000
+  mailbox-push-timeout-time = 100ms
+}
index 9b70f0c4d708d63b1544d05dd1948df35e209912..05ca61a3535699273ed4ca0e169a9fcbd9dc88b7 100644 (file)
@@ -49,8 +49,17 @@ public interface DOMDataReadTransaction extends AsyncReadTransaction<YangInstanc
             LogicalDatastoreType store, YangInstanceIdentifier path);
 
     /**
-     * Checks if data is available in the logical data store located at provided path
+     /**
+     * Checks if data is available in the logical data store located at provided path.
+     * <p>
      *
+     * Note: a successful result from this method makes no guarantee that a subsequent call to {@link #read}
+     * will succeed. It is possible that the data resides in a data store on a remote node and, if that
+     * node goes down or a network failure occurs, a subsequent read would fail. Another scenario is if
+     * the data is deleted in between the calls to <code>exists</code> and <code>read</code>
+     *
+     * @param store
+     *            Logical data store from which read should occur.
      * @param path
      *            Path which uniquely identifies subtree which client want to
      *            check existence of
index 8664e8910b46bda523951f22961d59c13cbaec42..b423bbd0e5c644c147a69398a65da0a564c985a1 100644 (file)
@@ -7,11 +7,13 @@
  */
 package org.opendaylight.controller.config.yang.md.sal.dom.impl;
 
-import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
+
 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.common.util.jmx.ThreadExecutorStatsMXBeanImpl;
 import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl;
+import org.opendaylight.controller.md.sal.dom.broker.impl.jmx.CommitStatsMXBeanImpl;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreFactory;
 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
 import org.opendaylight.yangtools.util.concurrent.DeadlockDetectingListeningExecutorService;
@@ -24,6 +26,8 @@ import com.google.common.collect.ImmutableMap;
 public final class DomInmemoryDataBrokerModule extends
         org.opendaylight.controller.config.yang.md.sal.dom.impl.AbstractDomInmemoryDataBrokerModule {
 
+    private static final String JMX_BEAN_TYPE = "DOMDataBroker";
+
     public DomInmemoryDataBrokerModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
             final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
         super(identifier, dependencyResolver);
@@ -78,7 +82,7 @@ public final class DomInmemoryDataBrokerModule extends
          * nothing on success. The executor queue capacity is bounded and, if the capacity is
          * reached, subsequent submitted tasks will block the caller.
          */
-        Executor listenableFutureExecutor = SpecialExecutors.newBlockingBoundedCachedThreadPool(
+        ExecutorService listenableFutureExecutor = SpecialExecutors.newBlockingBoundedCachedThreadPool(
                 getMaxDataBrokerFutureCallbackPoolSize(), getMaxDataBrokerFutureCallbackQueueSize(),
                 "CommitFutures");
 
@@ -87,6 +91,29 @@ public final class DomInmemoryDataBrokerModule extends
                     TransactionCommitDeadlockException.DEADLOCK_EXECUTOR_FUNCTION,
                     listenableFutureExecutor));
 
+        final CommitStatsMXBeanImpl commitStatsMXBean = new CommitStatsMXBeanImpl(
+                newDataBroker.getCommitStatsTracker(), JMX_BEAN_TYPE);
+        commitStatsMXBean.registerMBean();
+
+        final ThreadExecutorStatsMXBeanImpl commitExecutorStatsMXBean =
+                new ThreadExecutorStatsMXBeanImpl(commitExecutor, "CommitExecutorStats",
+                        JMX_BEAN_TYPE, null);
+        commitExecutorStatsMXBean.registerMBean();
+
+        final ThreadExecutorStatsMXBeanImpl commitFutureStatsMXBean =
+                new ThreadExecutorStatsMXBeanImpl(listenableFutureExecutor,
+                        "CommitFutureExecutorStats", JMX_BEAN_TYPE, null);
+        commitFutureStatsMXBean.registerMBean();
+
+        newDataBroker.setCloseable(new AutoCloseable() {
+            @Override
+            public void close() {
+                commitStatsMXBean.unregisterMBean();
+                commitExecutorStatsMXBean.unregisterMBean();
+                commitFutureStatsMXBean.unregisterMBean();
+            }
+        });
+
         return newDataBroker;
     }
 }
index d1b9a8f6005097ccc463d87efe2a52d0e3911b4c..d63d6cbe3674fb44e9131e8cbf99dc52453e5ae5 100644 (file)
@@ -23,6 +23,7 @@ import org.opendaylight.controller.sal.core.spi.data.DOMStore;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.util.DurationStatsTracker;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -40,6 +41,7 @@ public class DOMDataBrokerImpl extends AbstractDOMForwardedTransactionFactory<DO
     private final DOMDataCommitCoordinatorImpl coordinator;
     private final AtomicLong txNum = new AtomicLong();
     private final AtomicLong chainNum = new AtomicLong();
+    private volatile AutoCloseable closeable;
 
     public DOMDataBrokerImpl(final ImmutableMap<LogicalDatastoreType, DOMStore> datastores,
             final ListeningExecutorService executor) {
@@ -47,6 +49,27 @@ public class DOMDataBrokerImpl extends AbstractDOMForwardedTransactionFactory<DO
         this.coordinator = new DOMDataCommitCoordinatorImpl(executor);
     }
 
+    public void setCloseable(AutoCloseable closeable) {
+        this.closeable = closeable;
+    }
+
+    public DurationStatsTracker getCommitStatsTracker() {
+        return coordinator.getCommitStatsTracker();
+    }
+
+    @Override
+    public void close() {
+        super.close();
+
+        if(closeable != null) {
+            try {
+                closeable.close();
+            } catch(Exception e) {
+                LOG.debug("Error closing instance", e);
+            }
+        }
+    }
+
     @Override
     protected Object newTransactionIdentifier() {
         return "DOM-" + txNum.getAndIncrement();
@@ -82,5 +105,4 @@ public class DOMDataBrokerImpl extends AbstractDOMForwardedTransactionFactory<DO
         LOG.debug("Transaction: {} submitted with cohorts {}.", transaction.getIdentifier(), cohorts);
         return coordinator.submit(transaction, cohorts, Optional.<DOMDataCommitErrorListener> absent());
     }
-
 }
index 521e2d0e731af06ac972ce2cce28f75a347ba490..3fde8d360f8af6df8cb0bcd705a9e3289d9fd35e 100644 (file)
@@ -16,6 +16,7 @@ import javax.annotation.concurrent.GuardedBy;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
+import org.opendaylight.yangtools.util.DurationStatsTracker;
 import org.opendaylight.yangtools.util.concurrent.MappingCheckedFuture;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -69,6 +70,8 @@ public class DOMDataCommitCoordinatorImpl implements DOMDataCommitExecutor {
 
     private final ListeningExecutorService executor;
 
+    private final DurationStatsTracker commitStatsTracker = new DurationStatsTracker();
+
     /**
      *
      * Construct DOMDataCommitCoordinator which uses supplied executor to
@@ -80,6 +83,10 @@ public class DOMDataCommitCoordinatorImpl implements DOMDataCommitExecutor {
         this.executor = Preconditions.checkNotNull(executor, "executor must not be null.");
     }
 
+    public DurationStatsTracker getCommitStatsTracker() {
+        return commitStatsTracker;
+    }
+
     @Override
     public CheckedFuture<Void,TransactionCommitFailedException> submit(final DOMDataWriteTransaction transaction,
             final Iterable<DOMStoreThreePhaseCommitCohort> cohorts, final Optional<DOMDataCommitErrorListener> listener) {
@@ -90,7 +97,8 @@ public class DOMDataCommitCoordinatorImpl implements DOMDataCommitExecutor {
 
         ListenableFuture<Void> commitFuture = null;
         try {
-            commitFuture = executor.submit(new CommitCoordinationTask(transaction, cohorts, listener));
+            commitFuture = executor.submit(new CommitCoordinationTask(transaction, cohorts,
+                    listener, commitStatsTracker));
         } catch(RejectedExecutionException e) {
             LOG.error("The commit executor's queue is full - submit task was rejected. \n" +
                       executor, e);
@@ -154,21 +162,25 @@ public class DOMDataCommitCoordinatorImpl implements DOMDataCommitExecutor {
 
         private final DOMDataWriteTransaction tx;
         private final Iterable<DOMStoreThreePhaseCommitCohort> cohorts;
+        private final DurationStatsTracker commitStatTracker;
 
         @GuardedBy("this")
         private CommitPhase currentPhase;
 
         public CommitCoordinationTask(final DOMDataWriteTransaction transaction,
                 final Iterable<DOMStoreThreePhaseCommitCohort> cohorts,
-                final Optional<DOMDataCommitErrorListener> listener) {
+                final Optional<DOMDataCommitErrorListener> listener,
+                final DurationStatsTracker commitStatTracker) {
             this.tx = Preconditions.checkNotNull(transaction, "transaction must not be null");
             this.cohorts = Preconditions.checkNotNull(cohorts, "cohorts must not be null");
             this.currentPhase = CommitPhase.SUBMITTED;
+            this.commitStatTracker = commitStatTracker;
         }
 
         @Override
         public Void call() throws TransactionCommitFailedException {
 
+            long startTime = System.nanoTime();
             try {
                 canCommitBlocking();
                 preCommitBlocking();
@@ -178,6 +190,10 @@ public class DOMDataCommitCoordinatorImpl implements DOMDataCommitExecutor {
                 LOG.warn("Tx: {} Error during phase {}, starting Abort", tx.getIdentifier(), currentPhase, e);
                 abortBlocking(e);
                 throw e;
+            } finally {
+                if(commitStatTracker != null) {
+                    commitStatTracker.addDuration(System.nanoTime() - startTime);
+                }
             }
         }
 
index b9504e72685f92f401173030af658d34b1982dcf..1c12d20504702eb7bf551922463bac74535f42c9 100644 (file)
@@ -62,12 +62,18 @@ abstract class TranslatingListenerInvoker implements AutoCloseable, DOMDataChang
         }
     }
 
+    @Override
+    public String toString() {
+        return getDelegate().getClass().getName();
+    }
+
     static final class TranslatingConfigListenerInvoker extends TranslatingListenerInvoker {
 
         public TranslatingConfigListenerInvoker(final DataChangeListener listener, final DataNormalizer normalizer) {
             super(listener, normalizer);
         }
 
+        @Override
         DataChangeEvent<YangInstanceIdentifier, CompositeNode> getLegacyEvent(final DataNormalizer normalizer, final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
             return TranslatingDataChangeEvent.createConfiguration(normalizedChange, normalizer);
         }
@@ -85,6 +91,7 @@ abstract class TranslatingListenerInvoker implements AutoCloseable, DOMDataChang
             super(listener, normalizer);
         }
 
+        @Override
         DataChangeEvent<YangInstanceIdentifier, CompositeNode> getLegacyEvent(final DataNormalizer normalizer, final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
             return TranslatingDataChangeEvent.createOperational(normalizedChange, normalizer);
         }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/jmx/CommitStatsMXBean.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/jmx/CommitStatsMXBean.java
new file mode 100644 (file)
index 0000000..40dc30e
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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.dom.broker.impl.jmx;
+
+/**
+ * MXBean interface for retrieving write Tx commit statistics.
+ *
+ * @author Thomas Pantelis
+ */
+public interface CommitStatsMXBean {
+
+    /**
+     * Returns the total number of commits that have occurred.
+     */
+    long getTotalCommits();
+
+    /**
+     * Returns a string representing the time duration of the longest commit, in the appropriate
+     * scaled units, along with the date/time that it occurred.
+     */
+    String getLongestCommitTime();
+
+    /**
+     * Returns a string representing the time duration of the shortest commit, in the appropriate
+     * scaled units, along with the date/time that it occurred.
+     */
+    String getShortestCommitTime();
+
+    /**
+     * Returns a string representing average commit time duration, in the appropriate
+     * scaled units.
+     */
+    String getAverageCommitTime();
+
+    /**
+     * Clears the current stats to their defaults.
+     */
+    void clearStats();
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/jmx/CommitStatsMXBeanImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/jmx/CommitStatsMXBeanImpl.java
new file mode 100644 (file)
index 0000000..f67f6b0
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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.dom.broker.impl.jmx;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.controller.md.sal.common.util.jmx.AbstractMXBean;
+import org.opendaylight.yangtools.util.DurationStatsTracker;
+
+/**
+ * Implementation of the CommitStatsMXBean interface.
+ *
+ * @author Thomas Pantelis
+ */
+public class CommitStatsMXBeanImpl extends AbstractMXBean implements CommitStatsMXBean {
+
+    private final DurationStatsTracker commitStatsTracker;
+
+    /**
+     * Constructor.
+     *
+     * @param commitStatsTracker the DurationStatsTracker used to obtain the stats.
+     * @param mBeanType mBeanType Used as the <code>type</code> property in the bean's ObjectName.
+     */
+    public CommitStatsMXBeanImpl(@Nonnull DurationStatsTracker commitStatsTracker,
+            @Nonnull String mBeanType) {
+        super("CommitStats", mBeanType, null);
+        this.commitStatsTracker = commitStatsTracker;
+    }
+
+    @Override
+    public long getTotalCommits() {
+        return commitStatsTracker.getTotalDurations();
+    }
+
+    @Override
+    public String getLongestCommitTime() {
+        return commitStatsTracker.getDisplayableLongestDuration();
+    }
+
+    @Override
+    public String getShortestCommitTime() {
+        return commitStatsTracker.getDisplayableShortestDuration();
+    }
+
+    @Override
+    public String getAverageCommitTime() {
+        return commitStatsTracker.getDisplayableAverageDuration();
+    }
+
+    @Override
+    public void clearStats() {
+        commitStatsTracker.reset();
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/jmx/CommitStatsMXBeanImplTest.java b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/jmx/CommitStatsMXBeanImplTest.java
new file mode 100644 (file)
index 0000000..d796930
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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.dom.broker.impl.jmx;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.util.DurationStatsTracker;
+
+/**
+ * Unit tests for CommitStatsMXBeanImpl.
+ *
+ * @author Thomas Pantelis
+ */
+public class CommitStatsMXBeanImplTest {
+
+    @Test
+    public void test() {
+
+        DurationStatsTracker commitStatsTracker = new DurationStatsTracker();
+        CommitStatsMXBeanImpl bean =
+                new CommitStatsMXBeanImpl(commitStatsTracker, "Test");
+
+        commitStatsTracker.addDuration(100);
+
+        String prefix = "100.0 ns";
+        assertEquals("getTotalCommits", 1L, bean.getTotalCommits());
+        assertEquals("getLongestCommitTime starts with \"" + prefix + "\"", true,
+                     bean.getLongestCommitTime().startsWith("100.0 ns"));
+        assertEquals("getShortestCommitTime starts with \"" + prefix + "\"", true,
+                     bean.getShortestCommitTime().startsWith(prefix));
+        assertEquals("getAverageCommitTime starts with \"" + prefix + "\"", true,
+                     bean.getAverageCommitTime().startsWith(prefix));
+    }
+}
index 719a6f0499d4423040e5547b82a3bc957c30abbe..306891189a6d7f0f5b0745c9de0e63362fff768c 100644 (file)
@@ -36,7 +36,13 @@ public interface DOMStoreReadTransaction extends DOMStoreTransaction {
     CheckedFuture<Optional<NormalizedNode<?,?>>, ReadFailedException> read(YangInstanceIdentifier path);
 
     /**
-     * Checks if data is available in the logical data store located at provided path
+     * Checks if data is available in the logical data store located at provided path.
+     * <p>
+     *
+     * Note: a successful result from this method makes no guarantee that a subsequent call to {@link #read}
+     * will succeed. It is possible that the data resides in a data store on a remote node and, if that
+     * node goes down or a network failure occurs, a subsequent read would fail. Another scenario is if
+     * the data is deleted in between the calls to <code>exists</code> and <code>read</code>
      *
      * @param path
      *            Path which uniquely identifies subtree which client want to
index 5876c50d51380a865afead594618627e7347bf3f..b916fddca7796e90dca402f1a8b4ac6a26fe2837 100644 (file)
@@ -12,8 +12,6 @@ package org.opendaylight.controller.sal.core.spi.data;
  * sequence and each transaction must see the effects of previous transactions
  * as if they happened. A chain makes no guarantees of atomicity, in fact
  * transactions are committed as soon as possible.
- *
- *
  */
 public interface DOMStoreTransactionChain extends DOMStoreTransactionFactory, AutoCloseable {
 
@@ -35,7 +33,7 @@ public interface DOMStoreTransactionChain extends DOMStoreTransactionFactory, Au
      *             if the chain has been closed.
      */
     @Override
-    public DOMStoreReadTransaction newReadOnlyTransaction();
+    DOMStoreReadTransaction newReadOnlyTransaction();
 
     /**
      * Create a new read write transaction which will continue the chain. The
@@ -55,10 +53,10 @@ public interface DOMStoreTransactionChain extends DOMStoreTransactionFactory, Au
      *             if the chain has been closed.
      */
     @Override
-    public DOMStoreReadWriteTransaction newReadWriteTransaction();
+    DOMStoreReadWriteTransaction newReadWriteTransaction();
 
     /**
-     * Create a new read write transaction which will continue the chain. The
+     * Create a new write-only transaction which will continue the chain. The
      * previous read-write transaction has to be either READY or CANCELLED.
      *
      *
@@ -68,8 +66,7 @@ public interface DOMStoreTransactionChain extends DOMStoreTransactionFactory, Au
      *             if the chain has been closed.
      */
     @Override
-    public DOMStoreWriteTransaction newWriteOnlyTransaction();
-
+    DOMStoreWriteTransaction newWriteOnlyTransaction();
 
     /**
      * Closes Transaction Chain.
@@ -80,6 +77,5 @@ public interface DOMStoreTransactionChain extends DOMStoreTransactionFactory, Au
      * @throws IllegalStateException If any of the outstanding created transactions was not canceled or ready.
      */
     @Override
-    public void close();
-
+    void close();
 }
diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/statistics/DOMStoreStatsTracker.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/statistics/DOMStoreStatsTracker.java
new file mode 100644 (file)
index 0000000..12713b2
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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.sal.core.spi.data.statistics;
+
+import java.util.concurrent.ExecutorService;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.yangtools.util.concurrent.QueuedNotificationManager;
+
+/**
+ * Interface for a class that tracks statistics for a data store.
+ *
+ * @author Thomas Pantelis
+ */
+public interface DOMStoreStatsTracker {
+
+    /**
+     * Sets the executor used for DataChangeListener notifications.
+     *
+     * @param dclExecutor the executor
+     */
+    void setDataChangeListenerExecutor( @Nonnull ExecutorService dclExecutor );
+
+    /**
+     * Sets the executor used internally by the data store.
+     *
+     * @param dsExecutor the executor
+     */
+    void setDataStoreExecutor( @Nonnull ExecutorService dsExecutor );
+
+    /**
+     * Sets the QueuedNotificationManager use for DataChangeListener notifications,
+     *
+     * @param manager the manager
+     */
+    void setNotificationManager( @Nonnull QueuedNotificationManager<?, ?> manager );
+}
diff --git a/opendaylight/md-sal/sal-dom-xsql-config/pom.xml b/opendaylight/md-sal/sal-dom-xsql-config/pom.xml
new file mode 100644 (file)
index 0000000..077405f
--- /dev/null
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.\r
+\r
+ This program and the accompanying materials are made available under the\r
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ and is available at http://www.eclipse.org/legal/epl-v10.html\r
+--><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">\r
+\r
+  <modelVersion>4.0.0</modelVersion>\r
+\r
+  <parent>\r
+    <artifactId>sal-parent</artifactId>\r
+    <groupId>org.opendaylight.controller</groupId>\r
+    <version>1.1-SNAPSHOT</version>\r
+  </parent>\r
+  <artifactId>sal-dom-xsql-config</artifactId>\r
+  <groupId>org.opendaylight.controller</groupId>\r
+  <description>Configuration files for md-sal</description>\r
+  <packaging>jar</packaging>\r
+  <properties>\r
+      <!-- Optional TODO: Rename your configfile to taste -->\r
+      <configfile>04-xsql.xml</configfile>\r
+  </properties>\r
+  <build>\r
+    <plugins>\r
+        <plugin>\r
+        <groupId>org.codehaus.mojo</groupId>\r
+        <artifactId>build-helper-maven-plugin</artifactId>\r
+        <executions>\r
+          <execution>\r
+            <id>attach-artifacts</id>\r
+            <goals>\r
+              <goal>attach-artifact</goal>\r
+            </goals>\r
+            <phase>package</phase>\r
+            <configuration>\r
+              <artifacts>\r
+                <artifact>\r
+                  <file>${project.build.directory}/classes/${configfile}</file>\r
+                  <type>xml</type>\r
+                  <classifier>config</classifier>\r
+                </artifact>\r
+              </artifacts>\r
+            </configuration>\r
+          </execution>\r
+        </executions>\r
+      </plugin>\r
+    </plugins>\r
+  </build>\r
+  <scm>\r
+      <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>\r
+      <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>\r
+      <tag>HEAD</tag>\r
+      <url>https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=summary</url>\r
+   </scm>\r
+</project>\r
diff --git a/opendaylight/md-sal/sal-dom-xsql-config/src/main/resources/04-xsql.xml b/opendaylight/md-sal/sal-dom-xsql-config/src/main/resources/04-xsql.xml
new file mode 100644 (file)
index 0000000..d7d547d
--- /dev/null
@@ -0,0 +1,29 @@
+<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:XSQL="http://netconfcentral.org/ns/XSQL">
+                        XSQL:XSQL
+                    </type>
+                    <name>XSQL</name>
+                    <data-broker>
+                       <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+                       <name>binding-data-broker</name>
+                    </data-broker>
+                    <async-data-broker>
+                        <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
+                        <name>inmemory-data-broker</name>
+                    </async-data-broker>
+                    <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>
+            </modules>
+        </data>
+    </configuration>
+    <required-capabilities>
+        <capability>http://netconfcentral.org/ns/XSQL?module=XSQL&amp;revision=2014-06-26</capability>
+    </required-capabilities>
+</snapshot>
index 6d4400fe20f1f115d5e09ef56cc9a8fc749c8bfd..496f27ecaa1defe4f49d1cd724b58e8a3f673794 100644 (file)
@@ -200,8 +200,7 @@ public class XSQLAdapter extends Thread implements SchemaContextListener {
 
     }
 
-    protected void processCommand(StringBuffer inputString, PrintStream sout,
-            TelnetConnection tc) {
+    public void processCommand(StringBuffer inputString, PrintStream sout) {
         if (inputString.toString().trim().equals("r")) {
             sout.println(lastInputString);
             inputString = lastInputString;
@@ -263,25 +262,6 @@ public class XSQLAdapter extends Thread implements SchemaContextListener {
             for (int i = 0; i < iNames.length; i++) {
                 sout.println(iNames[i]);
             }
-        } else if (input.startsWith("cd sid")) {
-            String substr = input.substring("cd sid".length()).trim();
-            for (NEEntry e : elements.values()) {
-                if (((Module) e.ne).getName().equals(substr)) {
-                    tc.currentModule = (Module) e.ne;
-                }
-            }
-        } else if (input.equals("list sid")) {
-            String arr[] = new String[elements.size()];
-
-            int i = 0;
-            for (NEEntry entry : elements.values()) {
-                arr[i] = entry.toString();
-                i++;
-            }
-            Arrays.sort(arr);
-            for (String s : arr) {
-                sout.println(s);
-            }
         } else if (input.equals("help") || input.equals("?")) {
             // sout.println(getLongDescription());
         } else if (input.equals("avmdata")) {
@@ -517,7 +497,7 @@ public class XSQLAdapter extends Thread implements SchemaContextListener {
                         }
                     }
 
-                    processCommand(inputString, out, this);
+                    processCommand(inputString, out);
                     inputString = new StringBuffer();
                 }
             } catch (Exception err) {
index fd1627c6f994677abe043f767519fbb78e2d5eeb..b98844ba641f6e7f585c3c6b687c56d55161933c 100644 (file)
@@ -1,7 +1,9 @@
 package org.opendaylight.controller.config.yang.inmemory_datastore_provider;
 
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreConfigProperties;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreFactory;
+import org.opendaylight.controller.md.sal.dom.store.impl.jmx.InMemoryDataStoreStats;
 
 public class InMemoryConfigDataStoreProviderModule extends org.opendaylight.controller.config.yang.inmemory_datastore_provider.AbstractInMemoryConfigDataStoreProviderModule {
 
@@ -20,9 +22,19 @@ public class InMemoryConfigDataStoreProviderModule extends org.opendaylight.cont
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-        return InMemoryDOMDataStoreFactory.create("DOM-CFG", getSchemaServiceDependency(),
+
+        InMemoryDOMDataStore dataStore = InMemoryDOMDataStoreFactory.create(
+                "DOM-CFG", getSchemaServiceDependency(),
                 InMemoryDOMDataStoreConfigProperties.create(getMaxDataChangeExecutorPoolSize(),
-                        getMaxDataChangeExecutorQueueSize(), getMaxDataChangeListenerQueueSize()));
+                        getMaxDataChangeExecutorQueueSize(), getMaxDataChangeListenerQueueSize(),
+                        getMaxDataStoreExecutorQueueSize()));
+
+        InMemoryDataStoreStats statsBean = new InMemoryDataStoreStats("InMemoryConfigDataStore",
+                dataStore.getDataChangeListenerNotificationManager(), dataStore.getDomStoreExecutor());
+
+        dataStore.setCloseable(statsBean);
+
+        return dataStore;
     }
 
 }
index 7026b03022ff47b548743b34efb3f0f35d6d6e94..4532452c65e32521dece928f5b20f00310f3c358 100644 (file)
@@ -1,7 +1,9 @@
 package org.opendaylight.controller.config.yang.inmemory_datastore_provider;
 
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreConfigProperties;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreFactory;
+import org.opendaylight.controller.md.sal.dom.store.impl.jmx.InMemoryDataStoreStats;
 
 public class InMemoryOperationalDataStoreProviderModule extends org.opendaylight.controller.config.yang.inmemory_datastore_provider.AbstractInMemoryOperationalDataStoreProviderModule {
 
@@ -20,9 +22,17 @@ public class InMemoryOperationalDataStoreProviderModule extends org.opendaylight
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-        return InMemoryDOMDataStoreFactory.create("DOM-OPER", getOperationalSchemaServiceDependency(),
+        InMemoryDOMDataStore dataStore = InMemoryDOMDataStoreFactory.create("DOM-OPER", getSchemaServiceDependency(),
                 InMemoryDOMDataStoreConfigProperties.create(getMaxDataChangeExecutorPoolSize(),
-                        getMaxDataChangeExecutorQueueSize(), getMaxDataChangeListenerQueueSize()));
-    }
+                        getMaxDataChangeExecutorQueueSize(), getMaxDataChangeListenerQueueSize(),
+                        getMaxDataStoreExecutorQueueSize()));
+
+
+        InMemoryDataStoreStats statsBean = new InMemoryDataStoreStats("InMemoryOperationalDataStore",
+                dataStore.getDataChangeListenerNotificationManager(), dataStore.getDomStoreExecutor());
 
+        dataStore.setCloseable(statsBean);
+
+        return dataStore;
+    }
 }
diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ChangeListenerNotifyTask.java b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ChangeListenerNotifyTask.java
deleted file mode 100644 (file)
index 536cfa0..0000000
+++ /dev/null
@@ -1,54 +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.sal.dom.store.impl;
-
-import com.google.common.base.Preconditions;
-
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
-import org.opendaylight.yangtools.util.concurrent.NotificationManager;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-class ChangeListenerNotifyTask implements Runnable {
-    private static final Logger LOG = LoggerFactory.getLogger(ChangeListenerNotifyTask.class);
-
-    @SuppressWarnings("rawtypes")
-    private final NotificationManager<AsyncDataChangeListener,AsyncDataChangeEvent> notificationMgr;
-    private final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> event;
-    private final DataChangeListenerRegistration<?> listener;
-
-    @SuppressWarnings("rawtypes")
-    public ChangeListenerNotifyTask(final DataChangeListenerRegistration<?> listener,
-            final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> event,
-            final NotificationManager<AsyncDataChangeListener,AsyncDataChangeEvent> notificationMgr) {
-        this.notificationMgr = Preconditions.checkNotNull(notificationMgr);
-        this.listener = Preconditions.checkNotNull(listener);
-        this.event = Preconditions.checkNotNull(event);
-    }
-
-    @Override
-    public void run() {
-        final AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> l = listener.getInstance();
-        if (l == null) {
-            LOG.trace("Skipping event delivery to unregistered listener {}", l);
-            return;
-        }
-        LOG.trace("Listener {} event {}", l, event);
-
-        // FIXME: Yo dawg I heard you like queues, so this was queued to be queued
-        notificationMgr.submitNotification(l, event);
-    }
-
-    @Override
-    public String toString() {
-        return "ChangeListenerNotifyTask [listener=" + listener + ", event=" + event + "]";
-    }
-}
index 129013378ea57c713304793248e1cdc2f2c0a6ce..476356a19e79113b0b0121662b8842610757d12f 100644 (file)
@@ -7,30 +7,29 @@
  */
 package org.opendaylight.controller.md.sal.dom.store.impl;
 
+import static com.google.common.base.Preconditions.checkState;
+
 import com.google.common.base.Optional;
 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.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.annotation.concurrent.GuardedBy;
 
 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.AsyncDataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.md.sal.dom.store.impl.SnapshotBackedWriteTransaction.TransactionReadyPrototype;
-import org.opendaylight.yangtools.util.ExecutorServiceUtil;
-import org.opendaylight.yangtools.util.concurrent.NotificationManager;
-import org.opendaylight.yangtools.util.concurrent.QueuedNotificationManager;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificationAppliedException;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree;
-import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory;
 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
@@ -40,22 +39,23 @@ import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
 import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
 import org.opendaylight.yangtools.concepts.Identifiable;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.util.ExecutorServiceUtil;
+import org.opendaylight.yangtools.util.concurrent.QueuedNotificationManager;
+import org.opendaylight.yangtools.util.concurrent.QueuedNotificationManager.Invoker;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificationAppliedException;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
+import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.annotation.concurrent.GuardedBy;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-
-import static com.google.common.base.Preconditions.checkState;
-
 /**
  * In-memory DOM Data Store
  *
@@ -68,18 +68,17 @@ import static com.google.common.base.Preconditions.checkState;
 public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, SchemaContextListener,
         TransactionReadyPrototype,AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(InMemoryDOMDataStore.class);
+    private static final ListenableFuture<Void> SUCCESSFUL_FUTURE = Futures.immediateFuture(null);
 
-    @SuppressWarnings("rawtypes")
-    private static final QueuedNotificationManager.Invoker<AsyncDataChangeListener,
-                                       AsyncDataChangeEvent> DCL_NOTIFICATION_MGR_INVOKER =
-            new QueuedNotificationManager.Invoker<AsyncDataChangeListener,
-                                                  AsyncDataChangeEvent>() {
-
-                @SuppressWarnings("unchecked")
+    private static final Invoker<DataChangeListenerRegistration<?>, DOMImmutableDataChangeEvent> DCL_NOTIFICATION_MGR_INVOKER =
+            new Invoker<DataChangeListenerRegistration<?>, DOMImmutableDataChangeEvent>() {
                 @Override
-                public void invokeListener( AsyncDataChangeListener listener,
-                                            AsyncDataChangeEvent notification ) {
-                    listener.onDataChanged(notification);
+                public void invokeListener(final DataChangeListenerRegistration<?> listener,
+                                           final DOMImmutableDataChangeEvent notification ) {
+                    final AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> inst = listener.getInstance();
+                    if (inst != null) {
+                        inst.onDataChanged(notification);
+                    }
                 }
             };
 
@@ -88,24 +87,26 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
     private final AtomicLong txCounter = new AtomicLong(0);
     private final ListeningExecutorService listeningExecutor;
 
-    @SuppressWarnings("rawtypes")
-    private final NotificationManager<AsyncDataChangeListener,AsyncDataChangeEvent>
-                                                              dataChangeListenerNotificationManager;
+    private final QueuedNotificationManager<DataChangeListenerRegistration<?>, DOMImmutableDataChangeEvent> dataChangeListenerNotificationManager;
     private final ExecutorService dataChangeListenerExecutor;
 
+    private final ExecutorService domStoreExecutor;
+
     private final String name;
 
-    public InMemoryDOMDataStore(final String name, final ListeningExecutorService listeningExecutor,
+    private volatile AutoCloseable closeable;
+
+    public InMemoryDOMDataStore(final String name, final ExecutorService domStoreExecutor,
             final ExecutorService dataChangeListenerExecutor) {
-        this(name, listeningExecutor, dataChangeListenerExecutor,
-                InMemoryDOMDataStoreConfigProperties.DEFAULT_MAX_DATA_CHANGE_LISTENER_QUEUE_SIZE);
+        this(name, domStoreExecutor, dataChangeListenerExecutor,
+             InMemoryDOMDataStoreConfigProperties.DEFAULT_MAX_DATA_CHANGE_LISTENER_QUEUE_SIZE);
     }
 
-    public InMemoryDOMDataStore(final String name, final ListeningExecutorService listeningExecutor,
-            final ExecutorService dataChangeListenerExecutor, int maxDataChangeListenerQueueSize) {
+    public InMemoryDOMDataStore(final String name, final ExecutorService domStoreExecutor,
+            final ExecutorService dataChangeListenerExecutor, final int maxDataChangeListenerQueueSize) {
         this.name = Preconditions.checkNotNull(name);
-        this.listeningExecutor = Preconditions.checkNotNull(listeningExecutor);
-
+        this.domStoreExecutor = Preconditions.checkNotNull(domStoreExecutor);
+        this.listeningExecutor = MoreExecutors.listeningDecorator(this.domStoreExecutor);
         this.dataChangeListenerExecutor = Preconditions.checkNotNull(dataChangeListenerExecutor);
 
         dataChangeListenerNotificationManager =
@@ -114,6 +115,18 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
                         "DataChangeListenerQueueMgr");
     }
 
+    public void setCloseable(AutoCloseable closeable) {
+        this.closeable = closeable;
+    }
+
+    public QueuedNotificationManager<?, ?> getDataChangeListenerNotificationManager() {
+        return dataChangeListenerNotificationManager;
+    }
+
+    public ExecutorService getDomStoreExecutor() {
+        return domStoreExecutor;
+    }
+
     @Override
     public final String getIdentifier() {
         return name;
@@ -148,7 +161,16 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
     public void close() {
         ExecutorServiceUtil.tryGracefulShutdown(listeningExecutor, 30, TimeUnit.SECONDS);
         ExecutorServiceUtil.tryGracefulShutdown(dataChangeListenerExecutor, 30, TimeUnit.SECONDS);
+
+        if(closeable != null) {
+            try {
+                closeable.close();
+            } catch(Exception e) {
+                LOG.debug("Error closing instance", e);
+            }
+        }
     }
+
     @Override
     public <L extends AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>> ListenerRegistration<L> registerChangeListener(
             final YangInstanceIdentifier path, final L listener, final DataChangeScope scope) {
@@ -175,8 +197,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
                         .addCreated(path, data) //
                         .build();
 
-                new ChangeListenerNotifyTask(reg, event,
-                        dataChangeListenerNotificationManager).run();
+                dataChangeListenerNotificationManager.submitNotification(reg, event);
             }
         }
 
@@ -191,7 +212,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
     }
 
     @Override
-    public synchronized DOMStoreThreePhaseCommitCohort ready(final SnapshotBackedWriteTransaction writeTx) {
+    public DOMStoreThreePhaseCommitCohort ready(final SnapshotBackedWriteTransaction writeTx) {
         LOG.debug("Tx: {} is submitted. Modifications: {}", writeTx.getIdentifier(), writeTx.getMutatedView());
         return new ThreePhaseCommitImpl(writeTx);
     }
@@ -277,7 +298,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
         }
 
         public synchronized void onTransactionCommited(final SnapshotBackedWriteTransaction transaction) {
-            // If commited transaction is latestOutstandingTx we clear
+            // If committed transaction is latestOutstandingTx we clear
             // latestOutstandingTx
             // field in order to base new transactions on Datastore Data Tree
             // directly.
@@ -379,8 +400,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
                 @Override
                 public Void call() {
                     candidate = dataTree.prepare(modification);
-                    listenerResolver = ResolveDataChangeEventsTask.create(candidate, listenerTree,
-                            dataChangeListenerNotificationManager);
+                    listenerResolver = ResolveDataChangeEventsTask.create(candidate, listenerTree);
                     return null;
                 }
             });
@@ -389,7 +409,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
         @Override
         public ListenableFuture<Void> abort() {
             candidate = null;
-            return Futures.immediateFuture(null);
+            return SUCCESSFUL_FUTURE;
         }
 
         @Override
@@ -402,14 +422,10 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
              */
             synchronized (this) {
                 dataTree.commit(candidate);
-
-                for (ChangeListenerNotifyTask task : listenerResolver.call()) {
-                    LOG.trace("Scheduling invocation of listeners: {}", task);
-                    task.run();
-                }
+                listenerResolver.resolve(dataChangeListenerNotificationManager);
             }
 
-            return Futures.immediateFuture(null);
+            return SUCCESSFUL_FUTURE;
         }
     }
 }
index 6e451ba12b20241d97c2826dce55d3870de0b9cb..be89d53a69b2b99b442c0820781959f30832666f 100644 (file)
@@ -20,15 +20,18 @@ public class InMemoryDOMDataStoreConfigProperties {
     public static final int DEFAULT_MAX_DATA_CHANGE_EXECUTOR_QUEUE_SIZE = 1000;
     public static final int DEFAULT_MAX_DATA_CHANGE_EXECUTOR_POOL_SIZE = 20;
     public static final int DEFAULT_MAX_DATA_CHANGE_LISTENER_QUEUE_SIZE = 1000;
+    public static final int DEFAULT_MAX_DATA_STORE_EXECUTOR_QUEUE_SIZE = 5000;
 
     private static final InMemoryDOMDataStoreConfigProperties DEFAULT =
             create(DEFAULT_MAX_DATA_CHANGE_EXECUTOR_POOL_SIZE,
                     DEFAULT_MAX_DATA_CHANGE_EXECUTOR_QUEUE_SIZE,
-                    DEFAULT_MAX_DATA_CHANGE_LISTENER_QUEUE_SIZE);
+                    DEFAULT_MAX_DATA_CHANGE_LISTENER_QUEUE_SIZE,
+                    DEFAULT_MAX_DATA_STORE_EXECUTOR_QUEUE_SIZE);
 
     private final int maxDataChangeExecutorQueueSize;
     private final int maxDataChangeExecutorPoolSize;
     private final int maxDataChangeListenerQueueSize;
+    private final int maxDataStoreExecutorQueueSize;
 
     /**
      * Constructs an instance with the given property values.
@@ -39,11 +42,22 @@ public class InMemoryDOMDataStoreConfigProperties {
      *            maximum queue size for the data change notification executor.
      * @param maxDataChangeListenerQueueSize
      *            maximum queue size for the data change listeners.
+     * @param maxDataStoreExecutorQueueSize
+     *            maximum queue size for the data store executor.
      */
+    public static InMemoryDOMDataStoreConfigProperties create(int maxDataChangeExecutorPoolSize,
+            int maxDataChangeExecutorQueueSize, int maxDataChangeListenerQueueSize,
+            int maxDataStoreExecutorQueueSize) {
+        return new InMemoryDOMDataStoreConfigProperties(maxDataChangeExecutorPoolSize,
+                maxDataChangeExecutorQueueSize, maxDataChangeListenerQueueSize,
+                maxDataStoreExecutorQueueSize);
+    }
+
     public static InMemoryDOMDataStoreConfigProperties create(int maxDataChangeExecutorPoolSize,
             int maxDataChangeExecutorQueueSize, int maxDataChangeListenerQueueSize) {
         return new InMemoryDOMDataStoreConfigProperties(maxDataChangeExecutorPoolSize,
-                maxDataChangeExecutorQueueSize, maxDataChangeListenerQueueSize);
+                maxDataChangeExecutorQueueSize, maxDataChangeListenerQueueSize,
+                DEFAULT_MAX_DATA_STORE_EXECUTOR_QUEUE_SIZE);
     }
 
     /**
@@ -54,10 +68,12 @@ public class InMemoryDOMDataStoreConfigProperties {
     }
 
     private InMemoryDOMDataStoreConfigProperties(int maxDataChangeExecutorPoolSize,
-            int maxDataChangeExecutorQueueSize, int maxDataChangeListenerQueueSize) {
+            int maxDataChangeExecutorQueueSize, int maxDataChangeListenerQueueSize,
+            int maxDataStoreExecutorQueueSize) {
         this.maxDataChangeExecutorQueueSize = maxDataChangeExecutorQueueSize;
         this.maxDataChangeExecutorPoolSize = maxDataChangeExecutorPoolSize;
         this.maxDataChangeListenerQueueSize = maxDataChangeListenerQueueSize;
+        this.maxDataStoreExecutorQueueSize = maxDataStoreExecutorQueueSize;
     }
 
     /**
@@ -80,4 +96,11 @@ public class InMemoryDOMDataStoreConfigProperties {
     public int getMaxDataChangeListenerQueueSize() {
         return maxDataChangeListenerQueueSize;
     }
+
+    /**
+     * Returns the maximum queue size for the data store executor.
+     */
+    public int getMaxDataStoreExecutorQueueSize() {
+        return maxDataStoreExecutorQueueSize;
+    }
 }
index a3512743ed1a34acac5a1923983e06995e0d0f24..052fb2b89ba563c7be55612d75b48625f31de840 100644 (file)
@@ -9,13 +9,11 @@
 package org.opendaylight.controller.md.sal.dom.store.impl;
 
 import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
 
 import javax.annotation.Nullable;
 
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
 import org.opendaylight.yangtools.util.concurrent.SpecialExecutors;
-import com.google.common.util.concurrent.MoreExecutors;
 
 /**
  * A factory for creating InMemoryDOMDataStore instances.
@@ -61,9 +59,12 @@ public final class InMemoryDOMDataStoreFactory {
         ExecutorService dataChangeListenerExecutor = SpecialExecutors.newBlockingBoundedFastThreadPool(
                 dclExecutorMaxPoolSize, dclExecutorMaxQueueSize, name + "-DCL" );
 
+        ExecutorService domStoreExecutor = SpecialExecutors.newBoundedSingleThreadExecutor(
+                actualProperties.getMaxDataStoreExecutorQueueSize(), "DOMStore-" + name );
+
         InMemoryDOMDataStore dataStore = new InMemoryDOMDataStore(name,
-                MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()),
-                dataChangeListenerExecutor, actualProperties.getMaxDataChangeListenerQueueSize());
+                domStoreExecutor, dataChangeListenerExecutor,
+                actualProperties.getMaxDataChangeListenerQueueSize());
 
         if(schemaService != null) {
             schemaService.registerSchemaContextListener(dataStore);
index a4e8c86aa83f1b10f084f86f81a10feb08178d58..5fe9866b12ed0ec6e2a669de4cc7bd3b9957b641 100644 (file)
@@ -12,14 +12,10 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.Multimap;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Map.Entry;
-import java.util.concurrent.Callable;
 
 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.AsyncDataChangeListener;
 import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.Builder;
 import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.SimpleEventFactory;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree;
@@ -40,35 +36,23 @@ import org.slf4j.LoggerFactory;
  * Computes data change events for all affected registered listeners in data
  * tree.
  */
-final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListenerNotifyTask>> {
+final class ResolveDataChangeEventsTask {
     private static final Logger LOG = LoggerFactory.getLogger(ResolveDataChangeEventsTask.class);
 
-    @SuppressWarnings("rawtypes")
-    private final NotificationManager<AsyncDataChangeListener, AsyncDataChangeEvent> notificationMgr;
     private final DataTreeCandidate candidate;
     private final ListenerTree listenerRoot;
 
     private Multimap<DataChangeListenerRegistration<?>, DOMImmutableDataChangeEvent> collectedEvents;
 
-    @SuppressWarnings("rawtypes")
-    public ResolveDataChangeEventsTask(final DataTreeCandidate candidate, final ListenerTree listenerTree,
-            final NotificationManager<AsyncDataChangeListener, AsyncDataChangeEvent> notificationMgr) {
+    public ResolveDataChangeEventsTask(final DataTreeCandidate candidate, final ListenerTree listenerTree) {
         this.candidate = Preconditions.checkNotNull(candidate);
         this.listenerRoot = Preconditions.checkNotNull(listenerTree);
-        this.notificationMgr = Preconditions.checkNotNull(notificationMgr);
     }
 
     /**
-     * Resolves and creates Notification Tasks
-     *
-     * Implementation of done as Map-Reduce with two steps: 1. resolving events
-     * and their mapping to listeners 2. merging events affecting same listener
-     *
-     * @return An {@link Iterable} of Notification Tasks which needs to be executed in
-     *         order to delivery data change events.
+     * Resolves and submits notification tasks to the specified manager.
      */
-    @Override
-    public synchronized Iterable<ChangeListenerNotifyTask> call() {
+    public synchronized void resolve(final NotificationManager<DataChangeListenerRegistration<?>, DOMImmutableDataChangeEvent> manager) {
         try (final Walker w = listenerRoot.getWalker()) {
             // Defensive: reset internal state
             collectedEvents = ArrayListMultimap.create();
@@ -81,7 +65,6 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
              * Convert to tasks, but be mindful of multiple values -- those indicate multiple
              * wildcard matches, which need to be merged.
              */
-            final Collection<ChangeListenerNotifyTask> ret = new ArrayList<>();
             for (Entry<DataChangeListenerRegistration<?>, Collection<DOMImmutableDataChangeEvent>> e : collectedEvents.asMap().entrySet()) {
                 final Collection<DOMImmutableDataChangeEvent> col = e.getValue();
                 final DOMImmutableDataChangeEvent event;
@@ -98,12 +81,8 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
                     event = col.iterator().next();
                 }
 
-                ret.add(new ChangeListenerNotifyTask(e.getKey(), event, notificationMgr));
+                manager.submitNotification(e.getKey(), event);
             }
-
-            // FIXME: so now we have tasks to submit tasks... Inception-style!
-            LOG.debug("Created tasks {}", ret);
-            return ret;
         }
     }
 
@@ -333,10 +312,7 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
         return scope != null;
     }
 
-    @SuppressWarnings("rawtypes")
-    public static ResolveDataChangeEventsTask create(final DataTreeCandidate candidate,
-            final ListenerTree listenerTree,
-            final NotificationManager<AsyncDataChangeListener,AsyncDataChangeEvent> notificationMgr) {
-        return new ResolveDataChangeEventsTask(candidate, listenerTree, notificationMgr);
+    public static ResolveDataChangeEventsTask create(final DataTreeCandidate candidate, final ListenerTree listenerTree) {
+        return new ResolveDataChangeEventsTask(candidate, listenerTree);
     }
 }
index dca2eff70558c03de97c36aa46436caf21244a92..d3c5a7cb70e8013734f64619b456e74ed18ee0e2 100644 (file)
@@ -136,8 +136,7 @@ final class ResolveDataChangeState {
             return true;
         }
 
-        // FIXME: do we need anything else? If not, flip this to 'false'
-        return true;
+        return false;
     }
 
     /**
index 44ee61c116a9a4c5f8f336890827fcfceea68075..2caa76d49dff02a34ad98232ccdc7db139f07f2c 100644 (file)
@@ -33,7 +33,7 @@ final class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction
                                           implements DOMStoreReadTransaction {
 
     private static final Logger LOG = LoggerFactory.getLogger(SnapshotBackedReadTransaction.class);
-    private DataTreeSnapshot stableSnapshot;
+    private volatile DataTreeSnapshot stableSnapshot;
 
     public SnapshotBackedReadTransaction(final Object identifier, final DataTreeSnapshot snapshot) {
         super(identifier);
@@ -52,19 +52,21 @@ final class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction
         LOG.debug("Tx: {} Read: {}", getIdentifier(), path);
         checkNotNull(path, "Path must not be null.");
 
-        if(stableSnapshot == null) {
+        final DataTreeSnapshot snapshot = stableSnapshot;
+        if (snapshot == null) {
             return Futures.immediateFailedCheckedFuture(new ReadFailedException("Transaction is closed"));
         }
 
         try {
-            return Futures.immediateCheckedFuture(stableSnapshot.readNode(path));
+            return Futures.immediateCheckedFuture(snapshot.readNode(path));
         } catch (Exception e) {
             LOG.error("Tx: {} Failed Read of {}", getIdentifier(), path, e);
             return Futures.immediateFailedCheckedFuture(new ReadFailedException("Read failed",e));
         }
     }
 
-    @Override public CheckedFuture<Boolean, ReadFailedException> exists(YangInstanceIdentifier path) {
+    @Override
+    public CheckedFuture<Boolean, ReadFailedException> exists(YangInstanceIdentifier path) {
         LOG.debug("Tx: {} Exists: {}", getIdentifier(), path);
         checkNotNull(path, "Path must not be null.");
 
diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/jmx/InMemoryDataStoreStats.java b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/jmx/InMemoryDataStoreStats.java
new file mode 100644 (file)
index 0000000..b3608ec
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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.dom.store.impl.jmx;
+
+import java.util.concurrent.ExecutorService;
+
+import org.opendaylight.controller.md.sal.common.util.jmx.QueuedNotificationManagerMXBeanImpl;
+import org.opendaylight.controller.md.sal.common.util.jmx.ThreadExecutorStatsMXBeanImpl;
+import org.opendaylight.yangtools.util.concurrent.QueuedNotificationManager;
+
+/**
+ * Wrapper class for data store MXbeans.
+ *
+ * @author Thomas Pantelis
+ */
+public class InMemoryDataStoreStats implements AutoCloseable {
+
+    private final ThreadExecutorStatsMXBeanImpl notificationExecutorStatsBean;
+    private final ThreadExecutorStatsMXBeanImpl dataStoreExecutorStatsBean;
+    private final QueuedNotificationManagerMXBeanImpl notificationManagerStatsBean;
+
+    public InMemoryDataStoreStats(String mBeanType, QueuedNotificationManager<?, ?> manager,
+            ExecutorService dataStoreExecutor) {
+
+        this.notificationManagerStatsBean = new QueuedNotificationManagerMXBeanImpl(manager,
+                "notification-manager", mBeanType, null);
+        notificationManagerStatsBean.registerMBean();
+
+        this.notificationExecutorStatsBean = new ThreadExecutorStatsMXBeanImpl(manager.getExecutor(),
+                "notification-executor", mBeanType, null);
+        this.notificationExecutorStatsBean.registerMBean();
+
+        this.dataStoreExecutorStatsBean = new ThreadExecutorStatsMXBeanImpl(dataStoreExecutor,
+                "data-store-executor", mBeanType, null);
+        this.dataStoreExecutorStatsBean.registerMBean();
+    }
+
+    @Override
+    public void close() throws Exception {
+        if(notificationExecutorStatsBean != null) {
+            notificationExecutorStatsBean.unregisterMBean();
+        }
+
+        if(dataStoreExecutorStatsBean != null) {
+            dataStoreExecutorStatsBean.unregisterMBean();
+        }
+
+        if(notificationManagerStatsBean != null) {
+            notificationManagerStatsBean.unregisterMBean();
+        }
+    }
+}
index 1292d3772a6a9d99fb9527fa8688d1925f83a599..7d19a64446b519ea7795e86d81c6c431599ef7d9 100644 (file)
@@ -34,21 +34,7 @@ module opendaylight-inmemory-datastore-provider {
              config:java-name-prefix InMemoryOperationalDataStoreProvider;
       }
 
-
-    // Augments the 'configuration' choice node under modules/module.
-    augment "/config:modules/config:module/config:configuration" {
-        case inmemory-config-datastore-provider {
-            when "/config:modules/config:module/config:type = 'inmemory-config-datastore-provider'";
-
-            container schema-service {
-                uses config:service-ref {
-                   refine type {
-                          mandatory false;
-                          config:required-identity sal:schema-service;
-                    }
-                }
-            }
-
+    grouping datastore-configuration {
             leaf max-data-change-executor-queue-size {
                 default 1000;
                 type uint16;
@@ -66,42 +52,48 @@ module opendaylight-inmemory-datastore-provider {
                 type uint16;
                 description "The maximum queue size for the data change listeners.";
             }
-        }
+
+            leaf max-data-store-executor-queue-size {
+                default 5000;
+                type uint16;
+                description "The maximum queue size for the data store executor.";
+            }
     }
 
     // Augments the 'configuration' choice node under modules/module.
     augment "/config:modules/config:module/config:configuration" {
-        case inmemory-operational-datastore-provider {
-            when "/config:modules/config:module/config:type = 'inmemory-operational-datastore-provider'";
+        case inmemory-config-datastore-provider {
+            when "/config:modules/config:module/config:type = 'inmemory-config-datastore-provider'";
 
-            // Yang does not allow two cases from same namespaces with same children
-            // Schema-service dependency renamed to operational-schema-service
-            // to prevent conflict with schema-service container from inmemory-config-datastore-provider
-            container operational-schema-service {
-                uses config:service-ref {
-                    refine type {
-                        mandatory false;
-                        config:required-identity sal:schema-service;
+            container inmemory-config-datastore-provider {
+                container schema-service {
+                    uses config:service-ref {
+                        refine type {
+                            mandatory false;
+                            config:required-identity sal:schema-service;
+                        }
                     }
                 }
+                uses datastore-configuration;
             }
+        }
+    }
 
-            leaf max-data-change-executor-queue-size {
-                default 1000;
-                type uint16;
-                description "The maximum queue size for the data change notification executor.";
-            }
-
-            leaf max-data-change-executor-pool-size {
-                default 20;
-                type uint16;
-                description "The maximum thread pool size for the data change notification executor.";
-            }
+    // Augments the 'configuration' choice node under modules/module.
+    augment "/config:modules/config:module/config:configuration" {
+        case inmemory-operational-datastore-provider {
+            when "/config:modules/config:module/config:type = 'inmemory-operational-datastore-provider'";
 
-            leaf max-data-change-listener-queue-size {
-                default 1000;
-                type uint16;
-                description "The maximum queue size for the data change listeners.";
+            container inmemory-operational-datastore-provider {
+                container schema-service {
+                    uses config:service-ref {
+                        refine type {
+                            mandatory false;
+                            config:required-identity sal:schema-service;
+                        }
+                    }
+                }
+                uses datastore-configuration;
             }
         }
     }
diff --git a/opendaylight/md-sal/sal-karaf-xsql/pom.xml b/opendaylight/md-sal/sal-karaf-xsql/pom.xml
new file mode 100644 (file)
index 0000000..c32d960
--- /dev/null
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<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">\r
+\r
+    <!--
+        Licensed to the Apache Software Foundation (ASF) under one or more
+        contributor license agreements.  See the NOTICE file distributed with
+        this work for additional information regarding copyright ownership.
+        The ASF licenses this file to You under the Apache License, Version 2.0
+        (the "License"); you may not use this file except in compliance with
+        the License.  You may obtain a copy of the License at
+
+            http://www.apache.org/licenses/LICENSE-2.0
+
+        Unless required by applicable law or agreed to in writing, software
+        distributed under the License is distributed on an "AS IS" BASIS,
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+        See the License for the specific language governing permissions and
+        limitations under the License.
+    -->\r
+\r
+    <modelVersion>4.0.0</modelVersion>\r
+\r
+    <parent>\r
+    <artifactId>sal-parent</artifactId>\r
+    <groupId>org.opendaylight.controller</groupId>\r
+    <version>1.1-SNAPSHOT</version>\r
+  </parent>\r
+\r
+    <groupId>xsqlcommand</groupId>\r
+    <artifactId>xsqlcommand</artifactId>\r
+    <packaging>bundle</packaging>\r
+    <version>1.0.0-SNAPSHOT</version>\r
+    <name>Apache Karaf :: Shell odl/xsql Commands</name>\r
+\r
+    <description>Provides the OSGi odl commands</description>\r
+\r
+    <dependencies>\r
+        <dependency>\r
+            <groupId>org.apache.karaf.shell</groupId>\r
+            <artifactId>org.apache.karaf.shell.console</artifactId>\r
+            <version>3.0.1</version>\r
+        </dependency>\r
+\r
+        <dependency>\r
+            <groupId>org.osgi</groupId>\r
+            <artifactId>org.osgi.core</artifactId>\r
+            <version>5.0.0</version>\r
+            <scope>provided</scope>\r
+        </dependency>\r
+\r
+        <dependency>\r
+            <groupId>org.osgi</groupId>\r
+            <artifactId>org.osgi.compendium</artifactId>\r
+            <version>5.0.0</version>\r
+            <scope>provided</scope>\r
+        </dependency>\r
+\r
+        <dependency>\r
+            <groupId>junit</groupId>\r
+            <artifactId>junit</artifactId>\r
+            <version>4.11</version>\r
+            <scope>test</scope>\r
+        </dependency>\r
+        <dependency>\r
+            <groupId>org.opendaylight.controller</groupId>\r
+            <artifactId>sal-dom-xsql</artifactId>\r
+            <type>bundle</type>\r
+            <version>1.1-SNAPSHOT</version>\r
+        </dependency>\r
+    </dependencies>\r
+\r
+    <build>\r
+        <plugins>\r
+            <plugin>\r
+                <artifactId>maven-compiler-plugin</artifactId>\r
+                <inherited>true</inherited>\r
+                <version>2.3.2</version>\r
+                <configuration>\r
+                    <source>1.5</source>\r
+                    <target>1.5</target>\r
+                </configuration>\r
+            </plugin>\r
+            <plugin>\r
+                <groupId>org.apache.felix</groupId>\r
+                <artifactId>maven-bundle-plugin</artifactId>\r
+                <version>2.4.0</version>\r
+                <extensions>true</extensions>\r
+                <configuration>\r
+                    <instructions>\r
+                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>\r
+                        <Export-Package>org.opendaylight.controller.xsql*;version=${project.version}</Export-Package>\r
+                        <Import-Package>!org.opendaylight.controller.xsql*,\r
+                            org.apache.aries.blueprint,\r
+                            org.osgi.service.blueprint.container,\r
+                            org.osgi.service.blueprint.reflect,\r
+                            org.apache.felix.service.command,\r
+                            org.apache.karaf.shell.commands,\r
+                            org.apache.karaf.shell.console,\r
+                            *</Import-Package>\r
+                    </instructions>\r
+                </configuration>\r
+            </plugin>\r
+        </plugins>\r
+    </build>\r
+\r
+</project>\r
diff --git a/opendaylight/md-sal/sal-karaf-xsql/src/main/java/org/opendaylight/controller/xsql/xsql.java b/opendaylight/md-sal/sal-karaf-xsql/src/main/java/org/opendaylight/controller/xsql/xsql.java
new file mode 100644 (file)
index 0000000..b7994dc
--- /dev/null
@@ -0,0 +1,23 @@
+package org.opendaylight.controller.xsql;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.controller.md.sal.dom.xsql.XSQLAdapter;
+
+@Command(scope = "odl", name = "xsql", description = "XSQL Karaf Command")
+public class xsql extends OsgiCommandSupport {
+
+    @Option(name = "-o", aliases = { "--option" }, description = "An option to the command", required = false, multiValued = false)
+    private String option;
+
+    @Argument(name = "argument", description = "Argument to the command", required = false, multiValued = false)
+    private String argument;
+
+    protected Object doExecute() throws Exception {
+        XSQLAdapter.getInstance().processCommand(new StringBuffer(argument),
+                System.out);
+        return null;
+    }
+}
index d6bfc0c3b69152fd560afd545f11ddfd0773862a..e0b774f53c9008e3d8bd25772128e770b247419a 100644 (file)
@@ -115,6 +115,11 @@ public final class NetconfStateSchemas {
 
         final CompositeNode schemasNode =
                 (CompositeNode) NetconfMessageTransformUtil.findNode(schemasNodeResult.getResult(), DATA_STATE_SCHEMAS_IDENTIFIER);
+        if(schemasNode == null) {
+            logger.warn("{}: Unable to detect available schemas, get to {} was empty", id, STATE_SCHEMAS_IDENTIFIER);
+            return EMPTY;
+        }
+
         return create(id, schemasNode);
     }
 
@@ -151,7 +156,13 @@ public final class NetconfStateSchemas {
 
             QName childNode = NetconfMessageTransformUtil.IETF_NETCONF_MONITORING_SCHEMA_FORMAT.withoutRevision();
 
-            final String formatAsString = getSingleChildNodeValue(schemaNode, childNode).get();
+            String formatAsString = getSingleChildNodeValue(schemaNode, childNode).get();
+            //This is HotFix for situations where format statement in netconf-monitoring might be passed with prefix.
+            if (formatAsString.contains(":")) {
+                String[] prefixedString = formatAsString.split(":");
+                //FIXME: might be good idea to check prefix against model namespace
+                formatAsString = prefixedString[1];
+            }
             if(formatAsString.equals(Yang.QNAME.getLocalName()) == false) {
                 logger.debug("{}: Ignoring schema due to unsupported format: {}", id, formatAsString);
                 return Optional.absent();
index 3cc513600dd709484f464fbae0530c7df67b4f29..2000e11a35db1f26b330cc5f6df732aa1df058a4 100644 (file)
@@ -95,7 +95,7 @@ public final class NetconfDeviceSalFacade implements AutoCloseable, RemoteDevice
     }
 
     @Override
-    public void onDeviceDisconnected() {
+    public synchronized void onDeviceDisconnected() {
         salProvider.getDatastoreAdapter().updateDeviceState(false, Collections.<QName>emptySet());
         salProvider.getMountInstance().onDeviceDisconnected();
     }
index dc90fd3826a4204861a0e4dd69fcbd6436cec9ad..5a528bc418ea386a04b428e047c58fe7d47c74bb 100644 (file)
@@ -16,7 +16,6 @@ import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.concurrent.ExecutionException;
 import org.apache.commons.io.IOUtils;
 import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
 import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
@@ -97,18 +96,18 @@ public final class NetconfRemoteSchemaYangSourceProvider implements SchemaSource
                 rpc.invokeRpc(GET_SCHEMA_QNAME, getSchemaRequest),
                 new ResultToYangSourceTransformer(id, sourceIdentifier, moduleName, revision));
 
-        // FIXME remove this get, it is only present to wait until source is retrieved
+        final CheckedFuture<YangTextSchemaSource, SchemaSourceException> checked = Futures.makeChecked(transformed, MAPPER);
+
+        // / FIXME remove this get, it is only present to wait until source is retrieved
         // (goal is to limit concurrent schema download, since NetconfDevice listener does not handle concurrent messages properly)
         try {
             logger.trace("{}: Blocking for {}", id, sourceIdentifier);
-            transformed.get();
-        } catch (final InterruptedException e) {
-            throw new RuntimeException(e);
-        } catch (final ExecutionException e) {
-           throw new IllegalStateException(id + ": Failed while getting source: " + sourceIdentifier, e);
+            checked.checkedGet();
+        } catch (final SchemaSourceException e) {
+            return Futures.immediateFailedCheckedFuture(e);
         }
 
-        return Futures.makeChecked(transformed, MAPPER);
+        return checked;
     }
 
     /**
index 4e007f4c5d8e4447c1ea683312f40302bc91f2d9..08450b3e789892429bc37aa1f68b015fae2271fb 100644 (file)
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-data-api</artifactId>
-
     </dependency>
       <dependency>
           <groupId>org.opendaylight.yangtools</groupId>
           <artifactId>yang-model-api</artifactId>
-
       </dependency>
-
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-data-impl</artifactId>
-
     </dependency>
-
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-common</artifactId>
-
     </dependency>
-
-
     <dependency>
       <groupId>org.osgi</groupId>
       <artifactId>org.osgi.core</artifactId>
     </dependency>
-
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
     </dependency>
-
     <dependency>
       <groupId>org.scala-lang</groupId>
       <artifactId>scala-library</artifactId>
     <dependency>
       <groupId>com.codahale.metrics</groupId>
       <artifactId>metrics-core</artifactId>
-      <version>3.0.1</version>
     </dependency>
+
+      <dependency>
+          <groupId>com.codahale.metrics</groupId>
+          <artifactId>metrics-graphite</artifactId>
+      </dependency>
     <!-- Test Dependencies -->
     <dependency>
       <groupId>junit</groupId>
 
   <build>
     <plugins>
+        <plugin>
+            <groupId>org.jacoco</groupId>
+            <artifactId>jacoco-maven-plugin</artifactId>
+            <configuration>
+                <includes>
+                    <include>org.opendaylight.controller.*</include>
+                </includes>
+                <excludes>
+                    <exclude>org.opendaylight.controller.config.yang.config.*</exclude>
+                </excludes>
+                <check>false</check>
+            </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.apache.felix</groupId>
index 96f24724286192131c08177943a572c45dba5a96..d4da226b9dc4278cd508e83082283a3163c6615c 100644 (file)
@@ -15,8 +15,11 @@ import akka.actor.Props;
 import akka.actor.SupervisorStrategy;
 import akka.japi.Creator;
 import akka.japi.Function;
+import com.typesafe.config.Config;
+import com.typesafe.config.ConfigFactory;
 import org.opendaylight.controller.remote.rpc.messages.UpdateSchemaContext;
 import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
+import org.opendaylight.controller.remote.rpc.utils.ActorUtil;
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -69,10 +72,16 @@ public class RpcManager extends AbstractUntypedActor {
   private void createRpcActors() {
     LOG.debug("Create rpc registry and broker actors");
 
+      Config conf = ConfigFactory.load();
 
-    rpcRegistry = getContext().actorOf(Props.create(RpcRegistry.class), ActorConstants.RPC_REGISTRY);
+    rpcRegistry =
+            getContext().actorOf(Props.create(RpcRegistry.class).
+                withMailbox(ActorUtil.MAILBOX), ActorConstants.RPC_REGISTRY);
+
+    rpcBroker =
+            getContext().actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext).
+                withMailbox(ActorUtil.MAILBOX),ActorConstants.RPC_BROKER);
 
-    rpcBroker = getContext().actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext), ActorConstants.RPC_BROKER);
     RpcRegistry.Messages.SetLocalRouter localRouter = new RpcRegistry.Messages.SetLocalRouter(rpcBroker);
     rpcRegistry.tell(localRouter, self());
   }
index 76f59304576b731f1a15df9c277628ad9ff611d6..5109d316446b13158e3739824e653e0259929135 100644 (file)
@@ -20,6 +20,7 @@ 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.remote.rpc.utils.ActorUtil;
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import scala.concurrent.Future;
 
@@ -107,7 +108,7 @@ public class RpcRegistry extends UntypedActor {
 
         Preconditions.checkState(localRouter != null, "Router must be set first");
 
-        Future<Object> futureReply = Patterns.ask(bucketStore, new GetLocalBucket(), 1000);
+        Future<Object> futureReply = Patterns.ask(bucketStore, new GetLocalBucket(), ActorUtil.ASK_DURATION.toMillis());
         futureReply.map(getMapperToAddRoutes(msg.getRouteIdentifiers()), getContext().dispatcher());
     }
 
@@ -116,7 +117,7 @@ public class RpcRegistry extends UntypedActor {
      */
     private void receiveRemoveRoutes(RemoveRoutes msg) {
 
-        Future<Object> futureReply = Patterns.ask(bucketStore, new GetLocalBucket(), 1000);
+        Future<Object> futureReply = Patterns.ask(bucketStore, new GetLocalBucket(), ActorUtil.ASK_DURATION.toMillis());
         futureReply.map(getMapperToRemoveRoutes(msg.getRouteIdentifiers()), getContext().dispatcher());
 
     }
@@ -129,7 +130,7 @@ public class RpcRegistry extends UntypedActor {
     private void receiveGetRouter(FindRouters msg) {
         final ActorRef sender = getSender();
 
-        Future<Object> futureReply = Patterns.ask(bucketStore, new GetAllBuckets(), 1000);
+        Future<Object> futureReply = Patterns.ask(bucketStore, new GetAllBuckets(), ActorUtil.ASK_DURATION.toMillis());
         futureReply.map(getMapperToGetRouter(msg.getRouteIdentifier(), sender), getContext().dispatcher());
     }
 
index 3b078aa062fdf1fc3feaca7fa10147de8c3503cc..ff51f4fcfa671ff4ae71be72c6403b741e3de8dd 100644 (file)
@@ -16,6 +16,7 @@ import akka.actor.UntypedActor;
 import akka.cluster.ClusterActorRefProvider;
 import akka.event.Logging;
 import akka.event.LoggingAdapter;
+import org.opendaylight.controller.remote.rpc.utils.ActorUtil;
 import org.opendaylight.controller.utils.ConditionalProbe;
 
 import java.util.HashMap;
@@ -76,7 +77,7 @@ public class BucketStore extends UntypedActor {
         selfAddress = provider.getDefaultAddress();
 
         if ( provider instanceof ClusterActorRefProvider)
-            getContext().actorOf(Props.create(Gossiper.class), "gossiper");
+            getContext().actorOf(Props.create(Gossiper.class).withMailbox(ActorUtil.MAILBOX), "gossiper");
     }
 
     @Override
index a8bc25c40ba14b2ecf8c45926f7871f189dbdafa..f6ce5e55f3ee63602fc92529e92d6e93d0ff9bb3 100644 (file)
@@ -21,6 +21,7 @@ import akka.dispatch.Mapper;
 import akka.event.Logging;
 import akka.event.LoggingAdapter;
 import akka.pattern.Patterns;
+import org.opendaylight.controller.remote.rpc.utils.ActorUtil;
 import scala.concurrent.Future;
 import scala.concurrent.duration.FiniteDuration;
 
@@ -105,7 +106,7 @@ public class Gossiper extends UntypedActor {
         if (autoStartGossipTicks) {
             gossipTask = getContext().system().scheduler().schedule(
                     new FiniteDuration(1, TimeUnit.SECONDS),        //initial delay
-                    new FiniteDuration(500, TimeUnit.MILLISECONDS), //interval
+                    ActorUtil.GOSSIP_TICK_INTERVAL,                 //interval
                     getSelf(),                                       //target
                     new Messages.GossiperMessages.GossipTick(),      //message
                     getContext().dispatcher(),                       //execution context
@@ -227,7 +228,9 @@ public class Gossiper extends UntypedActor {
             return;
 
         final ActorRef sender = getSender();
-        Future<Object> futureReply = Patterns.ask(getContext().parent(), new GetBucketVersions(), 1000);
+        Future<Object> futureReply =
+                Patterns.ask(getContext().parent(), new GetBucketVersions(), ActorUtil.ASK_DURATION.toMillis());
+
         futureReply.map(getMapperToProcessRemoteStatus(sender, status), getContext().dispatcher());
 
     }
@@ -267,7 +270,8 @@ public class Gossiper extends UntypedActor {
      */
     void sendGossipTo(final ActorRef remote, final Set<Address> addresses){
 
-        Future<Object> futureReply = Patterns.ask(getContext().parent(), new GetBucketsByMembers(addresses), 1000);
+        Future<Object> futureReply =
+                Patterns.ask(getContext().parent(), new GetBucketsByMembers(addresses), ActorUtil.ASK_DURATION.toMillis());
         futureReply.map(getMapperToSendGossip(remote), getContext().dispatcher());
     }
 
@@ -279,7 +283,10 @@ public class Gossiper extends UntypedActor {
     void getLocalStatusAndSendTo(Address remoteActorSystemAddress){
 
         //Get local status from bucket store and send to remote
-        Future<Object> futureReply = Patterns.ask(getContext().parent(), new GetBucketVersions(), 1000);
+        Future<Object> futureReply =
+                Patterns.ask(getContext().parent(), new GetBucketVersions(), ActorUtil.ASK_DURATION.toMillis());
+
+        //Find gossiper on remote system
         ActorSelection remoteRef = getContext().system().actorSelection(
                 remoteActorSystemAddress.toString() + getSelf().path().toStringWithoutAddress());
 
index b7b2216a08b0293fccc733836355ed8e4bd5767a..ca14fecb4c4bc65d4d56f66b67b2533fd802ce2a 100644 (file)
@@ -20,28 +20,32 @@ import java.util.concurrent.TimeUnit;
 import static akka.pattern.Patterns.ask;
 
 public class ActorUtil {
-  public static final FiniteDuration LOCAL_ASK_DURATION = Duration.create(2, TimeUnit.SECONDS);
-  public static final FiniteDuration REMOTE_ASK_DURATION = Duration.create(15, TimeUnit.SECONDS);
-  public static final FiniteDuration ASK_DURATION = Duration.create(17, TimeUnit.SECONDS);
-  public static final FiniteDuration LOCAL_AWAIT_DURATION = Duration.create(2, TimeUnit.SECONDS);
-  public static final FiniteDuration REMOTE_AWAIT_DURATION = Duration.create(15, TimeUnit.SECONDS);
-  public static final FiniteDuration AWAIT_DURATION = Duration.create(17, TimeUnit.SECONDS);
-
-  /**
-   * Executes an operation on a local actor and wait for it's response
-   * @param actor
-   * @param message
-   * @param askDuration
-   * @param awaitDuration
-   * @return The response of the operation
-   */
-  public static Object executeOperation(ActorRef actor, Object message,
-                                        FiniteDuration askDuration, FiniteDuration awaitDuration) throws Exception{
-    Future<Object> future =
-        ask(actor, message, new Timeout(askDuration));
-
-      return Await.result(future, awaitDuration);
-  }
+    public static final FiniteDuration LOCAL_ASK_DURATION = Duration.create(2, TimeUnit.SECONDS);
+    public static final FiniteDuration REMOTE_ASK_DURATION = Duration.create(15, TimeUnit.SECONDS);
+    public static final FiniteDuration ASK_DURATION = Duration.create(17, TimeUnit.SECONDS);
+    public static final FiniteDuration LOCAL_AWAIT_DURATION = Duration.create(2, TimeUnit.SECONDS);
+    public static final FiniteDuration REMOTE_AWAIT_DURATION = Duration.create(15, TimeUnit.SECONDS);
+    public static final FiniteDuration AWAIT_DURATION = Duration.create(17, TimeUnit.SECONDS);
+    public static final FiniteDuration GOSSIP_TICK_INTERVAL = Duration.create(500, TimeUnit.MILLISECONDS);
+    public static final String MAILBOX = "bounded-mailbox";
+
+
+    /**
+     * Executes an operation on a local actor and wait for it's response
+     *
+     * @param actor
+     * @param message
+     * @param askDuration
+     * @param awaitDuration
+     * @return The response of the operation
+     */
+    public static Object executeOperation(ActorRef actor, Object message,
+                                          FiniteDuration askDuration, FiniteDuration awaitDuration) throws Exception {
+        Future<Object> future =
+                ask(actor, message, new Timeout(askDuration));
+
+        return Await.result(future, awaitDuration);
+    }
 
 
 }
index 711ae1c48b75c794bad3cb93de12e397632bcbfd..266832a0ab0491dfd5d58d2c0414c2733ef0300b 100644 (file)
@@ -38,10 +38,15 @@ odl-cluster-data {
 }
 
 odl-cluster-rpc {
+  bounded-mailbox {
+    mailbox-type = "org.opendaylight.controller.common.actor.MeteredBoundedMailbox"
+    mailbox-capacity = 1000
+    mailbox-push-timeout-time = 100ms
+  }
+
   akka {
     actor {
       provider = "akka.cluster.ClusterActorRefProvider"
-
     }
     remote {
       log-remote-lifecycle-events = off
index 17ad237ad7e4302065c08ff8796a058cd78d7885..8a7e4a039846205846e1b54b21981f78af843783 100644 (file)
@@ -14,8 +14,8 @@ import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
 import akka.testkit.JavaTestKit;
 import com.typesafe.config.ConfigFactory;
-import junit.framework.Assert;
 import org.junit.AfterClass;
+import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.controller.sal.core.api.Broker;
@@ -25,7 +25,6 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import scala.concurrent.Await;
 import scala.concurrent.duration.Duration;
 
-
 import java.util.concurrent.TimeUnit;
 
 import static org.mockito.Mockito.mock;
@@ -38,7 +37,7 @@ public class RemoteRpcProviderTest {
 
   @BeforeClass
   public static void setup() throws InterruptedException {
-    system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("odl-cluster"));
+    system = ActorSystem.create("odl-cluster-rpc", ConfigFactory.load().getConfig("odl-cluster-rpc"));
   }
 
   @AfterClass
@@ -59,7 +58,4 @@ public class RemoteRpcProviderTest {
         Duration.create(2, TimeUnit.SECONDS));
     Assert.assertTrue(actorRef.path().toString().contains(ActorConstants.RPC_MANAGER_PATH));
   }
-
-
-
 }
index 9b6215addd841633cf1dd57ce42c635d1dae89b7..98a33bf4e64a680adcc40d2dd3e92823a86c5fb6 100644 (file)
@@ -32,7 +32,7 @@ public class RouteRpcListenerTest {
 
   @BeforeClass
   public static void setup() throws InterruptedException {
-    system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("odl-cluster"));
+    system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("odl-cluster-rpc"));
   }
 
   @AfterClass
index 7b5a968866ca1ecca306b42fc09d76b0a6aaf20a..956e1599904ccc52303ff380892bc3531861cd5b 100644 (file)
@@ -28,7 +28,7 @@ public class RpcListenerTest {
 
   @BeforeClass
   public static void setup() throws InterruptedException {
-    system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("odl-cluster"));
+    system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("odl-cluster-rpc"));
   }
 
   @AfterClass
index e6793741a3ec2ef9030a2e469058ab92de93c153..83f52930b2b07ac32c75f83f437f1048132b54df 100644 (file)
@@ -10,10 +10,8 @@ import akka.actor.Props;
 import akka.testkit.JavaTestKit;
 import com.google.common.base.Predicate;
 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;
@@ -22,8 +20,6 @@ import org.opendaylight.controller.remote.rpc.registry.gossip.Messages;
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import org.opendaylight.controller.utils.ConditionalProbe;
 import org.opendaylight.yangtools.yang.common.QName;
-import scala.concurrent.Await;
-import scala.concurrent.Future;
 import scala.concurrent.duration.FiniteDuration;
 
 import javax.annotation.Nullable;
@@ -33,9 +29,9 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
-import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.SetLocalRouter;
 import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.AddOrUpdateRoutes;
 import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.RemoveRoutes;
+import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.SetLocalRouter;
 
 public class RpcRegistryTest {
 
@@ -95,7 +91,6 @@ public class RpcRegistryTest {
    */
   @Test
   public void testAddRemoveRpcOnSameNode() throws URISyntaxException, InterruptedException {
-    validateSystemStartup();
 
     final JavaTestKit mockBroker = new JavaTestKit(node1);
 
@@ -137,8 +132,6 @@ public class RpcRegistryTest {
   @Test
   public void testRpcAddRemoveInCluster() throws URISyntaxException, InterruptedException {
 
-    validateSystemStartup();
-
     final JavaTestKit mockBroker1 = new JavaTestKit(node1);
 
     //install probe on node2's bucket store
@@ -146,7 +139,6 @@ public class RpcRegistryTest {
     final JavaTestKit probe2 = createProbeForMessage(
         node2, bucketStorePath, Messages.BucketStoreMessages.UpdateRemoteBuckets.class);
 
-
     //Add rpc on node 1
     registry1.tell(new SetLocalRouter(mockBroker1.getRef()), mockBroker1.getRef());
     registry1.tell(getAddRouteMessage(), mockBroker1.getRef());
@@ -175,8 +167,6 @@ public class RpcRegistryTest {
   @Test
   public void testRpcAddedOnMultiNodes() throws Exception {
 
-    validateSystemStartup();
-
     final JavaTestKit mockBroker1 = new JavaTestKit(node1);
     final JavaTestKit mockBroker2 = new JavaTestKit(node2);
     final JavaTestKit mockBroker3 = new JavaTestKit(node3);
@@ -225,49 +215,6 @@ public class RpcRegistryTest {
 
   }
 
-  private void validateSystemStartup() throws InterruptedException {
-
-    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");
-
-    ActorSelection gossiper1 = node1.actorSelection(gossiper1Path);
-    ActorSelection gossiper2 = node2.actorSelection(gossiper2Path);
-    ActorSelection gossiper3 = node3.actorSelection(gossiper3Path);
-
-
-    if (!resolveReference(gossiper1, gossiper2, gossiper3))
-      Assert.fail("Could not find gossipers");
-  }
-
-  private Boolean resolveReference(ActorSelection... gossipers) {
-
-    Boolean resolved = true;
-    for (int i = 0; i < 5; i++) {
-
-      resolved = true;
-      System.out.println(System.currentTimeMillis() + " Resolving gossipers; trial #" + i);
-
-      for (ActorSelection gossiper : gossipers) {
-        ActorRef ref = null;
-
-        try {
-          Future<ActorRef> future = gossiper.resolveOne(new FiniteDuration(15000, TimeUnit.MILLISECONDS));
-          ref = Await.result(future, new FiniteDuration(10000, TimeUnit.MILLISECONDS));
-        } catch (Exception e) {
-          System.out.println("Could not find gossiper in attempt#" + i + ". Got exception " + e.getMessage());
-        }
-
-        if (ref == null)
-          resolved = false;
-      }
-
-      if (resolved) break;
-
-    }
-    return resolved;
-  }
-
   private AddOrUpdateRoutes getAddRouteMessage() throws URISyntaxException {
     return new AddOrUpdateRoutes(createRouteIds());
   }
index b21f0f0069e3db4d62a7e024c7c3d5ff513067d2..cd031a1d0abcf330b3c63c90a576b65dc2cd2d1d 100644 (file)
@@ -30,7 +30,7 @@ public class LatestEntryRoutingLogicTest {
 
   @BeforeClass
   public static void setup() throws InterruptedException {
-    system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("odl-cluster"));
+    system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("odl-cluster-rpc"));
   }
 
   @AfterClass
index 8100ed35abd580a13367922ff255e42c61369f93..5c4af8d3da457c99344c0a26942c9d3456694f75 100644 (file)
@@ -1,6 +1,12 @@
-odl-cluster{
+odl-cluster-rpc{
+  bounded-mailbox {
+    mailbox-type = "org.opendaylight.controller.common.actor.MeteredBoundedMailbox"
+    mailbox-capacity = 1000
+    mailbox-push-timeout-time = 10ms
+  }
+
   akka {
-    loglevel = "DEBUG"
+    loglevel = "INFO"
     #log-config-on-start = on
 
     actor {
@@ -34,12 +40,22 @@ unit-test{
     loglevel = "INFO"
     #loggers = ["akka.event.slf4j.Slf4jLogger"]
   }
+  bounded-mailbox {
+    mailbox-type = "org.opendaylight.controller.common.actor.MeteredBoundedMailbox"
+    mailbox-capacity = 1000
+    mailbox-push-timeout-time = 10ms
+  }
 }
 
 memberA{
+  bounded-mailbox {
+    mailbox-type = "org.opendaylight.controller.common.actor.MeteredBoundedMailbox"
+    mailbox-capacity = 1000
+    mailbox-push-timeout-time = 10ms
+  }
   akka {
     loglevel = "INFO"
-    loggers = ["akka.event.slf4j.Slf4jLogger"]
+    #loggers = ["akka.event.slf4j.Slf4jLogger"]
     actor {
       provider = "akka.cluster.ClusterActorRefProvider"
       debug {
@@ -65,11 +81,20 @@ memberA{
   }
 }
 memberB{
+  bounded-mailbox {
+    mailbox-type = "org.opendaylight.controller.common.actor.MeteredBoundedMailbox"
+    mailbox-capacity = 1000
+    mailbox-push-timeout-time = 10ms
+  }
   akka {
     loglevel = "INFO"
-    loggers = ["akka.event.slf4j.Slf4jLogger"]
+    #loggers = ["akka.event.slf4j.Slf4jLogger"]
+
     actor {
       provider = "akka.cluster.ClusterActorRefProvider"
+      debug {
+        #lifecycle = on
+      }
     }
     remote {
       log-received-messages = off
@@ -90,11 +115,19 @@ memberB{
   }
 }
 memberC{
+  bounded-mailbox {
+    mailbox-type = "org.opendaylight.controller.common.actor.MeteredBoundedMailbox"
+    mailbox-capacity = 1000
+    mailbox-push-timeout-time = 10ms
+  }
   akka {
     loglevel = "INFO"
-    loggers = ["akka.event.slf4j.Slf4jLogger"]
+    #loggers = ["akka.event.slf4j.Slf4jLogger"]
     actor {
       provider = "akka.cluster.ClusterActorRefProvider"
+      debug {
+        #lifecycle = on
+      }
     }
     remote {
       log-received-messages = off
@@ -113,4 +146,5 @@ memberC{
       auto-down-unreachable-after = 10s
     }
   }
-}
\ No newline at end of file
+}
+
index e61cafa70b40c83f922460572ee232f5043ed4ea..fe5c9f39d8251e903c1ed5d9f173ced7df5f0f5b 100644 (file)
       <artifactId>jaxrs-api</artifactId>
       <scope>provided</scope>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-core-spi</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-data-composite-node</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-data-codec-gson</artifactId>
+    </dependency>
+
     <dependency>
       <groupId>ch.qos.logback</groupId>
       <artifactId>logback-classic</artifactId>
       <artifactId>mockito-all</artifactId>
       <scope>test</scope>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-core-spi</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.yangtools</groupId>
-      <artifactId>yang-data-composite-node</artifactId>
-      <version>0.6.2-SNAPSHOT</version>
-    </dependency>
   </dependencies>
 
   <build>
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfConstants.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfConstants.java
new file mode 100644 (file)
index 0000000..1ec1c29
--- /dev/null
@@ -0,0 +1,7 @@
+package org.opendaylight.controller.sal.rest.api;
+
+public interface RestconfConstants {
+
+
+    public static String IDENTIFIER = "identifier";
+}
index 9c149a21e60e70ff88c0371e936e3844c05b5985..4a46a3c26712c8e54da6650bd4e68b2de9ad91ca 100644 (file)
@@ -21,10 +21,12 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
+import org.opendaylight.controller.sal.restconf.impl.NormalizedNodeContext;
 import org.opendaylight.controller.sal.restconf.impl.StructuredData;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.Node;
 
+
 /**
  * The URI hierarchy for the RESTCONF resources consists of an entry point container, 4 top-level resources, and 1
  * field.
@@ -109,14 +111,14 @@ public interface RestconfService {
     @Path("/config/{identifier:.+}")
     @Produces({ Draft02.MediaTypes.DATA + JSON, Draft02.MediaTypes.DATA + XML, MediaType.APPLICATION_JSON,
             MediaType.APPLICATION_XML, MediaType.TEXT_XML })
-    public StructuredData readConfigurationData(@Encoded @PathParam("identifier") String identifier,
+    public NormalizedNodeContext readConfigurationData(@Encoded @PathParam("identifier") String identifier,
             @Context UriInfo uriInfo);
 
     @GET
     @Path("/operational/{identifier:.+}")
     @Produces({ Draft02.MediaTypes.DATA + JSON, Draft02.MediaTypes.DATA + XML, MediaType.APPLICATION_JSON,
             MediaType.APPLICATION_XML, MediaType.TEXT_XML })
-    public StructuredData readOperationalData(@Encoded @PathParam("identifier") String identifier,
+    public NormalizedNodeContext readOperationalData(@Encoded @PathParam("identifier") String identifier,
             @Context UriInfo uriInfo);
 
     @PUT
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/AbstractIdentifierAwareJaxRsProvider.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/AbstractIdentifierAwareJaxRsProvider.java
new file mode 100644 (file)
index 0000000..978ae0d
--- /dev/null
@@ -0,0 +1,30 @@
+package org.opendaylight.controller.sal.rest.impl;
+
+import com.google.common.base.Optional;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+import org.opendaylight.controller.sal.rest.api.RestconfConstants;
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.InstanceIdentifierContext;
+
+public class AbstractIdentifierAwareJaxRsProvider {
+
+    @Context
+    private UriInfo uriInfo;
+
+    protected final String getIdentifier() {
+        return uriInfo.getPathParameters().getFirst(RestconfConstants.IDENTIFIER);
+    }
+
+    protected final Optional<InstanceIdentifierContext> getIdentifierWithSchema() {
+        return Optional.of(getInstanceIdentifierContext());
+    }
+
+    protected InstanceIdentifierContext getInstanceIdentifierContext() {
+        return ControllerContext.getInstance().toInstanceIdentifier(getIdentifier());
+    }
+
+    protected UriInfo getUriInfo() {
+        return uriInfo;
+    }
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonNormalizedNodeBodyReader.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonNormalizedNodeBodyReader.java
new file mode 100644 (file)
index 0000000..dc989d2
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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.rest.impl;
+
+import com.google.common.base.Optional;
+import com.google.gson.stream.JsonReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.Provider;
+import org.opendaylight.controller.sal.rest.api.Draft02;
+import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.restconf.impl.InstanceIdentifierContext;
+import org.opendaylight.controller.sal.restconf.impl.NormalizedNodeContext;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.codec.gson.JsonParserStream;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Provider
+@Consumes({ Draft02.MediaTypes.DATA + RestconfService.JSON, Draft02.MediaTypes.OPERATION + RestconfService.JSON,
+        MediaType.APPLICATION_JSON })
+public class JsonNormalizedNodeBodyReader extends AbstractIdentifierAwareJaxRsProvider implements MessageBodyReader<NormalizedNodeContext> {
+
+    private final static Logger LOG = LoggerFactory.getLogger(JsonNormalizedNodeBodyReader.class);
+
+    @Override
+    public boolean isReadable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+            final MediaType mediaType) {
+        return true;
+    }
+
+    @Override
+    public NormalizedNodeContext readFrom(final Class<NormalizedNodeContext> type, final Type genericType,
+            final Annotation[] annotations, final MediaType mediaType,
+            final MultivaluedMap<String, String> httpHeaders, final InputStream entityStream) throws IOException,
+            WebApplicationException {
+        try {
+            Optional<InstanceIdentifierContext> path = getIdentifierWithSchema();
+            NormalizedNodeResult resultHolder = new NormalizedNodeResult();
+            NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
+            JsonParserStream jsonParser = JsonParserStream.create(writer, path.get().getSchemaContext());
+            JsonReader reader = new JsonReader(new InputStreamReader(entityStream));
+            jsonParser.parse(reader);
+            return new NormalizedNodeContext(path.get(),resultHolder.getResult());
+        } catch (Exception e) {
+            LOG.debug("Error parsing json input", e);
+
+            throw new RestconfDocumentedException("Error parsing input: " + e.getMessage(), ErrorType.PROTOCOL,
+                    ErrorTag.MALFORMED_MESSAGE);
+        }
+    }
+}
+
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/NormalizedNodeJsonBodyWriter.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/NormalizedNodeJsonBodyWriter.java
new file mode 100644 (file)
index 0000000..cfb5e5d
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * 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.rest.impl;
+
+import com.google.common.base.Charsets;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.util.Iterator;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import org.opendaylight.controller.sal.rest.api.Draft02;
+import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.restconf.impl.InstanceIdentifierContext;
+import org.opendaylight.controller.sal.restconf.impl.NormalizedNodeContext;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+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.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
+import org.opendaylight.yangtools.yang.data.codec.gson.JSONNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+@Provider
+@Produces({ Draft02.MediaTypes.API + RestconfService.JSON, Draft02.MediaTypes.DATA + RestconfService.JSON,
+    Draft02.MediaTypes.OPERATION + RestconfService.JSON, MediaType.APPLICATION_JSON })
+public class NormalizedNodeJsonBodyWriter implements MessageBodyWriter<NormalizedNodeContext> {
+
+    @Override
+    public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) {
+        return type.equals(NormalizedNodeContext.class);
+    }
+
+    @Override
+    public long getSize(final NormalizedNodeContext t, final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) {
+        return -1;
+    }
+
+    @Override
+    public void writeTo(final NormalizedNodeContext t, final Class<?> type, final Type genericType, final Annotation[] annotations,
+            final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream)
+                    throws IOException, WebApplicationException {
+        NormalizedNode<?, ?> data = t.getData();
+        InstanceIdentifierContext context = t.getInstanceIdentifierContext();
+        DataSchemaNode schema = context.getSchemaNode();
+        SchemaPath path = context.getSchemaNode().getPath();
+        OutputStreamWriter outputWriter = new OutputStreamWriter(entityStream, Charsets.UTF_8);
+        if (data == null) {
+            throw new RestconfDocumentedException(Response.Status.NOT_FOUND);
+        }
+
+        boolean isDataRoot = false;
+        URI initialNs = null;
+        outputWriter.write('{');
+        if (SchemaPath.ROOT.equals(path)) {
+            isDataRoot = true;
+        } else {
+            path = path.getParent();
+            // FIXME: Add proper handling of reading root.
+        }
+        if(!schema.isAugmenting() && !(schema instanceof SchemaContext)) {
+            initialNs = schema.getQName().getNamespace();
+        }
+        NormalizedNodeStreamWriter jsonWriter = JSONNormalizedNodeStreamWriter.create(context.getSchemaContext(),path,initialNs,outputWriter);
+        NormalizedNodeWriter nnWriter = NormalizedNodeWriter.forStreamWriter(jsonWriter);
+        if(isDataRoot) {
+            writeDataRoot(outputWriter,nnWriter,(ContainerNode) data);
+        } else {
+            if(data instanceof MapEntryNode) {
+                data = ImmutableNodes.mapNodeBuilder(data.getNodeType()).withChild(((MapEntryNode) data)).build();
+            }
+            nnWriter.write(data);
+        }
+        nnWriter.flush();
+        outputWriter.write('}');
+        outputWriter.flush();
+    }
+
+    private void writeDataRoot(OutputStreamWriter outputWriter, NormalizedNodeWriter nnWriter, ContainerNode data) throws IOException {
+        Iterator<DataContainerChild<? extends PathArgument, ?>> iterator = data.getValue().iterator();
+        while(iterator.hasNext()) {
+            DataContainerChild<? extends PathArgument, ?> child = iterator.next();
+            nnWriter.write(child);
+            nnWriter.flush();
+            if(iterator.hasNext()) {
+                outputWriter.write(",");
+            }
+        }
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/NormalizedNodeXmlBodyWriter.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/NormalizedNodeXmlBodyWriter.java
new file mode 100644 (file)
index 0000000..3a6de30
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * 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.rest.impl;
+
+import com.google.common.base.Throwables;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.xml.stream.FactoryConfigurationError;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import org.opendaylight.controller.sal.rest.api.Draft02;
+import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.restconf.impl.InstanceIdentifierContext;
+import org.opendaylight.controller.sal.restconf.impl.NormalizedNodeContext;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.yangtools.yang.common.QName;
+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.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XMLStreamNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+@Provider
+@Produces({ Draft02.MediaTypes.API + RestconfService.XML, Draft02.MediaTypes.DATA + RestconfService.XML,
+        Draft02.MediaTypes.OPERATION + RestconfService.XML, MediaType.APPLICATION_XML, MediaType.TEXT_XML })
+public class NormalizedNodeXmlBodyWriter implements MessageBodyWriter<NormalizedNodeContext> {
+
+    private static final XMLOutputFactory XML_FACTORY;
+
+    static {
+        XML_FACTORY = XMLOutputFactory.newFactory();
+        XML_FACTORY.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
+    }
+
+    @Override
+    public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+            final MediaType mediaType) {
+        return type.equals(NormalizedNodeContext.class);
+    }
+
+    @Override
+    public long getSize(final NormalizedNodeContext t, final Class<?> type, final Type genericType,
+            final Annotation[] annotations, final MediaType mediaType) {
+        return -1;
+    }
+
+    @Override
+    public void writeTo(final NormalizedNodeContext t, final Class<?> type, final Type genericType,
+            final Annotation[] annotations, final MediaType mediaType,
+            final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream) throws IOException,
+            WebApplicationException {
+        InstanceIdentifierContext pathContext = t.getInstanceIdentifierContext();
+        if (t.getData() == null) {
+            throw new RestconfDocumentedException(Response.Status.NOT_FOUND);
+        }
+
+        XMLStreamWriter xmlWriter;
+        try {
+            xmlWriter = XML_FACTORY.createXMLStreamWriter(entityStream);
+        } catch (XMLStreamException e) {
+            throw new IllegalStateException(e);
+        } catch (FactoryConfigurationError e) {
+            throw new IllegalStateException(e);
+        }
+        NormalizedNode<?, ?> data = t.getData();
+        SchemaPath schemaPath = pathContext.getSchemaNode().getPath();
+
+        boolean isDataRoot = false;
+        if (SchemaPath.ROOT.equals(schemaPath)) {
+            isDataRoot = true;
+        } else {
+            schemaPath = schemaPath.getParent();
+        }
+
+        NormalizedNodeStreamWriter jsonWriter = XMLStreamNormalizedNodeStreamWriter.create(xmlWriter,
+                pathContext.getSchemaContext(), schemaPath);
+        NormalizedNodeWriter nnWriter = NormalizedNodeWriter.forStreamWriter(jsonWriter);
+        if (isDataRoot) {
+            writeRootElement(xmlWriter, nnWriter, (ContainerNode) data);
+        } else {
+            if (data instanceof MapEntryNode) {
+                // Restconf allows returning one list item. We need to wrap it
+                // in map node in order to serialize it properly
+                data = ImmutableNodes.mapNodeBuilder(data.getNodeType()).addChild((MapEntryNode) data).build();
+            }
+            nnWriter.write(data);
+            nnWriter.flush();
+        }
+    }
+
+    private void writeRootElement(XMLStreamWriter xmlWriter, NormalizedNodeWriter nnWriter, ContainerNode data)
+            throws IOException {
+        try {
+            QName name = SchemaContext.NAME;
+            xmlWriter.writeStartElement(name.getNamespace().toString(), name.getLocalName());
+            for (DataContainerChild<? extends PathArgument, ?> child : data.getValue()) {
+                nnWriter.write(child);
+            }
+            nnWriter.flush();
+            xmlWriter.writeEndElement();
+            xmlWriter.flush();
+        } catch (XMLStreamException e) {
+            Throwables.propagate(e);
+        }
+    }
+}
index b4b2a1f9ef7249734e128456a33876abc3862ae8..a298f4b0937ae71c146c9baada15a14535b7de9d 100644 (file)
@@ -19,7 +19,13 @@ public class RestconfApplication extends Application {
 
     @Override
     public Set<Class<?>> getClasses() {
-        return ImmutableSet.<Class<?>> of(RestconfDocumentedExceptionMapper.class);
+        return ImmutableSet.<Class<?>> builder()
+                .add(RestconfDocumentedExceptionMapper.class)
+                .add(XmlNormalizedNodeBodyReader.class)
+                .add(JsonNormalizedNodeBodyReader.class)
+                .add(NormalizedNodeJsonBodyWriter.class)
+                .add(NormalizedNodeXmlBodyWriter.class)
+                .build();
     }
 
     @Override
@@ -33,10 +39,10 @@ public class RestconfApplication extends Application {
         singletons.add(controllerContext);
         singletons.add(brokerFacade);
         singletons.add(restconfImpl);
-        singletons.add(XmlToCompositeNodeProvider.INSTANCE);
         singletons.add(StructuredDataToXmlProvider.INSTANCE);
-        singletons.add(JsonToCompositeNodeProvider.INSTANCE);
         singletons.add(StructuredDataToJsonProvider.INSTANCE);
+        singletons.add(JsonToCompositeNodeProvider.INSTANCE);
+        singletons.add(XmlToCompositeNodeProvider.INSTANCE);
         return singletons;
     }
 
index 933ed0f849e7171b7c16c423c5462aa8de1bb25a..063d2f51afffdd0c7094d7363d95795182b5cd8e 100644 (file)
@@ -30,27 +30,24 @@ import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 
 @Provider
 @Produces({ Draft02.MediaTypes.API + RestconfService.JSON, Draft02.MediaTypes.DATA + RestconfService.JSON,
-        Draft02.MediaTypes.OPERATION + RestconfService.JSON, MediaType.APPLICATION_JSON })
+    Draft02.MediaTypes.OPERATION + RestconfService.JSON, MediaType.APPLICATION_JSON })
 public enum StructuredDataToJsonProvider implements MessageBodyWriter<StructuredData> {
     INSTANCE;
 
     @Override
-    public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
-            final MediaType mediaType) {
+    public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) {
         return type.equals(StructuredData.class);
     }
 
     @Override
-    public long getSize(final StructuredData t, final Class<?> type, final Type genericType,
-            final Annotation[] annotations, final MediaType mediaType) {
+    public long getSize(final StructuredData t, final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) {
         return -1;
     }
 
     @Override
-    public void writeTo(final StructuredData t, final Class<?> type, final Type genericType,
-            final Annotation[] annotations, final MediaType mediaType,
-            final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream) throws IOException,
-            WebApplicationException {
+    public void writeTo(final StructuredData t, final Class<?> type, final Type genericType, final Annotation[] annotations,
+            final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream)
+                    throws IOException, WebApplicationException {
         CompositeNode data = t.getData();
         if (data == null) {
             throw new RestconfDocumentedException(Response.Status.NOT_FOUND);
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlNormalizedNodeBodyReader.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlNormalizedNodeBodyReader.java
new file mode 100644 (file)
index 0000000..062a448
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * 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.rest.impl;
+
+import com.google.common.base.Optional;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.List;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.Provider;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import org.opendaylight.controller.sal.rest.api.Draft02;
+import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.restconf.impl.InstanceIdentifierContext;
+import org.opendaylight.controller.sal.restconf.impl.NormalizedNodeContext;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+@Provider
+@Consumes({ Draft02.MediaTypes.DATA + RestconfService.XML, Draft02.MediaTypes.OPERATION + RestconfService.XML,
+    MediaType.APPLICATION_XML, MediaType.TEXT_XML })
+public class XmlNormalizedNodeBodyReader extends AbstractIdentifierAwareJaxRsProvider implements MessageBodyReader<NormalizedNodeContext> {
+
+    private final static Logger LOG = LoggerFactory.getLogger(XmlNormalizedNodeBodyReader.class);
+    private final static DomToNormalizedNodeParserFactory DOM_PARSER_FACTORY = DomToNormalizedNodeParserFactory.getInstance(XmlUtils.DEFAULT_XML_CODEC_PROVIDER);
+    private static final DocumentBuilderFactory BUILDERFACTORY;
+
+    static {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        factory.setCoalescing(true);
+        factory.setIgnoringElementContentWhitespace(true);
+        factory.setIgnoringComments(true);
+        BUILDERFACTORY = factory;
+    }
+
+    @Override
+    public boolean isReadable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+            final MediaType mediaType) {
+        return true;
+    }
+
+    @Override
+    public NormalizedNodeContext readFrom(final Class<NormalizedNodeContext> type, final Type genericType,
+            final Annotation[] annotations, final MediaType mediaType,
+            final MultivaluedMap<String, String> httpHeaders, final InputStream entityStream) throws IOException,
+            WebApplicationException {
+        try {
+            Optional<InstanceIdentifierContext> path = getIdentifierWithSchema();
+
+            final DocumentBuilder dBuilder;
+            try {
+                dBuilder = BUILDERFACTORY.newDocumentBuilder();
+            } catch (ParserConfigurationException e) {
+                throw new RuntimeException("Failed to parse XML document", e);
+            }
+            Document doc = dBuilder.parse(entityStream);
+
+            NormalizedNode<?, ?> result = parse(path.get(),doc);
+            return new NormalizedNodeContext(path.get(),result);
+        } catch (Exception e) {
+            LOG.debug("Error parsing json input", e);
+
+            throw new RestconfDocumentedException("Error parsing input: " + e.getMessage(), ErrorType.PROTOCOL,
+                    ErrorTag.MALFORMED_MESSAGE);
+        }
+    }
+
+    private static NormalizedNode<?,?> parse(InstanceIdentifierContext pathContext,Document doc) {
+        List<Element> elements = Collections.singletonList(doc.getDocumentElement());
+        DataSchemaNode schemaNode = pathContext.getSchemaNode();
+        if(schemaNode instanceof ContainerSchemaNode) {
+            return DOM_PARSER_FACTORY.getContainerNodeParser().parse(Collections.singletonList(doc.getDocumentElement()), (ContainerSchemaNode) schemaNode);
+        } else if(schemaNode instanceof ListSchemaNode) {
+            ListSchemaNode casted = (ListSchemaNode) schemaNode;
+            return DOM_PARSER_FACTORY.getMapEntryNodeParser().parse(elements, casted);
+        }
+        return null;
+    }
+}
+
index 5944d6003e9e1e33dba8a0b482a60de5f01ac4c0..6b9da80c685f913cce59edb19bc4588b16e0ed57 100644 (file)
@@ -28,6 +28,7 @@ import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
 import org.opendaylight.yangtools.yang.data.api.Node;
 
+@Deprecated
 public class XmlToCompositeNodeReader {
 
     private final static XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
@@ -45,7 +46,6 @@ public class XmlToCompositeNodeReader {
         }
 
         eventReader = xmlInputFactory.createXMLEventReader(entityStream);
-
         if (eventReader.hasNext()) {
             XMLEvent element = eventReader.peek();
             if (element.isStartDocument()) {
@@ -110,7 +110,7 @@ public class XmlToCompositeNodeReader {
         return entityStream;
     }
 
-    private boolean isInputStreamEmpty(InputStream entityStream) throws IOException {
+    private boolean isInputStreamEmpty(final InputStream entityStream) throws IOException {
         boolean isEmpty = false;
         entityStream.mark(1);
         if (entityStream.read() == -1) {
@@ -180,7 +180,7 @@ public class XmlToCompositeNodeReader {
                 resolveValueOfElement(data, startElement));
     }
 
-    private String getValueOf(StartElement startElement) throws XMLStreamException {
+    private String getValueOf(final StartElement startElement) throws XMLStreamException {
         String data = null;
         if (eventReader.hasNext()) {
             final XMLEvent innerEvent = eventReader.peek();
@@ -201,7 +201,7 @@ public class XmlToCompositeNodeReader {
         return data == null ? null : data.trim();
     }
 
-    private String getAdditionalData(XMLEvent event) throws XMLStreamException {
+    private String getAdditionalData(final XMLEvent event) throws XMLStreamException {
         String data = "";
         if (eventReader.hasNext()) {
             final XMLEvent innerEvent = eventReader.peek();
@@ -216,16 +216,16 @@ public class XmlToCompositeNodeReader {
         return data;
     }
 
-    private String getLocalNameFor(StartElement startElement) {
+    private String getLocalNameFor(final StartElement startElement) {
         return startElement.getName().getLocalPart();
     }
 
-    private URI getNamespaceFor(StartElement startElement) {
+    private URI getNamespaceFor(final StartElement startElement) {
         String namespaceURI = startElement.getName().getNamespaceURI();
         return namespaceURI.isEmpty() ? null : URI.create(namespaceURI);
     }
 
-    private Object resolveValueOfElement(String value, StartElement startElement) {
+    private Object resolveValueOfElement(final String value, final StartElement startElement) {
         // it could be instance-identifier Built-In Type
         if (value.startsWith("/")) {
             IdentityValuesDTO iiValue = RestUtil.asInstanceIdentifier(value, new RestUtil.PrefixMapingFromXml(
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlToNormalizedNodeReaderWithSchema.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlToNormalizedNodeReaderWithSchema.java
deleted file mode 100644 (file)
index 935d96c..0000000
+++ /dev/null
@@ -1,352 +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.rest.impl;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Stack;
-import javax.xml.stream.XMLEventReader;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLStreamConstants;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.events.Characters;
-import javax.xml.stream.events.StartElement;
-import javax.xml.stream.events.XMLEvent;
-import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
-import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
-import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.RestCodec;
-import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
-import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-
-public class XmlToNormalizedNodeReaderWithSchema {
-
-    private final static XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
-    private XMLEventReader eventReader;
-    private InstanceIdWithSchemaNode iiWithSchema;
-
-    public XmlToNormalizedNodeReaderWithSchema(final InstanceIdWithSchemaNode iiWithSchema) {
-        this.iiWithSchema = iiWithSchema;
-    }
-
-    public Node<?> read(InputStream entityStream) throws XMLStreamException, UnsupportedFormatException, IOException {
-        // Get an XML stream which can be marked, and reset, so we can check and see if there is
-        // any content being provided.
-        entityStream = getMarkableStream(entityStream);
-
-        if (isInputStreamEmpty(entityStream)) {
-            return null;
-        }
-
-        eventReader = xmlInputFactory.createXMLEventReader(entityStream);
-        if (eventReader.hasNext()) {
-            XMLEvent element = eventReader.peek();
-            if (element.isStartDocument()) {
-                eventReader.nextEvent();
-            }
-        }
-
-        final Stack<NodeWrapper<?>> processingQueue = new Stack<>();
-        NodeWrapper<?> root = null;
-        NodeWrapper<?> element = null;
-        Stack<DataSchemaNode> processingQueueSchema = new Stack<>();
-
-        while (eventReader.hasNext()) {
-            final XMLEvent event = eventReader.nextEvent();
-
-            if (event.isStartElement()) {
-                final StartElement startElement = event.asStartElement();
-                CompositeNodeWrapper compParentNode = null;
-                if (!processingQueue.isEmpty() && processingQueue.peek() instanceof CompositeNodeWrapper) {
-                    compParentNode = (CompositeNodeWrapper) processingQueue.peek();
-                    findSchemaNodeForElement(startElement, processingQueueSchema);
-                } else {
-                    processingQueueSchema = checkElementAndSchemaNodeNameAndNamespace(startElement,
-                            iiWithSchema.getSchemaNode());
-                    DataSchemaNode currentSchemaNode = processingQueueSchema.peek();
-                    if (!(currentSchemaNode instanceof ListSchemaNode)
-                            && !(currentSchemaNode instanceof ContainerSchemaNode)) {
-                        throw new UnsupportedFormatException(
-                                "Top level element has to be of type list or container schema node.");
-                    }
-                }
-
-                NodeWrapper<?> newNode = null;
-                if (isCompositeNodeEvent(event)) {
-                    newNode = resolveCompositeNodeFromStartElement(processingQueueSchema.peek().getQName());
-                    if (root == null) {
-                        root = newNode;
-                    }
-                } else if (isSimpleNodeEvent(event)) {
-                    newNode = resolveSimpleNodeFromStartElement(processingQueueSchema.peek(), getValueOf(startElement));
-                    if (root == null) {
-                        root = newNode;
-                    }
-                }
-
-                if (newNode != null) {
-                    processingQueue.push(newNode);
-                    if (compParentNode != null) {
-                        compParentNode.addValue(newNode);
-                    }
-                }
-            } else if (event.isEndElement()) {
-                element = processingQueue.pop();
-//                if(((EndElement)event).getName().getLocalPart().equals
-                processingQueueSchema.pop();
-            }
-        }
-
-        if (!root.getLocalName().equals(element.getLocalName())) {
-            throw new UnsupportedFormatException("XML should contain only one root element");
-        }
-
-        return root.unwrap();
-    }
-
-    private void findSchemaNodeForElement(StartElement element, Stack<DataSchemaNode> processingQueueSchema) {
-        DataSchemaNode currentSchemaNode = processingQueueSchema.peek();
-        if (currentSchemaNode instanceof DataNodeContainer) {
-            final URI realNamespace = getNamespaceFor(element);
-            final String realName = getLocalNameFor(element);
-            Map<URI, DataSchemaNode> childNamesakes = resolveChildsWithNameAsElement(
-                    ((DataNodeContainer) currentSchemaNode), realName);
-            DataSchemaNode childDataSchemaNode = childNamesakes.get(realNamespace);
-            if (childDataSchemaNode == null) {
-                throw new RestconfDocumentedException("Element " + realName + " has namespace " + realNamespace
-                        + ". Available namespaces are: " + childNamesakes.keySet(), ErrorType.APPLICATION,
-                        ErrorTag.INVALID_VALUE);
-            }
-            processingQueueSchema.push(childDataSchemaNode);
-        } else {
-            throw new RestconfDocumentedException("Element " + processingQueueSchema.peek().getQName().getLocalName()
-                    + " should be data node container .", ErrorType.APPLICATION, ErrorTag.INVALID_VALUE);
-        }
-
-    }
-
-    /**
-     * Returns map of data schema node which are accesible by URI which have equal name
-     */
-    private Map<URI, DataSchemaNode> resolveChildsWithNameAsElement(final DataNodeContainer dataNodeContainer,
-            final String realName) {
-        final Map<URI, DataSchemaNode> namespaceToDataSchemaNode = new HashMap<URI, DataSchemaNode>();
-        for (DataSchemaNode dataSchemaNode : dataNodeContainer.getChildNodes()) {
-            if (dataSchemaNode.equals(realName)) {
-                namespaceToDataSchemaNode.put(dataSchemaNode.getQName().getNamespace(), dataSchemaNode);
-            }
-        }
-        return namespaceToDataSchemaNode;
-    }
-
-    private final Stack<DataSchemaNode> checkElementAndSchemaNodeNameAndNamespace(final StartElement startElement,
-            final DataSchemaNode node) {
-        checkArgument(startElement != null, "Start Element cannot be NULL!");
-        final String expectedName = node.getQName().getLocalName();
-        final String xmlName = getLocalNameFor(startElement);
-        final URI expectedNamespace = node.getQName().getNamespace();
-        final URI xmlNamespace = getNamespaceFor(startElement);
-        if (!expectedName.equals(xmlName)) {
-            throw new RestconfDocumentedException("Xml element name: " + xmlName + "\nSchema node name: "
-                    + expectedName, org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType.APPLICATION,
-                    ErrorTag.INVALID_VALUE);
-        }
-
-        if (xmlNamespace != null && !expectedNamespace.equals(xmlNamespace)) {
-            throw new RestconfDocumentedException("Xml element ns: " + xmlNamespace + "\nSchema node ns: "
-                    + expectedNamespace,
-                    org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType.APPLICATION,
-                    ErrorTag.INVALID_VALUE);
-        }
-        Stack<DataSchemaNode> processingQueueSchema = new Stack<>();
-        processingQueueSchema.push(node);
-        return processingQueueSchema;
-    }
-
-    /**
-     * If the input stream is not markable, then it wraps the input stream with a buffered stream, which is mark able.
-     * That way we can check if the stream is empty safely.
-     *
-     * @param entityStream
-     * @return
-     */
-    private InputStream getMarkableStream(InputStream entityStream) {
-        if (!entityStream.markSupported()) {
-            entityStream = new BufferedInputStream(entityStream);
-        }
-        return entityStream;
-    }
-
-    private boolean isInputStreamEmpty(final InputStream entityStream) throws IOException {
-        boolean isEmpty = false;
-        entityStream.mark(1);
-        if (entityStream.read() == -1) {
-            isEmpty = true;
-        }
-        entityStream.reset();
-        return isEmpty;
-    }
-
-    private boolean isSimpleNodeEvent(final XMLEvent event) throws XMLStreamException {
-        checkArgument(event != null, "XML Event cannot be NULL!");
-        if (event.isStartElement()) {
-            XMLEvent innerEvent = skipCommentsAndWhitespace();
-            if (innerEvent != null && (innerEvent.isCharacters() || innerEvent.isEndElement())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private boolean isCompositeNodeEvent(final XMLEvent event) throws XMLStreamException {
-        checkArgument(event != null, "XML Event cannot be NULL!");
-        if (event.isStartElement()) {
-            XMLEvent innerEvent = skipCommentsAndWhitespace();
-            if (innerEvent != null) {
-                if (innerEvent.isStartElement()) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    private XMLEvent skipCommentsAndWhitespace() throws XMLStreamException {
-        while (eventReader.hasNext()) {
-            XMLEvent event = eventReader.peek();
-            if (event.getEventType() == XMLStreamConstants.COMMENT) {
-                eventReader.nextEvent();
-                continue;
-            }
-
-            if (event.isCharacters()) {
-                Characters chars = event.asCharacters();
-                if (chars.isWhiteSpace()) {
-                    eventReader.nextEvent();
-                    continue;
-                }
-            }
-            return event;
-        }
-        return null;
-    }
-
-    private CompositeNodeWrapper resolveCompositeNodeFromStartElement(final QName qName) {
-        // checkArgument(startElement != null, "Start Element cannot be NULL!");
-        CompositeNodeWrapper compositeNodeWrapper = new CompositeNodeWrapper("dummy");
-        compositeNodeWrapper.setQname(qName);
-        return compositeNodeWrapper;
-
-    }
-
-    private SimpleNodeWrapper resolveSimpleNodeFromStartElement(final DataSchemaNode node, final String value)
-            throws XMLStreamException {
-        // checkArgument(startElement != null, "Start Element cannot be NULL!");
-        Object deserializedValue = null;
-
-        if (node instanceof LeafSchemaNode) {
-            TypeDefinition<?> baseType = RestUtil.resolveBaseTypeFrom(((LeafSchemaNode) node).getType());
-            deserializedValue = RestCodec.from(baseType, iiWithSchema.getMountPoint()).deserialize(value);
-        } else if (node instanceof LeafListSchemaNode) {
-            TypeDefinition<?> baseType = RestUtil.resolveBaseTypeFrom(((LeafListSchemaNode) node).getType());
-            deserializedValue = RestCodec.from(baseType, iiWithSchema.getMountPoint()).deserialize(value);
-        }
-        // String data;
-        // if (data == null) {
-        // return new EmptyNodeWrapper(getNamespaceFor(startElement), getLocalNameFor(startElement));
-        // }
-        SimpleNodeWrapper simpleNodeWrapper = new SimpleNodeWrapper("dummy", deserializedValue);
-        simpleNodeWrapper.setQname(node.getQName());
-        return simpleNodeWrapper;
-    }
-
-    private String getValueOf(final StartElement startElement) throws XMLStreamException {
-        String data = null;
-        if (eventReader.hasNext()) {
-            final XMLEvent innerEvent = eventReader.peek();
-            if (innerEvent.isCharacters()) {
-                final Characters chars = innerEvent.asCharacters();
-                if (!chars.isWhiteSpace()) {
-                    data = innerEvent.asCharacters().getData();
-                    data = data + getAdditionalData(eventReader.nextEvent());
-                }
-            } else if (innerEvent.isEndElement()) {
-                if (startElement.getLocation().getCharacterOffset() == innerEvent.getLocation().getCharacterOffset()) {
-                    data = null;
-                } else {
-                    data = "";
-                }
-            }
-        }
-        return data == null ? null : data.trim();
-    }
-
-    private String getAdditionalData(final XMLEvent event) throws XMLStreamException {
-        String data = "";
-        if (eventReader.hasNext()) {
-            final XMLEvent innerEvent = eventReader.peek();
-            if (innerEvent.isCharacters() && !innerEvent.isEndElement()) {
-                final Characters chars = innerEvent.asCharacters();
-                if (!chars.isWhiteSpace()) {
-                    data = innerEvent.asCharacters().getData();
-                    data = data + getAdditionalData(eventReader.nextEvent());
-                }
-            }
-        }
-        return data;
-    }
-
-    private String getLocalNameFor(final StartElement startElement) {
-        return startElement.getName().getLocalPart();
-    }
-
-    private URI getNamespaceFor(final StartElement startElement) {
-        String namespaceURI = startElement.getName().getNamespaceURI();
-        return namespaceURI.isEmpty() ? null : URI.create(namespaceURI);
-    }
-
-    private Object resolveValueOfElement(final String value, final StartElement startElement) {
-        // it could be instance-identifier Built-In Type
-        if (value.startsWith("/")) {
-            IdentityValuesDTO iiValue = RestUtil.asInstanceIdentifier(value, new RestUtil.PrefixMapingFromXml(
-                    startElement));
-            if (iiValue != null) {
-                return iiValue;
-            }
-        }
-        // it could be identityref Built-In Type
-        String[] namespaceAndValue = value.split(":");
-        if (namespaceAndValue.length == 2) {
-            String namespace = startElement.getNamespaceContext().getNamespaceURI(namespaceAndValue[0]);
-            if (namespace != null && !namespace.isEmpty()) {
-                return new IdentityValuesDTO(namespace, namespaceAndValue[1], namespaceAndValue[0], value);
-            }
-        }
-        // it is not "prefix:value" but just "value"
-        return value;
-    }
-
-}
index f11e25c046feab69fe3c41f229dfdbadd496e18d..8dbc5b50ee5dbd8ac374ef7d1452384442923085 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.controller.sal.restconf.impl;
 
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
@@ -40,6 +41,7 @@ import javax.ws.rs.core.Response.Status;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
@@ -176,31 +178,39 @@ public class BrokerFacade {
     private NormalizedNode<?, ?> readDataViaTransaction(final DOMDataReadTransaction transaction,
             LogicalDatastoreType datastore, YangInstanceIdentifier path) {
         LOG.trace("Read " + datastore.name() + " via Restconf: {}", path);
-        final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> listenableFuture =
-                                                                 transaction.read(datastore, path);
+        final ListenableFuture<Optional<NormalizedNode<?, ?>>> listenableFuture = transaction.read(datastore, path);
+        if (listenableFuture != null) {
+            Optional<NormalizedNode<?, ?>> optional;
+            try {
+                LOG.debug("Reading result data from transaction.");
+                optional = listenableFuture.get();
+            } catch (InterruptedException | ExecutionException e) {
+                throw new RestconfDocumentedException("Problem to get data from transaction.", e.getCause());
 
-        try {
-            Optional<NormalizedNode<?, ?>> optional = listenableFuture.checkedGet();
-            return optional.isPresent() ? optional.get() : null;
-        } catch(ReadFailedException e) {
-            throw new RestconfDocumentedException(e.getMessage(), e, e.getErrorList());
+            }
+            if (optional != null) {
+                if (optional.isPresent()) {
+                    return optional.get();
+                }
+            }
         }
+        return null;
     }
 
     private CheckedFuture<Void, TransactionCommitFailedException> postDataViaTransaction(
             final DOMDataReadWriteTransaction rWTransaction, final LogicalDatastoreType datastore,
             final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload, DataNormalizationOperation<?> root) {
-        CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> futureDatastoreData =
-                                                               rWTransaction.read(datastore, path);
+        ListenableFuture<Optional<NormalizedNode<?, ?>>> futureDatastoreData = rWTransaction.read(datastore, path);
         try {
-            final Optional<NormalizedNode<?, ?>> optionalDatastoreData = futureDatastoreData.checkedGet();
+            final Optional<NormalizedNode<?, ?>> optionalDatastoreData = futureDatastoreData.get();
             if (optionalDatastoreData.isPresent() && payload.equals(optionalDatastoreData.get())) {
-                LOG.trace("Post Configuration via Restconf was not executed because data already exists :{}", path);
+                String errMsg = "Post Configuration via Restconf was not executed because data already exists";
+                LOG.trace(errMsg + ":{}", path);
                 throw new RestconfDocumentedException("Data already exists for path: " + path, ErrorType.PROTOCOL,
                         ErrorTag.DATA_EXISTS);
             }
-        } catch(ReadFailedException e) {
-            LOG.warn("Error reading from datastore with path: " + path, e);
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.trace("It wasn't possible to get data loaded from datastore at path " + path);
         }
 
         ensureParentsByMerge(datastore, path, rWTransaction, root);
@@ -241,21 +251,27 @@ public class BrokerFacade {
             try {
                 currentOp = currentOp.getChild(currentArg);
             } catch (DataNormalizationException e) {
-                throw new RestconfDocumentedException(
-                        String.format("Error normalizing data for path %s", normalizedPath), e);
+                throw new IllegalArgumentException(
+                        String.format("Invalid child encountered in path %s", normalizedPath), e);
             }
             currentArguments.add(currentArg);
             YangInstanceIdentifier currentPath = YangInstanceIdentifier.create(currentArguments);
 
+            final Boolean exists;
+
             try {
 
-                boolean exists = rwTx.exists(store, currentPath).checkedGet();
-                if (!exists && iterator.hasNext()) {
-                    rwTx.merge(store, currentPath, currentOp.createDefault(currentArg));
-                }
+                CheckedFuture<Boolean, ReadFailedException> future =
+                    rwTx.exists(store, currentPath);
+                exists = future.checkedGet();
             } catch (ReadFailedException e) {
                 LOG.error("Failed to read pre-existing data from store {} path {}", store, currentPath, e);
-                throw new RestconfDocumentedException("Failed to read pre-existing data", e);
+                throw new IllegalStateException("Failed to read pre-existing data", e);
+            }
+
+
+            if (!exists && iterator.hasNext()) {
+                rwTx.merge(store, currentPath, currentOp.createDefault(currentArg));
             }
         }
     }
index 93e6a2c0e98504e169703423837177078992c2a4..b0a6e0d6f3885f20242d483044c0cfa92af1dea6 100644 (file)
@@ -118,15 +118,19 @@ public class ControllerContext implements SchemaContextListener {
         this.onGlobalContextUpdated(schemas);
     }
 
-    public InstanceIdWithSchemaNode toInstanceIdentifier(final String restconfInstance) {
+    public InstanceIdentifierContext toInstanceIdentifier(final String restconfInstance) {
         return this.toIdentifier(restconfInstance, false);
     }
 
-    public InstanceIdWithSchemaNode toMountPointIdentifier(final String restconfInstance) {
+    public SchemaContext getGlobalSchema() {
+        return globalSchema;
+    }
+
+    public InstanceIdentifierContext toMountPointIdentifier(final String restconfInstance) {
         return this.toIdentifier(restconfInstance, true);
     }
 
-    private InstanceIdWithSchemaNode toIdentifier(final String restconfInstance, final boolean toMountPointIdentifier) {
+    private InstanceIdentifierContext toIdentifier(final String restconfInstance, final boolean toMountPointIdentifier) {
         this.checkPreconditions();
 
         final List<String> pathArgs = urlPathArgsDecode(SLASH_SPLITTER.split(restconfInstance));
@@ -144,7 +148,7 @@ public class ControllerContext implements SchemaContextListener {
 
         InstanceIdentifierBuilder builder = YangInstanceIdentifier.builder();
         Module latestModule = globalSchema.findModuleByName(startModule, null);
-        InstanceIdWithSchemaNode iiWithSchemaNode = this.collectPathArguments(builder, pathArgs, latestModule, null,
+        InstanceIdentifierContext iiWithSchemaNode = this.collectPathArguments(builder, pathArgs, latestModule, null,
                 toMountPointIdentifier);
 
         if (iiWithSchemaNode == null) {
@@ -462,7 +466,7 @@ public class ControllerContext implements SchemaContextListener {
         return object == null ? "" : URLEncoder.encode(object.toString(), ControllerContext.URI_ENCODING_CHAR_SET);
     }
 
-    private InstanceIdWithSchemaNode collectPathArguments(final InstanceIdentifierBuilder builder,
+    private InstanceIdentifierContext collectPathArguments(final InstanceIdentifierBuilder builder,
             final List<String> strings, final DataNodeContainer parentNode, final DOMMountPoint mountPoint,
             final boolean returnJustMountPoint) {
         Preconditions.<List<String>> checkNotNull(strings);
@@ -472,7 +476,7 @@ public class ControllerContext implements SchemaContextListener {
         }
 
         if (strings.isEmpty()) {
-            return new InstanceIdWithSchemaNode(builder.toInstance(), ((DataSchemaNode) parentNode), mountPoint);
+            return new InstanceIdentifierContext(builder.toInstance(), ((DataSchemaNode) parentNode), mountPoint,mountPoint != null ? mountPoint.getSchemaContext() : globalSchema);
         }
 
         String head = strings.iterator().next();
@@ -511,12 +515,12 @@ public class ControllerContext implements SchemaContextListener {
 
                 if (returnJustMountPoint) {
                     YangInstanceIdentifier instance = YangInstanceIdentifier.builder().toInstance();
-                    return new InstanceIdWithSchemaNode(instance, mountPointSchema, mount);
+                    return new InstanceIdentifierContext(instance, mountPointSchema, mount,mountPointSchema);
                 }
 
                 if (strings.size() == 1) {
                     YangInstanceIdentifier instance = YangInstanceIdentifier.builder().toInstance();
-                    return new InstanceIdWithSchemaNode(instance, mountPointSchema, mount);
+                    return new InstanceIdentifierContext(instance, mountPointSchema, mount,mountPointSchema);
                 }
 
                 final String moduleNameBehindMountPoint = toModuleName(strings.get(1));
@@ -632,7 +636,7 @@ public class ControllerContext implements SchemaContextListener {
                     returnJustMountPoint);
         }
 
-        return new InstanceIdWithSchemaNode(builder.toInstance(), targetNode, mountPoint);
+        return new InstanceIdentifierContext(builder.toInstance(), targetNode, mountPoint,mountPoint != null ? mountPoint.getSchemaContext() : globalSchema);
     }
 
     public static DataSchemaNode findInstanceDataChildByNameAndNamespace(final DataNodeContainer container, final String name,
@@ -10,18 +10,21 @@ package org.opendaylight.controller.sal.restconf.impl;
 import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
-public class InstanceIdWithSchemaNode {
+public class InstanceIdentifierContext {
 
     private final YangInstanceIdentifier instanceIdentifier;
     private final DataSchemaNode schemaNode;
     private final DOMMountPoint mountPoint;
+    private final SchemaContext schemaContext;
 
-    public InstanceIdWithSchemaNode(YangInstanceIdentifier instanceIdentifier, DataSchemaNode schemaNode,
-            DOMMountPoint mountPoint) {
+    public InstanceIdentifierContext(YangInstanceIdentifier instanceIdentifier, DataSchemaNode schemaNode,
+            DOMMountPoint mountPoint,SchemaContext context) {
         this.instanceIdentifier = instanceIdentifier;
         this.schemaNode = schemaNode;
         this.mountPoint = mountPoint;
+        this.schemaContext = context;
     }
 
     public YangInstanceIdentifier getInstanceIdentifier() {
@@ -36,4 +39,8 @@ public class InstanceIdWithSchemaNode {
         return mountPoint;
     }
 
+    public SchemaContext getSchemaContext() {
+        return schemaContext;
+    }
+
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/NormalizedDataPrunner.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/NormalizedDataPrunner.java
new file mode 100644 (file)
index 0000000..5d0185b
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * 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.restconf.impl;
+
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+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.AnyXmlNode;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MixinNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
+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.api.DataContainerNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+
+class NormalizedDataPrunner {
+
+    public DataContainerChild<?, ?> pruneDataAtDepth(final DataContainerChild<?, ?> node, final Integer depth) {
+        if (depth == null) {
+            return node;
+        }
+
+        if (node instanceof LeafNode || node instanceof LeafSetNode || node instanceof AnyXmlNode
+                || node instanceof OrderedLeafSetNode) {
+            return node;
+        } else if (node instanceof MixinNode) {
+            return processMixinNode(node, depth);
+        } else if (node instanceof DataContainerNode) {
+            return processContainerNode(node, depth);
+        }
+        throw new IllegalStateException("Unexpected Mixin node occured why pruning data to requested depth");
+    }
+
+    private DataContainerChild<?, ?> processMixinNode(final NormalizedNode<?, ?> node, final Integer depth) {
+        if (node instanceof AugmentationNode) {
+            return processAugmentationNode(node, depth);
+        } else if (node instanceof ChoiceNode) {
+            return processChoiceNode(node, depth);
+        } else if (node instanceof OrderedMapNode) {
+            return processOrderedMapNode(node, depth);
+        } else if (node instanceof MapNode) {
+            return processMapNode(node, depth);
+        } else if (node instanceof UnkeyedListNode) {
+            return processUnkeyedListNode(node, depth);
+        }
+        throw new IllegalStateException("Unexpected Mixin node occured why pruning data to requested depth");
+    }
+
+    private DataContainerChild<?, ?> processContainerNode(final NormalizedNode<?, ?> node, final Integer depth) {
+        final ContainerNode containerNode = (ContainerNode) node;
+        DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> newContainerBuilder = Builders.containerBuilder()
+                .withNodeIdentifier(containerNode.getIdentifier());
+        if (depth > 1) {
+            processDataContainerChild((DataContainerNode<?>) node, depth, newContainerBuilder);
+        }
+        return newContainerBuilder.build();
+    }
+
+    private DataContainerChild<?, ?> processChoiceNode(final NormalizedNode<?, ?> node, final Integer depth) {
+        final ChoiceNode choiceNode = (ChoiceNode) node;
+        DataContainerNodeBuilder<NodeIdentifier, ChoiceNode> newChoiceBuilder = Builders.choiceBuilder()
+                .withNodeIdentifier(choiceNode.getIdentifier());
+
+        processDataContainerChild((DataContainerNode<?>) node, depth, newChoiceBuilder);
+
+        return newChoiceBuilder.build();
+    }
+
+    private DataContainerChild<?, ?> processAugmentationNode(final NormalizedNode<?, ?> node, final Integer depth) {
+        final AugmentationNode augmentationNode = (AugmentationNode) node;
+        DataContainerNodeBuilder<AugmentationIdentifier, ? extends DataContainerChild<?, ?>> newAugmentationBuilder = Builders
+                .augmentationBuilder().withNodeIdentifier(augmentationNode.getIdentifier());
+
+        processDataContainerChild((DataContainerNode<?>) node, depth, newAugmentationBuilder);
+
+        return newAugmentationBuilder.build();
+    }
+
+    private void processDataContainerChild(
+            final DataContainerNode<?> node,
+            final Integer depth,
+            final DataContainerNodeBuilder<? extends YangInstanceIdentifier.PathArgument, ? extends DataContainerNode<?>> newBuilder) {
+
+        for (DataContainerChild<? extends PathArgument, ?> nodeValue : node.getValue()) {
+            newBuilder.withChild(pruneDataAtDepth(nodeValue, depth - 1));
+        }
+
+    }
+
+    private DataContainerChild<?, ?> processUnkeyedListNode(final NormalizedNode<?, ?> node, final Integer depth) {
+        CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> newUnkeyedListBuilder = Builders
+                .unkeyedListBuilder();
+        if (depth > 1) {
+            for (UnkeyedListEntryNode oldUnkeyedListEntry : ((UnkeyedListNode) node).getValue()) {
+                DataContainerNodeAttrBuilder<NodeIdentifier, UnkeyedListEntryNode> newUnkeyedListEntry = Builders
+                        .unkeyedListEntryBuilder().withNodeIdentifier(oldUnkeyedListEntry.getIdentifier());
+                for (DataContainerChild<? extends PathArgument, ?> oldUnkeyedListEntryValue : oldUnkeyedListEntry
+                        .getValue()) {
+                    newUnkeyedListEntry.withChild(pruneDataAtDepth(oldUnkeyedListEntryValue, depth - 1));
+                }
+                newUnkeyedListBuilder.addChild(newUnkeyedListEntry.build());
+            }
+        }
+        return newUnkeyedListBuilder.build();
+    }
+
+    private DataContainerChild<?, ?> processOrderedMapNode(final NormalizedNode<?, ?> node, final Integer depth) {
+        CollectionNodeBuilder<MapEntryNode, OrderedMapNode> newOrderedMapNodeBuilder = Builders.orderedMapBuilder();
+        processMapEntries(node, depth, newOrderedMapNodeBuilder);
+        return newOrderedMapNodeBuilder.build();
+    }
+
+    private DataContainerChild<?, ?> processMapNode(final NormalizedNode<?, ?> node, final Integer depth) {
+        CollectionNodeBuilder<MapEntryNode, MapNode> newMapNodeBuilder = Builders.mapBuilder();
+        processMapEntries(node, depth, newMapNodeBuilder);
+        return newMapNodeBuilder.build();
+    }
+
+    private void processMapEntries(final NormalizedNode<?, ?> node, final Integer depth,
+            CollectionNodeBuilder<MapEntryNode, ? extends MapNode> newOrderedMapNodeBuilder) {
+        if (depth > 1) {
+            for (MapEntryNode oldMapEntryNode : ((MapNode) node).getValue()) {
+                DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> newMapEntryNodeBuilder = Builders
+                        .mapEntryBuilder().withNodeIdentifier(oldMapEntryNode.getIdentifier());
+                for (DataContainerChild<? extends PathArgument, ?> mapEntryNodeValue : oldMapEntryNode.getValue()) {
+                    newMapEntryNodeBuilder.withChild(pruneDataAtDepth(mapEntryNodeValue, depth - 1));
+                }
+                newOrderedMapNodeBuilder.withChild(newMapEntryNodeBuilder.build());
+            }
+        }
+    }
+
+
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/NormalizedNodeContext.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/NormalizedNodeContext.java
new file mode 100644 (file)
index 0000000..e698693
--- /dev/null
@@ -0,0 +1,22 @@
+package org.opendaylight.controller.sal.restconf.impl;
+
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public class NormalizedNodeContext {
+
+    private final InstanceIdentifierContext context;
+    private final NormalizedNode<?,?> data;
+
+    public NormalizedNodeContext(InstanceIdentifierContext context, NormalizedNode<?, ?> data) {
+        this.context = context;
+        this.data = data;
+    }
+
+    public InstanceIdentifierContext getInstanceIdentifierContext() {
+        return context;
+    }
+
+    public NormalizedNode<?, ?> getData() {
+        return data;
+    }
+}
index b94f6a6166c47f3b1308f7dc4696341fe5ec202b..adad26e141d2315af5287c9ff2b49a02f16f68ac 100644 (file)
@@ -15,7 +15,6 @@ 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,7 +31,6 @@ 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;
@@ -205,7 +203,7 @@ public class RestconfImpl implements RestconfService {
         Set<Module> modules = null;
         DOMMountPoint mountPoint = null;
         if (identifier.contains(ControllerContext.MOUNT)) {
-            InstanceIdWithSchemaNode mountPointIdentifier = this.controllerContext.toMountPointIdentifier(identifier);
+            InstanceIdentifierContext mountPointIdentifier = this.controllerContext.toMountPointIdentifier(identifier);
             mountPoint = mountPointIdentifier.getMountPoint();
             modules = this.controllerContext.getAllModules(mountPoint);
         } else {
@@ -236,7 +234,7 @@ public class RestconfImpl implements RestconfService {
         Module module = null;
         DOMMountPoint mountPoint = null;
         if (identifier.contains(ControllerContext.MOUNT)) {
-            InstanceIdWithSchemaNode mountPointIdentifier = this.controllerContext.toMountPointIdentifier(identifier);
+            InstanceIdentifierContext mountPointIdentifier = this.controllerContext.toMountPointIdentifier(identifier);
             mountPoint = mountPointIdentifier.getMountPoint();
             module = this.controllerContext.findModuleByNameAndRevision(mountPoint, moduleNameAndRevision);
         } else {
@@ -267,7 +265,7 @@ public class RestconfImpl implements RestconfService {
         Set<Module> modules = null;
         DOMMountPoint mountPoint = null;
         if (identifier.contains(ControllerContext.MOUNT)) {
-            InstanceIdWithSchemaNode mountPointIdentifier = this.controllerContext.toMountPointIdentifier(identifier);
+            InstanceIdentifierContext mountPointIdentifier = this.controllerContext.toMountPointIdentifier(identifier);
             mountPoint = mountPointIdentifier.getMountPoint();
             modules = this.controllerContext.getAllModules(mountPoint);
         } else {
@@ -518,7 +516,7 @@ public class RestconfImpl implements RestconfService {
         DOMMountPoint mountPoint = null;
         if (identifier.contains(ControllerContext.MOUNT)) {
             // mounted RPC call - look up mount instance.
-            InstanceIdWithSchemaNode mountPointId = controllerContext.toMountPointIdentifier(identifier);
+            InstanceIdentifierContext mountPointId = controllerContext.toMountPointIdentifier(identifier);
             mountPoint = mountPointId.getMountPoint();
 
             int startOfRemoteRpcName = identifier.lastIndexOf(ControllerContext.MOUNT)
@@ -615,8 +613,8 @@ public class RestconfImpl implements RestconfService {
     }
 
     @Override
-    public StructuredData readConfigurationData(final String identifier, final UriInfo uriInfo) {
-        final InstanceIdWithSchemaNode iiWithData = controllerContext.toInstanceIdentifier(identifier);
+    public NormalizedNodeContext readConfigurationData(final String identifier, final UriInfo uriInfo) {
+        final InstanceIdentifierContext iiWithData = controllerContext.toInstanceIdentifier(identifier);
         DOMMountPoint mountPoint = iiWithData.getMountPoint();
         NormalizedNode<?, ?> data = null;
         YangInstanceIdentifier normalizedII;
@@ -628,12 +626,7 @@ public class RestconfImpl implements RestconfService {
             normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
             data = broker.readConfigurationData(normalizedII);
         }
-
-        final CompositeNode compositeNode = datastoreNormalizedNodeToCompositeNode(data, iiWithData.getSchemaNode());
-        final CompositeNode prunedCompositeNode = pruneDataAtDepth(compositeNode, parseDepthParameter(uriInfo));
-
-        final boolean prettyPrintMode = parsePrettyPrintParameter(uriInfo);
-        return new StructuredData(prunedCompositeNode, iiWithData.getSchemaNode(), mountPoint, prettyPrintMode);
+        return new NormalizedNodeContext(iiWithData, data);
     }
 
     @SuppressWarnings("unchecked")
@@ -679,8 +672,8 @@ public class RestconfImpl implements RestconfService {
     }
 
     @Override
-    public StructuredData readOperationalData(final String identifier, final UriInfo info) {
-        final InstanceIdWithSchemaNode iiWithData = controllerContext.toInstanceIdentifier(identifier);
+    public NormalizedNodeContext readOperationalData(final String identifier, final UriInfo info) {
+        final InstanceIdentifierContext iiWithData = controllerContext.toInstanceIdentifier(identifier);
         DOMMountPoint mountPoint = iiWithData.getMountPoint();
         NormalizedNode<?, ?> data = null;
         YangInstanceIdentifier normalizedII;
@@ -693,11 +686,7 @@ public class RestconfImpl implements RestconfService {
             data = broker.readOperationalData(normalizedII);
         }
 
-        final CompositeNode compositeNode = datastoreNormalizedNodeToCompositeNode(data, iiWithData.getSchemaNode());
-        final CompositeNode prunedCompositeNode = pruneDataAtDepth(compositeNode, parseDepthParameter(info));
-
-        final boolean prettyPrintMode = parsePrettyPrintParameter(info);
-        return new StructuredData(prunedCompositeNode, iiWithData.getSchemaNode(), mountPoint, prettyPrintMode);
+        return new NormalizedNodeContext(iiWithData, data);
     }
 
     private boolean parsePrettyPrintParameter(final UriInfo info) {
@@ -707,7 +696,7 @@ public class RestconfImpl implements RestconfService {
 
     @Override
     public Response updateConfigurationData(final String identifier, final Node<?> payload) {
-        final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
+        final InstanceIdentifierContext iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
 
         validateInput(iiWithData.getSchemaNode(), payload);
 
@@ -774,7 +763,7 @@ public class RestconfImpl implements RestconfService {
      *             if key values or key count in payload and URI isn't equal
      *
      */
-    private void validateListKeysEqualityInPayloadAndUri(final InstanceIdWithSchemaNode iiWithData,
+    private void validateListKeysEqualityInPayloadAndUri(final InstanceIdentifierContext iiWithData,
             final CompositeNode payload) {
         if (iiWithData.getSchemaNode() instanceof ListSchemaNode) {
             final List<QName> keyDefinitions = ((ListSchemaNode) iiWithData.getSchemaNode()).getKeyDefinition();
@@ -825,7 +814,7 @@ public class RestconfImpl implements RestconfService {
                     ErrorType.PROTOCOL, ErrorTag.UNKNOWN_NAMESPACE);
         }
 
-        InstanceIdWithSchemaNode iiWithData = null;
+        InstanceIdentifierContext iiWithData = null;
         CompositeNode value = null;
         if (this.representsMountPointRootData(payload)) {
             // payload represents mount point data and URI represents path to the mount point
@@ -841,7 +830,7 @@ public class RestconfImpl implements RestconfService {
 
             value = this.normalizeNode(payload, iiWithData.getSchemaNode(), iiWithData.getMountPoint());
         } else {
-            final InstanceIdWithSchemaNode incompleteInstIdWithData = this.controllerContext
+            final InstanceIdentifierContext incompleteInstIdWithData = this.controllerContext
                     .toInstanceIdentifier(identifier);
             final DataNodeContainer parentSchema = (DataNodeContainer) incompleteInstIdWithData.getSchemaNode();
             DOMMountPoint mountPoint = incompleteInstIdWithData.getMountPoint();
@@ -856,7 +845,7 @@ public class RestconfImpl implements RestconfService {
                     parentSchema, payloadName, module.getNamespace());
             value = this.normalizeNode(payload, schemaNode, mountPoint);
 
-            iiWithData = addLastIdentifierFromData(incompleteInstIdWithData, value, schemaNode);
+            iiWithData = addLastIdentifierFromData(incompleteInstIdWithData, value, schemaNode,incompleteInstIdWithData.getSchemaContext());
         }
 
         final NormalizedNode<?, ?> datastoreNormalizedData = compositeNodeToDatastoreNormalizedNode(value,
@@ -906,7 +895,7 @@ public class RestconfImpl implements RestconfService {
         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);
+        final InstanceIdentifierContext iiWithData = this.addLastIdentifierFromData(null, value, schemaNode,ControllerContext.getInstance().getGlobalSchema());
         final NormalizedNode<?, ?> datastoreNormalizedData = compositeNodeToDatastoreNormalizedNode(value, schemaNode);
         DOMMountPoint mountPoint = iiWithData.getMountPoint();
         YangInstanceIdentifier normalizedII;
@@ -932,7 +921,7 @@ public class RestconfImpl implements RestconfService {
 
     @Override
     public Response deleteConfigurationData(final String identifier) {
-        final InstanceIdWithSchemaNode iiWithData = controllerContext.toInstanceIdentifier(identifier);
+        final InstanceIdentifierContext iiWithData = controllerContext.toInstanceIdentifier(identifier);
         DOMMountPoint mountPoint = iiWithData.getMountPoint();
         YangInstanceIdentifier normalizedII;
 
@@ -1098,8 +1087,8 @@ public class RestconfImpl implements RestconfService {
         return module;
     }
 
-    private InstanceIdWithSchemaNode addLastIdentifierFromData(final InstanceIdWithSchemaNode identifierWithSchemaNode,
-            final CompositeNode data, final DataSchemaNode schemaOfData) {
+    private InstanceIdentifierContext addLastIdentifierFromData(final InstanceIdentifierContext identifierWithSchemaNode,
+            final CompositeNode data, final DataSchemaNode schemaOfData, SchemaContext schemaContext) {
         YangInstanceIdentifier instanceIdentifier = null;
         if (identifierWithSchemaNode != null) {
             instanceIdentifier = identifierWithSchemaNode.getInstanceIdentifier();
@@ -1122,11 +1111,12 @@ public class RestconfImpl implements RestconfService {
 
         YangInstanceIdentifier instance = iiBuilder.toInstance();
         DOMMountPoint mountPoint = null;
+        SchemaContext schemaCtx = null;
         if (identifierWithSchemaNode != null) {
             mountPoint = identifierWithSchemaNode.getMountPoint();
         }
 
-        return new InstanceIdWithSchemaNode(instance, schemaOfData, mountPoint);
+        return new InstanceIdentifierContext(instance, schemaOfData, mountPoint,schemaContext);
     }
 
     private HashMap<QName, Object> resolveKeysFromData(final ListSchemaNode listNode, final CompositeNode dataNode) {
@@ -1514,16 +1504,16 @@ public class RestconfImpl implements RestconfService {
                 "It wasn't possible to translate specified data to datastore readable form."));
     }
 
-    private InstanceIdWithSchemaNode normalizeInstanceIdentifierWithSchemaNode(
-            final InstanceIdWithSchemaNode iiWithSchemaNode) {
+    private InstanceIdentifierContext normalizeInstanceIdentifierWithSchemaNode(
+            final InstanceIdentifierContext iiWithSchemaNode) {
         return normalizeInstanceIdentifierWithSchemaNode(iiWithSchemaNode, false);
     }
 
-    private InstanceIdWithSchemaNode normalizeInstanceIdentifierWithSchemaNode(
-            final InstanceIdWithSchemaNode iiWithSchemaNode, final boolean unwrapLastListNode) {
-        return new InstanceIdWithSchemaNode(instanceIdentifierToReadableFormForNormalizeNode(
+    private InstanceIdentifierContext normalizeInstanceIdentifierWithSchemaNode(
+            final InstanceIdentifierContext iiWithSchemaNode, final boolean unwrapLastListNode) {
+        return new InstanceIdentifierContext(instanceIdentifierToReadableFormForNormalizeNode(
                 iiWithSchemaNode.getInstanceIdentifier(), unwrapLastListNode), iiWithSchemaNode.getSchemaNode(),
-                iiWithSchemaNode.getMountPoint());
+                iiWithSchemaNode.getMountPoint(),iiWithSchemaNode.getSchemaContext());
     }
 
     private YangInstanceIdentifier instanceIdentifierToReadableFormForNormalizeNode(
index f39eae45424941355b2d9a7291d62eea744048a4..60c3378471f6b0989967c707462c132d7418218f 100644 (file)
             <param-name>javax.ws.rs.Application</param-name>
             <param-value>org.opendaylight.controller.sal.rest.impl.RestconfApplication</param-value>
         </init-param>
+        <!-- AAA Auth Filter -->
+        <init-param>
+            <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
+            <param-value> org.opendaylight.aaa.sts.TokenAuthFilter</param-value>
+        </init-param>
         <load-on-startup>1</load-on-startup>
     </servlet>
 
index 2f045ce381ca0572cbeff4ad43147834fb59d2cf..559a6b9e8e4a8a88aed3f4c4c3b9a34d5ea377ae 100644 (file)
@@ -40,7 +40,7 @@ import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
-import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
+import org.opendaylight.controller.sal.restconf.impl.InstanceIdentifierContext;
 import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
@@ -324,7 +324,7 @@ public class InvokeRpcMethodTest {
         when(mockMountPoint.getService(eq(RpcProvisionRegistry.class))).thenReturn(Optional.of(mockedRpcProvisionRegistry));
         when(mockMountPoint.getSchemaContext()).thenReturn(TestUtils.loadSchemaContext("/invoke-rpc"));
 
-        InstanceIdWithSchemaNode mockedInstanceId = mock(InstanceIdWithSchemaNode.class);
+        InstanceIdentifierContext mockedInstanceId = mock(InstanceIdentifierContext.class);
         when(mockedInstanceId.getMountPoint()).thenReturn(mockMountPoint);
 
         ControllerContext mockedContext = mock(ControllerContext.class);
index bab06e92451985b5a0d95032e99174adb91ba4b0..856d8c006b6c40349d2a1fd646cc70db6bd5fd62 100644 (file)
@@ -17,7 +17,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
-import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
+import org.opendaylight.controller.sal.restconf.impl.InstanceIdentifierContext;
 import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
@@ -36,7 +36,7 @@ public class RestGetAugmentedElementWhenEqualNamesTest {
 
     @Test
     public void augmentedNodesInUri() {
-        InstanceIdWithSchemaNode iiWithData = controllerContext.toInstanceIdentifier("main:cont/augment-main-a:cont1");
+        InstanceIdentifierContext iiWithData = controllerContext.toInstanceIdentifier("main:cont/augment-main-a:cont1");
         assertEquals("ns:augment:main:a", iiWithData.getSchemaNode().getQName().getNamespace().toString());
         iiWithData = controllerContext.toInstanceIdentifier("main:cont/augment-main-b:cont1");
         assertEquals("ns:augment:main:b", iiWithData.getSchemaNode().getQName().getNamespace().toString());
index 539248a147cd4eea16dca9f4725cf26e9b185496..06cfd84b05048513249462de9245871da3905c5f 100644 (file)
@@ -44,12 +44,14 @@ import javax.ws.rs.core.UriInfo;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
 import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
 import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
+import org.opendaylight.controller.sal.rest.impl.RestconfApplication;
 import org.opendaylight.controller.sal.rest.impl.RestconfDocumentedExceptionMapper;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
@@ -130,6 +132,7 @@ public class RestGetOperationTest extends JerseyTest {
                 StructuredDataToJsonProvider.INSTANCE, XmlToCompositeNodeProvider.INSTANCE,
                 JsonToCompositeNodeProvider.INSTANCE);
         resourceConfig.registerClasses(RestconfDocumentedExceptionMapper.class);
+        resourceConfig.registerClasses(new RestconfApplication().getClasses());
         return resourceConfig;
     }
 
@@ -717,6 +720,7 @@ public class RestGetOperationTest extends JerseyTest {
     }
 
     @Test
+    @Ignore
     public void getDataWithUriDepthParameterTest() throws UnsupportedEncodingException {
 
         ControllerContext.getInstance().setGlobalSchema(schemaContextModules);
@@ -903,6 +907,7 @@ public class RestGetOperationTest extends JerseyTest {
      * Tests behavior when invalid value of depth URI parameter
      */
     @Test
+    @Ignore
     public void getDataWithInvalidDepthParameterTest() {
 
         ControllerContext.getInstance().setGlobalSchema(schemaContextModules);
@@ -930,7 +935,7 @@ public class RestGetOperationTest extends JerseyTest {
         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());
+            NormalizedNode value = (Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(qNameDepth1Cont)).build());
             when(brokerFacade.readConfigurationData(eq(ii))).thenReturn(value);
             restconfImpl.readConfigurationData("nested-module:depth1-cont", uriInfo);
             fail("Expected RestconfDocumentedException");
index 4e9c96ac3e8acef126077d7b932e737caae1e4f3..3a16b18efcf26e8704a06900fb16a36d32cb5a00 100644 (file)
@@ -53,6 +53,7 @@ import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.opendaylight.controller.sal.rest.api.Draft02;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
@@ -60,11 +61,11 @@ import org.opendaylight.controller.sal.rest.impl.RestconfDocumentedExceptionMapp
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.NormalizedNodeContext;
 import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
-import org.opendaylight.controller.sal.restconf.impl.StructuredData;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -679,13 +680,14 @@ public class RestconfDocumentedExceptionMapperTest extends JerseyTest {
     }
 
     @Test
+    @Ignore
     public void testToResponseWithStatusOnly() throws Exception {
 
         // The StructuredDataToJsonProvider should throw a
         // RestconfDocumentedException with no data
 
         when(mockRestConf.readOperationalData(any(String.class), any(UriInfo.class))).thenReturn(
-                new StructuredData(null, null, null));
+                new NormalizedNodeContext(null, null));
 
         Response resp = target("/operational/foo").request(MediaType.APPLICATION_JSON).get();
 
index c2b153f02bd27b6729dbba2a89a201a306763a99..15d73e3e7a301ca5a70879a851941eab0e4b35b3 100644 (file)
@@ -402,7 +402,7 @@ public final class TestUtils {
         return interfaceBuilder.toInstance();
     }
 
-    static NormalizedNode prepareNormalizedNodeWithIetfInterfacesInterfacesData() throws ParseException {
+    static NormalizedNode<?,?> prepareNormalizedNodeWithIetfInterfacesInterfacesData() throws ParseException {
         String ietfInterfacesDate = "2013-07-04";
         String namespace = "urn:ietf:params:xml:ns:yang:ietf-interfaces";
         DataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> mapEntryNode = ImmutableMapEntryNodeBuilder.create();
index ed871bb52727895c5cdf69dd80e0caa2433cacef..4900e6a66f1ab9d9d3324c85e6ca5c98f103e5ba 100644 (file)
@@ -26,7 +26,7 @@ import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
-import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
+import org.opendaylight.controller.sal.restconf.impl.InstanceIdentifierContext;
 import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -51,7 +51,7 @@ public class URITest {
 
     @Test
     public void testToInstanceIdentifierList() throws FileNotFoundException {
-        InstanceIdWithSchemaNode instanceIdentifier = controllerContext
+        InstanceIdentifierContext instanceIdentifier = controllerContext
                 .toInstanceIdentifier("simple-nodes:userWithoutClass/foo");
         assertEquals(instanceIdentifier.getSchemaNode().getQName().getLocalName(), "userWithoutClass");
 
@@ -80,7 +80,7 @@ public class URITest {
 
     @Test
     public void testToInstanceIdentifierContainer() throws FileNotFoundException {
-        InstanceIdWithSchemaNode instanceIdentifier = controllerContext.toInstanceIdentifier("simple-nodes:users");
+        InstanceIdentifierContext instanceIdentifier = controllerContext.toInstanceIdentifier("simple-nodes:users");
         assertEquals(instanceIdentifier.getSchemaNode().getQName().getLocalName(), "users");
         assertTrue(instanceIdentifier.getSchemaNode() instanceof ContainerSchemaNode);
         assertEquals(2, ((ContainerSchemaNode) instanceIdentifier.getSchemaNode()).getChildNodes().size());
@@ -88,7 +88,7 @@ public class URITest {
 
     @Test
     public void testToInstanceIdentifierChoice() throws FileNotFoundException {
-        InstanceIdWithSchemaNode instanceIdentifier = controllerContext
+        InstanceIdentifierContext instanceIdentifier = controllerContext
                 .toInstanceIdentifier("simple-nodes:food/nonalcoholic");
         assertEquals(instanceIdentifier.getSchemaNode().getQName().getLocalName(), "nonalcoholic");
     }
@@ -120,7 +120,7 @@ public class URITest {
     @Test
     public void testMountPointWithExternModul() throws FileNotFoundException {
         initMountService(true);
-        InstanceIdWithSchemaNode instanceIdentifier = controllerContext
+        InstanceIdentifierContext instanceIdentifier = controllerContext
                 .toInstanceIdentifier("simple-nodes:users/yang-ext:mount/test-interface2:class/student/name");
         assertEquals(
                 "[(urn:ietf:params:xml:ns:yang:test-interface2?revision=2014-08-01)class, (urn:ietf:params:xml:ns:yang:test-interface2?revision=2014-08-01)student[{(urn:ietf:params:xml:ns:yang:test-interface2?revision=2014-08-01)name=name}]]",
@@ -130,7 +130,7 @@ public class URITest {
     @Test
     public void testMountPointWithoutExternModul() throws FileNotFoundException {
         initMountService(true);
-        InstanceIdWithSchemaNode instanceIdentifier = controllerContext
+        InstanceIdentifierContext instanceIdentifier = controllerContext
                 .toInstanceIdentifier("simple-nodes:users/yang-ext:mount/");
         assertTrue(Iterables.isEmpty(instanceIdentifier.getInstanceIdentifier().getPathArguments()));
     }
@@ -140,7 +140,7 @@ public class URITest {
         exception.expect(RestconfDocumentedException.class);
 
         controllerContext.setMountService(null);
-        InstanceIdWithSchemaNode instanceIdentifier = controllerContext
+        InstanceIdentifierContext instanceIdentifier = controllerContext
                 .toInstanceIdentifier("simple-nodes:users/yang-ext:mount/test-interface2:class/student/name");
     }
 
@@ -149,7 +149,7 @@ public class URITest {
         initMountService(false);
         exception.expect(RestconfDocumentedException.class);
 
-        InstanceIdWithSchemaNode instanceIdentifier = controllerContext
+        InstanceIdentifierContext instanceIdentifier = controllerContext
                 .toInstanceIdentifier("simple-nodes:users/yang-ext:mount/test-interface2:class");
     }
 
index 2a778180d4448dd33ce7cabb17f911e77151df9f..c470b3237ea7fe2dd69f37254cae4b38439c8861 100644 (file)
@@ -2,7 +2,9 @@
 <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
     version="3.0">
-
+    <welcome-file-list>
+        <welcome-file>index.html</welcome-file>
+    </welcome-file-list>
     <servlet>
         <servlet-name>JAXRSApiDoc</servlet-name>
         <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
index 05a76a4cb7ca0551d0bb55322b4603f78eb7fd4b..f12616bc4b910d8127fc7269ea8bd5bc6b863dd5 100644 (file)
@@ -32,7 +32,7 @@
        var loadMount = function(mountIndex, mountPath) {\r
                $("#message").empty();\r
                $("#message").append( "<p>Loading...</p>" );\r
-               loadSwagger("http://localhost:8080/apidoc/apis/mounts/" + mountIndex,\r
+               loadSwagger("/apidoc/apis/mounts/" + mountIndex,\r
                                "swagger-ui-container");\r
                $("#message").empty();\r
                $("#message").append( "<h2><b>Showing mount points for " + mountPath + "</b></h2>");\r
@@ -48,7 +48,7 @@
        //loads the root swagger documenation (which comes from RestConf)\r
        var loadRootSwagger = function() {\r
                $("#message").empty();\r
-               loadSwagger("http://localhost:8080/apidoc/apis", "swagger-ui-container");\r
+               loadSwagger("/apidoc/apis", "swagger-ui-container");\r
        }\r
 \r
        //main method to initialize the mount list / swagger docs / tabs on page load\r
index 4d6b9ebd6f8317412943cce1a6750128b43668ac..89dcab2c3da1dfc45857ffe89a76c9e74c56a450 100644 (file)
       <groupId>org.osgi</groupId>
       <artifactId>org.osgi.core</artifactId>
     </dependency>
+
+    <!-- dependencies to use AbstractDataBrokerTest -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-broker-impl</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-broker-impl</artifactId>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+        <artifactId>junit</artifactId>
+        <groupId>junit</groupId>
+        <scope>test</scope>
+    </dependency>
+    <!-- used to mock up classes -->
+     <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <scope>test</scope>
+    </dependency>
+
   </dependencies>
 
   <build>
diff --git a/opendaylight/md-sal/samples/toaster-provider/src/test/java/org/opendaylight/controller/sample/toaster/provider/OpenDaylightToasterTest.java b/opendaylight/md-sal/samples/toaster-provider/src/test/java/org/opendaylight/controller/sample/toaster/provider/OpenDaylightToasterTest.java
new file mode 100644 (file)
index 0000000..516f214
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+* 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.sample.toaster.provider;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import java.util.concurrent.Future;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.DisplayString;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInput;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInputBuilder;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.Toaster;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.WheatBread;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import com.google.common.base.Optional;
+
+public class OpenDaylightToasterTest extends AbstractDataBrokerTest{
+
+    private static InstanceIdentifier<Toaster> TOASTER_IID =
+                        InstanceIdentifier.builder( Toaster.class ).build();
+    OpendaylightToaster toaster;
+
+    @Override
+    protected void setupWithDataBroker(DataBroker dataBroker) {
+        toaster = new OpendaylightToaster();
+        toaster.setDataProvider( dataBroker );
+
+        /**
+         * Doesn't look like we have support for the NotificationProviderService yet, so mock it
+         * for now.
+         */
+        NotificationProviderService mockNotification = mock( NotificationProviderService.class );
+        toaster.setNotificationProvider( mockNotification );
+    }
+
+    @Test
+    public void testToasterInitOnStartUp() throws Exception {
+        DataBroker broker = getDataBroker();
+
+        ReadOnlyTransaction rTx = broker.newReadOnlyTransaction();
+        Optional<Toaster> optional = rTx.read( LogicalDatastoreType.OPERATIONAL, TOASTER_IID ).get();
+        assertNotNull( optional );
+        assertTrue( "Operational toaster not present", optional.isPresent() );
+
+        Toaster toaster = optional.get();
+
+        assertEquals( Toaster.ToasterStatus.Up, toaster.getToasterStatus() );
+        assertEquals( new DisplayString("Opendaylight"),
+                      toaster.getToasterManufacturer() );
+        assertEquals( new DisplayString("Model 1 - Binding Aware"),
+                      toaster.getToasterModelNumber() );
+
+        Optional<Toaster> configToaster =
+                            rTx.read( LogicalDatastoreType.CONFIGURATION, TOASTER_IID ).get();
+        assertFalse( "Didn't expect config data for toaster.",
+                     configToaster.isPresent() );
+    }
+
+    @Test
+    @Ignore //ignored because it is not an e test right now. Illustrative purposes only.
+    public void testSomething() throws Exception{
+        MakeToastInput toastInput = new MakeToastInputBuilder()
+                                        .setToasterDoneness( 1L )
+                                        .setToasterToastType( WheatBread.class )
+                                        .build();
+
+        //NOTE: In a real test we would want to override the Thread.sleep() to prevent our junit test
+        //for sleeping for a second...
+        Future<RpcResult<Void>> makeToast = toaster.makeToast( toastInput );
+
+        RpcResult<Void> rpcResult = makeToast.get();
+
+        assertNotNull( rpcResult );
+        assertTrue( rpcResult.isSuccessful() );
+         //etc
+    }
+
+}
index e23ad0acdbe43a2603f458dd3a17b467116acd1b..838aeb7dc36af37ae0916fd1e60f708c8be1861d 100644 (file)
@@ -97,14 +97,15 @@ abstract class AbstractStatsTracker<I, K> {
     }
     protected abstract void cleanupSingleStat(DataModificationTransaction trans, K item);
     protected abstract K updateSingleStat(DataModificationTransaction trans, I item);
+    protected abstract K createInvariantKey(K item);
     public abstract void request();
 
     public final synchronized void updateStats(List<I> list) {
 
         final DataModificationTransaction trans = startTransaction();
-
         for (final I item : list) {
-            trackedItems.put(updateSingleStat(trans, item), requestCounter);
+            K key = updateSingleStat(trans, item);
+            trackedItems.put(createInvariantKey(key), requestCounter);
         }
 
         trans.commit();
index cd9738c894554a8e609eac1acb4b9fbd9534eac9..f3dac826e8ad609d39e024cbc7e46239934da035 100644 (file)
@@ -12,8 +12,11 @@ import java.net.InetAddress;
 import java.net.UnknownHostException;
 
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.MacAddressFilter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
 import org.slf4j.Logger;
@@ -35,9 +38,6 @@ final class FlowComparator {
         if (statsFlow == null || storedFlow == null) {
             return false;
         }
-        if (statsFlow.getClass() != storedFlow.getClass()) {
-            return false;
-        }
         if (statsFlow.getContainerName()== null) {
             if (storedFlow.getContainerName()!= null) {
                 return false;
@@ -99,14 +99,11 @@ final class FlowComparator {
         }
         if (storedFlow == null && statsFlow != null) return false;
         if (statsFlow == null && storedFlow != null) return false;
-        if (storedFlow.getClass() != statsFlow.getClass()) {
-            return false;
-        }
         if (storedFlow.getEthernetMatch() == null) {
             if (statsFlow.getEthernetMatch() != null) {
                 return false;
             }
-        } else if(!storedFlow.getEthernetMatch().equals(statsFlow.getEthernetMatch())) {
+        } else if(!ethernetMatchEquals(statsFlow.getEthernetMatch(),storedFlow.getEthernetMatch())) {
             return false;
         }
         if (storedFlow.getIcmpv4Match()== null) {
@@ -189,6 +186,67 @@ final class FlowComparator {
         return true;
     }
 
+    /*
+     * Custom EthernetMatch is required because mac address string provided by user in EthernetMatch can be in
+     * any case (upper or lower or mix). Ethernet Match which controller receives from switch is always
+     * an upper case string. Default EthernetMatch equals doesn't use equalsIgnoreCase() and hence it fails.
+     * E.g User provided mac address string in flow match is aa:bb:cc:dd:ee:ff and when controller fetch
+     * statistic data, openflow driver library returns AA:BB:CC:DD:EE:FF and default eqauls fails here.
+     */
+    @VisibleForTesting
+    static boolean ethernetMatchEquals(EthernetMatch statsEthernetMatch, EthernetMatch storedEthernetMatch){
+        boolean verdict = true;
+        Boolean checkNullValues = checkNullValues(statsEthernetMatch, storedEthernetMatch);
+        if (checkNullValues != null) {
+            verdict = checkNullValues;
+        } else {
+            if(verdict){
+                verdict = ethernetMatchFieldsEquals(statsEthernetMatch.getEthernetSource(),storedEthernetMatch.getEthernetSource());
+            }
+            if(verdict){
+                verdict = ethernetMatchFieldsEquals(statsEthernetMatch.getEthernetDestination(),storedEthernetMatch.getEthernetDestination());
+            }
+            if(verdict){
+                if(statsEthernetMatch.getEthernetType() == null){
+                    if(storedEthernetMatch.getEthernetType() != null){
+                        verdict = false;
+                    }
+                }else{
+                    verdict = statsEthernetMatch.getEthernetType().equals(storedEthernetMatch.getEthernetType());
+                }
+            }
+        }
+        return verdict;
+    }
+
+    private static boolean ethernetMatchFieldsEquals(MacAddressFilter statsEthernetMatchFields,
+                                                        MacAddressFilter storedEthernetMatchFields){
+        boolean verdict = true;
+        Boolean checkNullValues = checkNullValues(statsEthernetMatchFields, storedEthernetMatchFields);
+        if (checkNullValues != null) {
+            verdict = checkNullValues;
+        } else {
+            if(verdict){
+                verdict = macAddressEquals(statsEthernetMatchFields.getAddress(),storedEthernetMatchFields.getAddress());
+            }
+            if(verdict){
+                verdict = macAddressEquals(statsEthernetMatchFields.getMask(),storedEthernetMatchFields.getMask());
+            }
+        }
+        return verdict;
+    }
+
+    private static boolean macAddressEquals(MacAddress statsMacAddress, MacAddress storedMacAddress){
+        boolean verdict = true;
+        Boolean checkNullValues = checkNullValues(statsMacAddress, storedMacAddress);
+        if (checkNullValues != null) {
+            verdict = checkNullValues;
+        } else {
+            verdict = statsMacAddress.getValue().equalsIgnoreCase(storedMacAddress.getValue());
+        }
+        return verdict;
+    }
+
     @VisibleForTesting
     static boolean layer3MatchEquals(Layer3Match statsLayer3Match, Layer3Match storedLayer3Match){
         boolean verdict = true;
index b5b39d94d2f5839cf3901807f3435d93d53ba38d..c43c1ebaca211216a5046d65870b56b7ef432513 100644 (file)
@@ -56,4 +56,9 @@ final class FlowStatsEntry {
             return false;
         return true;
     }
+
+    @Override
+    public String toString() {
+        return "FlowStatsEntry [tableId=" + tableId + ", flow=" + flow + "]";
+    }
 }
index e92d0bd6251dbf89af9c98b175aa699d8d697994..d540f115c3ab7c107536a5797b3527e9dc7a36ba 100644 (file)
@@ -301,4 +301,13 @@ final class FlowStatsTracker extends AbstractListeningStatsTracker<FlowAndStatis
         }
         return flowCookieMap;
     }
+
+    @Override
+    protected FlowStatsEntry createInvariantKey(final FlowStatsEntry item) {
+        FlowBuilder newFlow = new FlowBuilder();
+        newFlow.setId(item.getFlow().getId());
+        newFlow.setKey(item.getFlow().getKey());
+        newFlow.fieldsFrom(item.getFlow());
+        return new FlowStatsEntry(item.getTableId(),newFlow.build());
+    }
 }
index a160f6d467ca6731a8c4d485250d6697cec8b97e..2e850580416084c36a1de4c054d21a7860b8d394 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev13
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMapBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatistics;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatisticsBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -70,4 +71,12 @@ final class FlowTableStatsTracker extends AbstractStatsTracker<FlowTableAndStati
             requestHelper(flowTableStatsService.getFlowTablesStatistics(input.build()));
         }
     }
+
+    @Override
+    protected FlowTableAndStatisticsMap createInvariantKey(FlowTableAndStatisticsMap item) {
+        FlowTableAndStatisticsMapBuilder flowTableAndStatisticsMapBuilder = new FlowTableAndStatisticsMapBuilder();
+        flowTableAndStatisticsMapBuilder.setTableId(item.getTableId());
+        flowTableAndStatisticsMapBuilder.setKey(item.getKey());
+        return flowTableAndStatisticsMapBuilder.build();
+    }
 }
index a775b73169dc5581cd3175eebfa078a471d5dbd3..11c6d4c22df5f53cd17d8bc089aa8b7338c8eceb 100644 (file)
@@ -114,4 +114,10 @@ final class GroupDescStatsTracker extends AbstractListeningStatsTracker<GroupDes
 
         super.start(dbs);
     }
+
+    @Override
+    protected GroupDescStats createInvariantKey(GroupDescStats item) {
+        // No invariant data exist in the group description stats.
+        return item;
+    }
 }
index c3c23c9b582cf493c02248087b08f80914b3fd82..f3ba45643c3fd4338b4f8f6bd8951de0d5184757 100644 (file)
@@ -17,6 +17,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatisticsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStatsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
@@ -105,4 +106,12 @@ final class GroupStatsTracker extends AbstractListeningStatsTracker<GroupStats,
 
         super.start(dbs);
     }
+
+    @Override
+    protected GroupStats createInvariantKey(GroupStats item) {
+        GroupStatsBuilder groupStatsBuilder = new GroupStatsBuilder();
+        groupStatsBuilder.setKey(item.getKey());
+        groupStatsBuilder.setGroupId(item.getGroupId());
+        return groupStatsBuilder.build();
+    }
 }
index ea412a09e183db8dcf958c6769a8b0ac37211c5f..88139fc60649541678f63edb46e8f9a250898644 100644 (file)
@@ -109,4 +109,10 @@ final class MeterConfigStatsTracker extends AbstractListeningStatsTracker<MeterC
 
         super.start(dbs);
     }
+
+    @Override
+    protected MeterConfigStats createInvariantKey(MeterConfigStats item) {
+        // No invariant data exist in the meter config stats.
+        return item;
+    }
 }
index be53a38f186eb2407b9ce30ff4a2e20da6379b53..f43ec693cd1d7a283a037f770361f1024ab4ed01 100644 (file)
@@ -20,6 +20,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatisticsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStatsBuilder;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -112,4 +113,12 @@ final class MeterStatsTracker extends AbstractListeningStatsTracker<MeterStats,
 
         super.start(dbs);
     }
+
+    @Override
+    protected MeterStats createInvariantKey(MeterStats item) {
+        MeterStatsBuilder meterStatsBuilder = new MeterStatsBuilder();
+        meterStatsBuilder.setKey(item.getKey());
+        meterStatsBuilder.setMeterId(item.getMeterId());
+        return meterStatsBuilder.build();
+    }
 }
index e4490eaa3cc2ea9ac2683ff36f6d48787ddded99..2e2bf1cd518b94a2b97c81b877b8372f447ef36e 100644 (file)
@@ -17,6 +17,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.G
 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatisticsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -83,4 +84,12 @@ final class NodeConnectorStatsTracker extends AbstractStatsTracker<NodeConnector
             requestHelper(portStatsService.getAllNodeConnectorsStatistics(input.build()));
         }
     }
+
+    @Override
+    protected NodeConnectorStatisticsAndPortNumberMap createInvariantKey(NodeConnectorStatisticsAndPortNumberMap item) {
+        NodeConnectorStatisticsAndPortNumberMapBuilder ncStatsBuilder = new NodeConnectorStatisticsAndPortNumberMapBuilder();
+        ncStatsBuilder.setNodeConnectorId(item.getNodeConnectorId());
+        ncStatsBuilder.setKey(item.getKey());
+        return ncStatsBuilder.build();
+    }
 }
index 03f7808c8f9b119cfb6ed0ba2fe877d340e3ffc0..4a589703beb4303b9686d7887663b8f6d1492486 100644 (file)
@@ -152,4 +152,10 @@ final class QueueStatsTracker extends AbstractListeningStatsTracker<QueueIdAndSt
 
         super.start(dbs);
     }
+
+    @Override
+    protected QueueStatsEntry createInvariantKey(QueueStatsEntry item) {
+        // No invariant data exist in the group description stats.
+        return item;
+    }
 }
index bf523a433bf8423a3badc399b77386296f152ca7..a687b1f28049bf7cc8b6220fb97c5d4540dac9d3 100644 (file)
@@ -11,6 +11,12 @@ package org.opendaylight.controller.md.statistics.manager;
 import org.junit.Assert;
 import org.junit.Test;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
 import org.slf4j.Logger;
@@ -111,5 +117,96 @@ public class StatisticsUpdateCommiterTest {
 
         return ipv4MatchBuilder.build();
     }
+    /**
+     * Test method for {@link org.opendaylight.controller.md.statistics.manager.FlowComparator#ethernetMatchEquals(EthernetMatch, EthernetMatch)
+     */
+    @Test
+    public void testEthernetMatchEquals() {
+        String[][][] ethernetMatchSeeds = new String[][][] {
+                {{"aa:bb:cc:dd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}, {"aa:bb:cc:dd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}},
+                {{"aa:bb:cc:dd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}, {"aa:bb:bc:cd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}},
+                {{"aa:bb:cc:dd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}, {"AA:BB:CC:DD:EE:FF", "ff:ff:ff:ff:ff:ff","0800"}},
+                {{"AA:BB:CC:dd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}, {"aa:bb:cc:dd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}},
+                {{"AA:BB:CC:dd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}, {"aa:bb:cc:dd:ee:ff", "FF:FF:FF:FF:FF:FF","0800"}},
+                {{"AA:BB:CC:dd:ee:ff", "ff:ff:ff:ee:ee:ee","0800"}, {"aa:bb:cc:dd:ee:ff", "FF:FF:FF:FF:FF:FF","0800"}},
+
+                {{"AA:BB:CC:dd:ee:ff", null,"0800"}, {"aa:bb:cc:dd:ee:ff", null,"0800"}},
+                {{"AA:BB:CC:dd:ee:ff", null,"0800"}, {"aa:bb:cc:dd:ee:ff", null,"0806"}},
+                {{"AA:BB:CC:dd:ee:ff", null,"0800"}, {"aa:bb:cc:dd:ee:ff", "FF:FF:FF:FF:FF:FF","0800"}},
+                {{"AA:BB:CC:dd:ee:ff", null,"0800"}, {null, "FF:FF:FF:FF:FF:FF","0800"}},
+
+                {{"AA:BB:CC:dd:ee:ff", "ff:ff:ff:ff:ff:ff",null}, {null, "FF:FF:FF:FF:FF:FF","0800"}},
+                {{"AA:BB:CC:dd:ee:ff", "ff:ff:ff:ff:ff:ff",null}, {"aa:bb:cc:dd:ee:ff", "FF:FF:FF:FF:FF:FF",null}},
+                {{"AA:BB:CC:dd:ee:ff", "ff:ff:ff:ff:ff:ff",null}, {null, "FF:FF:FF:FF:FF:FF",null}},
+
+                {{null, null,null}, {null, null,"0800"}},
+                {{null, null,null}, {null, null,null}},
+        };
+
+        boolean[] matches = new boolean[] {
+                true,
+                false,
+                true,
+                true,
+                true,
+                false,
+
+                true,
+                false,
+                false,
+                false,
 
+                false,
+                true,
+                false,
+
+                false,
+                true
+        };
+
+        for (int i = 0; i < matches.length; i++) {
+            checkComparisonOfEthernetMatch(
+                    ethernetMatchSeeds[i][0][0], ethernetMatchSeeds[i][0][1],ethernetMatchSeeds[i][0][2],
+                    ethernetMatchSeeds[i][1][0], ethernetMatchSeeds[i][1][1],ethernetMatchSeeds[i][1][2],
+                    matches[i]);
+        }
+    }
+
+    /*
+     * @param ethernetMatch1
+     * @param ethernetMatch2
+     */
+    private static void checkComparisonOfEthernetMatch(String macAddress1, String macAddressMask1,String etherType1,
+            String macAddress2, String macAddressMask2,String etherType2, boolean expectedResult) {
+        EthernetMatch ethernetMatch1 = prepareEthernetMatch(macAddress1, macAddressMask1,etherType1);
+        EthernetMatch ethernetMatch2 = prepareEthernetMatch(macAddress2, macAddressMask2,etherType2);
+        boolean comparisonResult;
+        try {
+            comparisonResult = FlowComparator.ethernetMatchEquals(ethernetMatch1, ethernetMatch2);
+            Assert.assertEquals("failed to compare: "+ethernetMatch1+" vs. "+ethernetMatch2,
+                    expectedResult, comparisonResult);
+        } catch (Exception e) {
+            LOG.error("failed to compare: {} vs. {}", ethernetMatch1, ethernetMatch2, e);
+            Assert.fail(e.getMessage());
+        }
+    }
+
+    private static EthernetMatch prepareEthernetMatch(String macAddress, String macAddressMask, String etherType) {
+        EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder();
+        EthernetSourceBuilder ethernetSourceBuilder =  new EthernetSourceBuilder();
+        if (macAddress != null) {
+            ethernetSourceBuilder.setAddress(new MacAddress(macAddress));
+        }
+        if (macAddressMask != null) {
+            ethernetSourceBuilder.setMask(new MacAddress(macAddressMask));
+        }
+        if(etherType != null){
+            EthernetTypeBuilder ethernetType = new EthernetTypeBuilder();
+            ethernetType.setType(new EtherType(Long.parseLong(etherType,16)));
+            ethernetMatchBuilder.setEthernetType(ethernetType.build());
+        }
+        ethernetMatchBuilder.setEthernetSource(ethernetSourceBuilder.build());
+
+        return ethernetMatchBuilder.build();
+    }
 }
index 451cad48169ea81869ef11047895010715f0e30f..c1996f4691632637abc9fc7dffacce0bcb12f2ad 100644 (file)
@@ -15,11 +15,9 @@ import static org.opendaylight.md.controller.topology.manager.FlowCapableNodeMap
 import static org.opendaylight.md.controller.topology.manager.FlowCapableNodeMapping.toTopologyNode;
 import static org.opendaylight.md.controller.topology.manager.FlowCapableNodeMapping.toTopologyNodeId;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
+import java.util.Collections;
+import java.util.List;
+
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
@@ -50,6 +48,12 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
 class FlowCapableTopologyExporter implements FlowTopologyDiscoveryListener, OpendaylightInventoryListener {
 
     private final Logger LOG = LoggerFactory.getLogger(FlowCapableTopologyExporter.class);
@@ -147,7 +151,7 @@ class FlowCapableTopologyExporter implements FlowTopologyDiscoveryListener, Open
             public void applyOperation(final ReadWriteTransaction transaction) {
                 final Link link = toTopologyLink(notification);
                 final InstanceIdentifier<Link> path = linkPath(link);
-                transaction.put(LogicalDatastoreType.OPERATIONAL, path, link);
+                transaction.merge(LogicalDatastoreType.OPERATIONAL, path, link, true);
             }
         });
     }
@@ -193,8 +197,9 @@ class FlowCapableTopologyExporter implements FlowTopologyDiscoveryListener, Open
                     @Override
                     public void onSuccess(Optional<Topology> topologyOptional) {
                         if (topologyOptional.isPresent()) {
-                            Topology topologyData = topologyOptional.get();
-                            for (Link link : topologyData.getLink()) {
+                            List<Link> linkList = topologyOptional.get().getLink() != null
+                                    ? topologyOptional.get().getLink() : Collections.<Link> emptyList();
+                            for (Link link : linkList) {
                                 if (id.equals(link.getSource().getSourceNode()) || id.equals(link.getDestination().getDestNode())) {
                                     transaction.delete(LogicalDatastoreType.OPERATIONAL, linkPath(link));
                                 }
@@ -220,8 +225,9 @@ class FlowCapableTopologyExporter implements FlowTopologyDiscoveryListener, Open
                     @Override
                     public void onSuccess(Optional<Topology> topologyOptional) {
                         if (topologyOptional.isPresent()) {
-                            Topology topologyData = topologyOptional.get();
-                            for (Link link : topologyData.getLink()) {
+                            List<Link> linkList = topologyOptional.get().getLink() != null
+                                    ? topologyOptional.get().getLink() : Collections.<Link> emptyList();
+                            for (Link link : linkList) {
                                 if (id.equals(link.getSource().getSourceTp()) || id.equals(link.getDestination().getDestTp())) {
                                     transaction.delete(LogicalDatastoreType.OPERATIONAL, linkPath(link));
                                 }
index dcc2fa15439b01ecd15eca5144f15eaa3a77086b..2b081258c42014e880846330994ea2dbb84147b8 100644 (file)
@@ -19,15 +19,15 @@ import javax.management.openmbean.OpenType;
  * of some module. Contains default value extracted from yang file.
  */
 public class AttributeConfigElement {
-    private final Object dafaultValue;
+    private final Object defaultValue;
     private final Object value;
 
     private Optional<?> resolvedValue;
     private Object resolvedDefaultValue;
     private String jmxName;
 
-    public AttributeConfigElement(Object dafaultValue, Object value) {
-        this.dafaultValue = dafaultValue;
+    public AttributeConfigElement(Object defaultValue, Object value) {
+        this.defaultValue = defaultValue;
         this.value = value;
     }
 
@@ -42,7 +42,7 @@ public class AttributeConfigElement {
     public void resolveValue(AttributeResolvingStrategy<?, ? extends OpenType<?>> attributeResolvingStrategy,
             String attrName) throws NetconfDocumentedException {
         resolvedValue = attributeResolvingStrategy.parseAttribute(attrName, value);
-        Optional<?> resolvedDefault = attributeResolvingStrategy.parseAttribute(attrName, dafaultValue);
+        Optional<?> resolvedDefault = attributeResolvingStrategy.parseAttribute(attrName, defaultValue);
         resolvedDefaultValue = resolvedDefault.isPresent() ? resolvedDefault.get() : null;
     }
 
@@ -58,6 +58,10 @@ public class AttributeConfigElement {
         return value;
     }
 
+    public Object getDefaultValue() {
+        return defaultValue;
+    }
+
     public Optional<?> getResolvedValue() {
         return resolvedValue;
     }
@@ -68,7 +72,7 @@ public class AttributeConfigElement {
 
     @Override
     public String toString() {
-        return "AttributeConfigElement [dafaultValue=" + dafaultValue + ", value=" + value + "]";
+        return "AttributeConfigElement [defaultValue=" + defaultValue + ", value=" + value + "]";
     }
 
 }
index 792fb28027245d92c30e1bbd3d84ee99e22beced..d06e55da6263e0cb56a0f0b7c4fe0f9fb0b283b7 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attri
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 
@@ -39,13 +40,18 @@ public class CompositeAttributeReadingStrategy extends AbstractAttributeReadingS
 
         List<XmlElement> recognisedChildren = Lists.newArrayList();
         for (Entry<String, AttributeReadingStrategy> innerAttrEntry : innerStrategies.entrySet()) {
-            List<XmlElement> childItem = null;
-            childItem = complexElement.getChildElementsWithSameNamespace(innerAttrEntry.getKey());
+            List<XmlElement> childItem = complexElement.getChildElementsWithSameNamespace(
+                    innerAttrEntry.getKey());
             recognisedChildren.addAll(childItem);
 
             AttributeConfigElement resolvedInner = innerAttrEntry.getValue().readElement(childItem);
 
-            innerMap.put(innerAttrEntry.getKey(), resolvedInner.getValue());
+            Object value = resolvedInner.getValue();
+            if(value == null) {
+                value = resolvedInner.getDefaultValue();
+            }
+
+            innerMap.put(innerAttrEntry.getKey(), value);
         }
 
         complexElement.checkUnrecognisedElements(recognisedChildren);
index 61ea76bbfeb9504f456132ba7cfebd67bcc6e508..e69084078963595a286e1aa75ea305b38789e091 100644 (file)
@@ -93,8 +93,9 @@ public class ObjectXmlReader extends AttributeIfcSwitchStatement<AttributeReadin
 
     @Override
     protected AttributeReadingStrategy caseTOAttribute(CompositeType openType) {
-        Preconditions.checkState(getLastAttribute() instanceof TOAttribute);
-        Map<String, AttributeIfc> inner = ((TOAttribute)getLastAttribute()).getYangPropertiesToTypesMap();
+        AttributeIfc lastAttribute = getLastAttribute();
+        Preconditions.checkState(lastAttribute instanceof TOAttribute);
+        Map<String, AttributeIfc> inner = ((TOAttribute)lastAttribute).getYangPropertiesToTypesMap();
 
         Map<String, AttributeReadingStrategy> innerStrategies = Maps.newHashMap();
 
@@ -104,21 +105,23 @@ public class ObjectXmlReader extends AttributeIfcSwitchStatement<AttributeReadin
             innerStrategies.put(innerAttrEntry.getKey(), innerStrat);
         }
 
-        return new CompositeAttributeReadingStrategy(getLastAttribute().getNullableDefault(), innerStrategies);
+        return new CompositeAttributeReadingStrategy(lastAttribute.getNullableDefault(), innerStrategies);
     }
 
     @Override
     protected AttributeReadingStrategy caseListAttribute(ArrayType<?> openType) {
-        Preconditions.checkState(getLastAttribute() instanceof ListAttribute);
-        AttributeReadingStrategy innerStrategy = prepareReadingStrategy(key, ((ListAttribute) getLastAttribute()).getInnerAttribute());
-        return new ArrayAttributeReadingStrategy(getLastAttribute().getNullableDefault(), innerStrategy);
+        AttributeIfc lastAttribute = getLastAttribute();
+        Preconditions.checkState(lastAttribute instanceof ListAttribute);
+        AttributeReadingStrategy innerStrategy = prepareReadingStrategy(key, ((ListAttribute) lastAttribute).getInnerAttribute());
+        return new ArrayAttributeReadingStrategy(lastAttribute.getNullableDefault(), innerStrategy);
     }
 
     @Override
     protected AttributeReadingStrategy caseListDependeciesAttribute(ArrayType<?> openType) {
-        Preconditions.checkState(getLastAttribute() instanceof ListDependenciesAttribute);
+        AttributeIfc lastAttribute = getLastAttribute();
+        Preconditions.checkState(lastAttribute instanceof ListDependenciesAttribute);
         AttributeReadingStrategy innerStrategy = caseDependencyAttribute(SimpleType.OBJECTNAME);
-        return new ArrayAttributeReadingStrategy(getLastAttribute().getNullableDefault(), innerStrategy);
+        return new ArrayAttributeReadingStrategy(lastAttribute.getNullableDefault(), innerStrategy);
     }
 
 }
index 4d984acee0206c1cce11b23f6f4f0dd1415506f8..b50a035be2f20d2d1c850701a845b2f766b11443 100644 (file)
@@ -42,6 +42,9 @@ public class ObjectMapper extends AttributeIfcSwitchStatement<AttributeMappingSt
         if(attributeIfc instanceof DependencyAttribute) {
             serviceNameOfDepAttr = ((DependencyAttribute)attributeIfc).getDependency().getSie().getQName().getLocalName();
             namespaceOfDepAttr = ((DependencyAttribute)attributeIfc).getDependency().getSie().getQName().getNamespace().toString();
+        } else if (attributeIfc instanceof ListDependenciesAttribute) {
+            serviceNameOfDepAttr = ((ListDependenciesAttribute)attributeIfc).getDependency().getSie().getQName().getLocalName();
+            namespaceOfDepAttr = ((ListDependenciesAttribute)attributeIfc).getDependency().getSie().getQName().getNamespace().toString();
         }
 
         return switchAttribute(attributeIfc);
index 0a48e6c67dc8cc290c2b81a1b0eb67c05ac7c618..8e9f9978c4dd837334b07db2d1f6c96764e0ede9 100644 (file)
@@ -173,8 +173,12 @@ public class ConfigPersisterActivator implements BundleActivator {
                         if(configs != null && !configs.isEmpty()) {
                             configPusher.pushConfigs(configs);
                         }
-                        registration = context.registerService(ConfigPusher.class.getName(), configPusher, null);
-                        configPusher.process(autoCloseables, platformMBeanServer, persisterAggregator);
+                        if(context != null) {
+                            registration = context.registerService(ConfigPusher.class.getName(), configPusher, null);
+                            configPusher.process(autoCloseables, platformMBeanServer, persisterAggregator);
+                        } else {
+                            logger.warn("Unable to process configs as BundleContext is null");
+                        }
                     } catch (InterruptedException e) {
                         logger.info("ConfigPusher thread stopped",e);
                     }
diff --git a/opendaylight/netconf/netconf-auth/pom.xml b/opendaylight/netconf/netconf-auth/pom.xml
new file mode 100644 (file)
index 0000000..e19359a
--- /dev/null
@@ -0,0 +1,31 @@
+<?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>netconf-subsystem</artifactId>
+        <version>0.2.5-SNAPSHOT</version>
+        <relativePath>../</relativePath>
+    </parent>
+    <artifactId>netconf-auth</artifactId>
+    <packaging>bundle</packaging>
+    <name>${project.artifactId}</name>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/opendaylight/netconf/netconf-auth/src/main/java/org/opendaylight/controller/netconf/auth/AuthConstants.java b/opendaylight/netconf/netconf-auth/src/main/java/org/opendaylight/controller/netconf/auth/AuthConstants.java
new file mode 100644 (file)
index 0000000..de5bdd6
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * 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.netconf.auth;
+
+public class AuthConstants {
+
+    /**
+     * This property should be set for every implementation of AuthService published to OSGi.
+     * Netconf SSH will pick the service with highest preference in case of multiple services present in OSGi.
+     */
+    public static final String SERVICE_PREFERENCE_KEY = "preference";
+}
@@ -6,11 +6,20 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.controller.netconf.ssh.authentication;
+package org.opendaylight.controller.netconf.auth;
 
+/**
+ * Authentication Service definition for netconf.
+ */
 public interface AuthProvider {
 
+    /**
+     * Authenticate user by username/password.
+     *
+     * @param username username
+     * @param password password
+     * @return true if authentication is successful, false otherwise
+     */
     boolean authenticated(String username, String password);
 
-    char[] getPEMAsCharArray();
 }
index 87b3f837e8c43a25f74f78cfbdd0b425bd8d94e9..7a14c4f4ac3507e953e4cdf595cc6575b38cd86e 100644 (file)
@@ -12,7 +12,7 @@ import io.netty.util.concurrent.Promise;
 import java.io.IOException;
 import org.opendaylight.controller.netconf.nettyutil.AbstractChannelInitializer;
 import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.AsyncSshHandler;
 import org.opendaylight.protocol.framework.SessionListenerFactory;
 
 final class SshClientChannelInitializer extends AbstractChannelInitializer<NetconfClientSession> {
@@ -32,7 +32,8 @@ final class SshClientChannelInitializer extends AbstractChannelInitializer<Netco
     @Override
     public void initialize(final Channel ch, final Promise<NetconfClientSession> promise) {
         try {
-            ch.pipeline().addFirst(SshHandler.createForNetconfSubsystem(authenticationHandler));
+            // ssh handler has to be the first handler in pipeline
+            ch.pipeline().addFirst(AsyncSshHandler.createForNetconfSubsystem(authenticationHandler));
             super.initialize(ch,promise);
         } catch (final IOException e) {
             throw new RuntimeException(e);
index d4073e5c178f1748ef71ee8466e70982646dab94..bd931c33d0212858b615aed61d843e1e6f1744d9 100644 (file)
  */
 package org.opendaylight.controller.netconf.it;
 
-import java.net.InetSocketAddress;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anySetOf;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.local.LocalAddress;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.HashedWheelTimer;
+import io.netty.util.concurrent.GlobalEventExecutor;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import org.apache.commons.io.IOUtils;
 import org.junit.After;
 import org.junit.Before;
 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.IdentityTestModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.MultipleDependenciesModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
 import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionListener;
 import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
 import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreService;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreServiceImpl;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot;
 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
 import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
 import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory;
 import org.opendaylight.controller.netconf.impl.SessionIdProvider;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl;
 import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
 import org.opendaylight.protocol.framework.NeverReconnectStrategy;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.w3c.dom.Element;
 
-import io.netty.channel.EventLoopGroup;
-import io.netty.channel.nio.NioEventLoopGroup;
-import io.netty.util.HashedWheelTimer;
-import io.netty.util.concurrent.GlobalEventExecutor;
+public abstract class AbstractNetconfConfigTest extends AbstractConfigTest {
 
-public class AbstractNetconfConfigTest extends AbstractConfigTest {
+    public static final String LOOPBACK_ADDRESS = "127.0.0.1";
+    public static final int SERVER_CONNECTION_TIMEOUT_MILLIS = 5000;
+
+    static ModuleFactory[] FACTORIES = { new TestImplModuleFactory(),
+            new DepTestImplModuleFactory(), new NetconfTestImplModuleFactory(),
+            new IdentityTestModuleFactory(), new MultipleDependenciesModuleFactory() };
 
     private EventLoopGroup nettyThreadgroup;
     private HashedWheelTimer hashedWheelTimer;
 
+    private NetconfClientDispatcherImpl clientDispatcher;
+    private Channel serverTcpChannel;
+
+    private NetconfMessage getConfig;
+    private NetconfMessage get;
+
+    /**
+     * @Before in subclasses is called after this method.
+     */
     @Before
-    public void setUpAbstractNetconfConfigTest() {
+    public void setUpAbstractNetconfConfigTest() throws Exception {
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, FACTORIES));
+
         nettyThreadgroup = new NioEventLoopGroup();
         hashedWheelTimer = new HashedWheelTimer();
+
+        loadMessages();
+
+        setUpTestInitial();
+
+        final NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
+        factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
+
+        for (final NetconfOperationServiceFactory netconfOperationServiceFactory : getAdditionalServiceFactories()) {
+            factoriesListener.onAddNetconfOperationServiceFactory(netconfOperationServiceFactory);
+        }
+
+        serverTcpChannel = startNetconfTcpServer(factoriesListener);
+        clientDispatcher = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer());
+    }
+
+    /**
+     * Called before setUp method is executed, so test classes can set up resources before setUpAbstractNetconfConfigTest method is called.
+     */
+    protected void setUpTestInitial() throws Exception {}
+
+    private void loadMessages() throws Exception {
+        this.getConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
+        this.get = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/get.xml");
+    }
+
+    public NetconfMessage getGetConfig() {
+        return getConfig;
+    }
+
+    public NetconfMessage getGet() {
+        return get;
+    }
+
+    private Channel startNetconfTcpServer(final NetconfOperationServiceFactoryListenerImpl factoriesListener) throws Exception {
+        final NetconfServerDispatcher dispatch = createDispatcher(factoriesListener, getNetconfMonitoringService(), getNotificationProducer());
+
+        final ChannelFuture s;
+        if(getTcpServerAddress() instanceof LocalAddress) {
+            s = dispatch.createLocalServer(((LocalAddress) getTcpServerAddress()));
+        } else {
+            s = dispatch.createServer(((InetSocketAddress) getTcpServerAddress()));
+        }
+        s.await();
+        return s.channel();
+    }
+
+    protected DefaultCommitNotificationProducer getNotificationProducer() {
+        final DefaultCommitNotificationProducer notificationProducer = mock(DefaultCommitNotificationProducer.class);
+        doNothing().when(notificationProducer).close();
+        doNothing().when(notificationProducer).sendCommitNotification(anyString(), any(Element.class), anySetOf(String.class));
+        return notificationProducer;
+    }
+
+    protected Iterable<NetconfOperationServiceFactory> getAdditionalServiceFactories() {
+        return Collections.emptySet();
+    }
+
+    protected SessionMonitoringService getNetconfMonitoringService() throws Exception {
+        final NetconfOperationProvider netconfOperationProvider = mock(NetconfOperationProvider.class);
+        final NetconfOperationServiceSnapshotImpl snap = mock(NetconfOperationServiceSnapshotImpl.class);
+        doReturn(Collections.<NetconfOperationService>emptySet()).when(snap).getServices();
+        doReturn(snap).when(netconfOperationProvider).openSnapshot(anyString());
+        return new NetconfMonitoringServiceImpl(netconfOperationProvider);
+    }
+
+    protected abstract SocketAddress getTcpServerAddress();
+
+    public NetconfClientDispatcherImpl getClientDispatcher() {
+        return clientDispatcher;
+    }
+
+    private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException {
+        final Collection<InputStream> yangDependencies = getBasicYangs();
+        return new HardcodedYangStoreService(yangDependencies);
+    }
+
+    static Collection<InputStream> getBasicYangs() throws IOException {
+
+        final List<String> paths = Arrays.asList(
+                "/META-INF/yang/config.yang",
+                "/META-INF/yang/rpc-context.yang",
+                "/META-INF/yang/config-test.yang",
+                "/META-INF/yang/config-test-impl.yang",
+                "/META-INF/yang/test-types.yang",
+                "/META-INF/yang/ietf-inet-types.yang");
+
+        final Collection<InputStream> yangDependencies = new ArrayList<>();
+        final List<String> failedToFind = new ArrayList<>();
+        for (final String path : paths) {
+            final InputStream resourceAsStream = NetconfITTest.class.getResourceAsStream(path);
+            if (resourceAsStream == null) {
+                failedToFind.add(path);
+            } else {
+                yangDependencies.add(resourceAsStream);
+            }
+        }
+        assertEquals("Some yang files were not found", Collections.<String>emptyList(), failedToFind);
+        return yangDependencies;
     }
 
     protected NetconfServerDispatcher createDispatcher(
-            NetconfOperationServiceFactoryListenerImpl factoriesListener, SessionMonitoringService sessionMonitoringService,
-            DefaultCommitNotificationProducer commitNotifier) {
-        SessionIdProvider idProvider = new SessionIdProvider();
+            final NetconfOperationServiceFactoryListenerImpl factoriesListener, final SessionMonitoringService sessionMonitoringService,
+            final DefaultCommitNotificationProducer commitNotifier) {
+        final SessionIdProvider idProvider = new SessionIdProvider();
 
-        NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
-                hashedWheelTimer, factoriesListener, idProvider, 5000, commitNotifier, sessionMonitoringService);
+        final NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
+                hashedWheelTimer, factoriesListener, idProvider, SERVER_CONNECTION_TIMEOUT_MILLIS, commitNotifier, sessionMonitoringService);
 
-        NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(
+        final NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(
                 serverNegotiatorFactory);
         return new NetconfServerDispatcher(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup);
     }
@@ -60,19 +222,58 @@ public class AbstractNetconfConfigTest extends AbstractConfigTest {
         return nettyThreadgroup;
     }
 
+    /**
+     * @After in subclasses is be called before this.
+     */
     @After
-    public void cleanUpTimer() {
+    public void cleanUpNetconf() throws Exception {
+        serverTcpChannel.close().await();
         hashedWheelTimer.stop();
-        nettyThreadgroup.shutdownGracefully();
+        nettyThreadgroup.shutdownGracefully().await();
     }
 
     public NetconfClientConfiguration getClientConfiguration(final InetSocketAddress tcpAddress, final int timeout) {
         final NetconfClientConfigurationBuilder b = NetconfClientConfigurationBuilder.create();
         b.withAddress(tcpAddress);
         b.withSessionListener(new SimpleNetconfClientSessionListener());
-        b.withReconnectStrategy(new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE,
-                timeout));
+        b.withReconnectStrategy(new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, timeout));
         b.withConnectionTimeoutMillis(timeout);
         return b.build();
     }
+
+    public static final class HardcodedYangStoreService implements YangStoreService {
+
+        private final List<InputStream> byteArrayInputStreams;
+
+        public HardcodedYangStoreService(final Collection<? extends InputStream> inputStreams) throws YangStoreException, IOException {
+            byteArrayInputStreams = new ArrayList<>();
+            for (final InputStream inputStream : inputStreams) {
+                assertNotNull(inputStream);
+                final byte[] content = IOUtils.toByteArray(inputStream);
+                final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(content);
+                byteArrayInputStreams.add(byteArrayInputStream);
+            }
+        }
+
+        @Override
+        public YangStoreSnapshot getYangStoreSnapshot() throws YangStoreException {
+            for (final InputStream inputStream : byteArrayInputStreams) {
+                try {
+                    inputStream.reset();
+                } catch (final IOException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+
+            final YangParserImpl yangParser = new YangParserImpl();
+            final SchemaContext schemaContext = yangParser.resolveSchemaContext(new HashSet<>(yangParser.parseYangModelsFromStreamsMapped(byteArrayInputStreams).values()));
+            final YangStoreServiceImpl yangStoreService = new YangStoreServiceImpl(new SchemaContextProvider() {
+                @Override
+                public SchemaContext getSchemaContext() {
+                    return schemaContext ;
+                }
+            });
+            return yangStoreService.getYangStoreSnapshot();
+        }
+    }
 }
diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/HardcodedYangStoreService.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/HardcodedYangStoreService.java
deleted file mode 100644 (file)
index 3fa1b01..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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
- */
-package org.opendaylight.controller.netconf.it;
-
-import static org.junit.Assert.assertNotNull;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-
-import org.apache.commons.io.IOUtils;
-import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException;
-import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreService;
-import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreServiceImpl;
-import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
-import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
-
-public class HardcodedYangStoreService implements YangStoreService {
-
-    private final List<InputStream> byteArrayInputStreams;
-
-    public HardcodedYangStoreService(
-            Collection<? extends InputStream> inputStreams)
-            throws YangStoreException, IOException {
-        byteArrayInputStreams = new ArrayList<>();
-        for (InputStream inputStream : inputStreams) {
-            assertNotNull(inputStream);
-            byte[] content = IOUtils.toByteArray(inputStream);
-            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
-                    content);
-            byteArrayInputStreams.add(byteArrayInputStream);
-        }
-    }
-
-    @Override
-    public YangStoreSnapshot getYangStoreSnapshot() throws YangStoreException {
-        for (InputStream inputStream : byteArrayInputStreams) {
-            try {
-                inputStream.reset();
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        YangParserImpl yangParser = new YangParserImpl();
-        final SchemaContext schemaContext = yangParser.resolveSchemaContext(new HashSet<>(yangParser.parseYangModelsFromStreamsMapped(byteArrayInputStreams).values()));
-        YangStoreServiceImpl yangStoreService = new YangStoreServiceImpl(new SchemaContextProvider() {
-            @Override
-            public SchemaContext getSchemaContext() {
-                return schemaContext ;
-            }
-        });
-        return yangStoreService.getYangStoreSnapshot();
-    }
-}
index eb99be0dc08f006ece7f7a93193f103bfa2bfb61..4b49c0928b09864342519cd9b2b5770b032cba30 100644 (file)
@@ -11,7 +11,6 @@ import static junit.framework.Assert.assertEquals;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithName;
@@ -20,41 +19,32 @@ import static org.opendaylight.controller.netconf.util.xml.XmlUtil.readXmlToDocu
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
-import io.netty.channel.ChannelFuture;
 import java.io.IOException;
-import java.io.InputStream;
+import java.lang.management.ManagementFactory;
 import java.net.InetSocketAddress;
-import java.util.Collection;
+import java.net.SocketAddress;
+import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 import javax.management.InstanceNotFoundException;
 import javax.management.Notification;
 import javax.management.NotificationListener;
-import org.junit.After;
-import org.junit.Before;
 import org.junit.Test;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
-import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
 import org.opendaylight.controller.config.persist.api.Persister;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.api.jmx.CommitJMXNotification;
-import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession;
-import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
-import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
 import org.opendaylight.controller.netconf.client.test.TestingNetconfClient;
-import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
-import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException;
 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
-import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
-import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl;
 import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
 import org.opendaylight.controller.netconf.mapping.api.Capability;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
 import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringActivator;
 import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOperationService;
 import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler;
@@ -65,64 +55,48 @@ import org.xml.sax.SAXException;
 
 public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest {
 
-    private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023);
+    public static final int PORT = 12026;
+    private static final InetSocketAddress TCP_ADDRESS = new InetSocketAddress(LOOPBACK_ADDRESS, PORT);
 
-    private NetconfClientDispatcher clientDispatcher;
-    private DefaultCommitNotificationProducer commitNotifier;
+    private NetconfMonitoringServiceImpl netconfMonitoringService;
 
-    @Before
-    public void setUp() throws Exception {
-        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,NetconfITTest.FACTORIES));
-
-        NetconfMonitoringServiceImpl monitoringService = new NetconfMonitoringServiceImpl(getNetconfOperationProvider());
-
-        NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
-        factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
-        factoriesListener
-                .onAddNetconfOperationServiceFactory(new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(
-                        new NetconfMonitoringOperationService(monitoringService)));
-
-
-        commitNotifier = new DefaultCommitNotificationProducer(platformMBeanServer);
-        NetconfServerDispatcher dispatch = createDispatcher(factoriesListener, mockSessionMonitoringService(), commitNotifier);
-        ChannelFuture s = dispatch.createServer(tcpAddress);
-        s.await();
-
-        clientDispatcher = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer());
+    @Override
+    protected void setUpTestInitial() {
+        netconfMonitoringService = new NetconfMonitoringServiceImpl(getNetconfOperationProvider());
     }
 
-    @After
-    public void cleanUp(){
-        commitNotifier.close();
+    @Override
+    protected SessionMonitoringService getNetconfMonitoringService() throws Exception {
+        return netconfMonitoringService;
     }
 
-    private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException {
-        final Collection<InputStream> yangDependencies = NetconfITTest.getBasicYangs();
-        return new HardcodedYangStoreService(yangDependencies);
+    @Override
+    protected SocketAddress getTcpServerAddress() {
+        return TCP_ADDRESS;
     }
 
-
-    protected SessionMonitoringService mockSessionMonitoringService() {
-        SessionMonitoringService mockedSessionMonitor = mock(SessionMonitoringService.class);
-        doNothing().when(mockedSessionMonitor).onSessionUp(any(NetconfManagementSession.class));
-        doNothing().when(mockedSessionMonitor).onSessionDown(any(NetconfManagementSession.class));
-        return mockedSessionMonitor;
+    @Override
+    protected Iterable<NetconfOperationServiceFactory> getAdditionalServiceFactories() {
+        return Collections.<NetconfOperationServiceFactory>singletonList(new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(
+                new NetconfMonitoringOperationService(netconfMonitoringService)));
     }
 
-
+    @Override
+    protected DefaultCommitNotificationProducer getNotificationProducer() {
+        return new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
+    }
 
     @Test
     public void testNetconfCommitNotifications() throws Exception {
+        final VerifyingNotificationListener notificationVerifier = createCommitNotificationListener();
+        final VerifyingPersister mockedAggregator = mockAggregator();
 
-        VerifyingNotificationListener notificationVerifier = createCommitNotificationListener();
-        VerifyingPersister mockedAggregator = mockAggregator();
-
-        try (TestingNetconfClient persisterClient = new TestingNetconfClient("persister", clientDispatcher, getClientConfiguration(tcpAddress, 4000))) {
+        try (TestingNetconfClient persisterClient = new TestingNetconfClient("persister", getClientDispatcher(), getClientConfiguration(TCP_ADDRESS, 4000))) {
             try (ConfigPersisterNotificationHandler configPersisterNotificationHandler = new ConfigPersisterNotificationHandler(
                     platformMBeanServer, mockedAggregator)) {
 
 
-                try (TestingNetconfClient netconfClient = new TestingNetconfClient("client", clientDispatcher, getClientConfiguration(tcpAddress, 4000))) {
+                try (TestingNetconfClient netconfClient = new TestingNetconfClient("client", getClientDispatcher(), getClientConfiguration(TCP_ADDRESS, 4000))) {
                     NetconfMessage response = netconfClient.sendMessage(loadGetConfigMessage());
                     assertContainsElementWithName(response.getDocument(), "modules");
                     assertContainsElementWithName(response.getDocument(), "services");
@@ -152,7 +126,7 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest {
     }
 
     private VerifyingNotificationListener createCommitNotificationListener() throws InstanceNotFoundException {
-        VerifyingNotificationListener listener = new VerifyingNotificationListener();
+        final VerifyingNotificationListener listener = new VerifyingNotificationListener();
         platformMBeanServer.addNotificationListener(DefaultCommitNotificationProducer.OBJECT_NAME, listener, null, null);
         return listener;
     }
@@ -171,12 +145,12 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest {
 
 
     public NetconfOperationProvider getNetconfOperationProvider() {
-        NetconfOperationProvider factoriesListener = mock(NetconfOperationProvider.class);
-        NetconfOperationServiceSnapshotImpl snap = mock(NetconfOperationServiceSnapshotImpl.class);
-        NetconfOperationService service = mock(NetconfOperationService.class);
-        Set<Capability> caps = Sets.newHashSet();
+        final NetconfOperationProvider factoriesListener = mock(NetconfOperationProvider.class);
+        final NetconfOperationServiceSnapshotImpl snap = mock(NetconfOperationServiceSnapshotImpl.class);
+        final NetconfOperationService service = mock(NetconfOperationService.class);
+        final Set<Capability> caps = Sets.newHashSet();
         doReturn(caps).when(service).getCapabilities();
-        Set<NetconfOperationService> services = Sets.newHashSet(service);
+        final Set<NetconfOperationService> services = Sets.newHashSet(service);
         doReturn(services).when(snap).getServices();
         doReturn(snap).when(factoriesListener).openSnapshot(anyString());
 
@@ -187,23 +161,23 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest {
         public List<Notification> notifications = Lists.newArrayList();
 
         @Override
-        public void handleNotification(Notification notification, Object handback) {
+        public void handleNotification(final Notification notification, final Object handback) {
             this.notifications.add(notification);
         }
 
-        void assertNotificationCount(Object size) {
+        void assertNotificationCount(final Object size) {
             assertEquals(size, notifications.size());
         }
 
-        void assertNotificationContent(int notificationIndex, int expectedModulesSize, int expectedServicesSize, int expectedCapsSize) {
-            Notification notification = notifications.get(notificationIndex);
+        void assertNotificationContent(final int notificationIndex, final int expectedModulesSize, final int expectedServicesSize, final int expectedCapsSize) {
+            final Notification notification = notifications.get(notificationIndex);
             assertEquals(CommitJMXNotification.class, notification.getClass());
-            int capsSize = ((CommitJMXNotification) notification).getCapabilities().size();
+            final int capsSize = ((CommitJMXNotification) notification).getCapabilities().size();
             assertEquals("Expected capabilities count", expectedCapsSize, capsSize);
-            Element configSnapshot = ((CommitJMXNotification) notification).getConfigSnapshot();
-            int modulesSize = configSnapshot.getElementsByTagName("module").getLength();
+            final Element configSnapshot = ((CommitJMXNotification) notification).getConfigSnapshot();
+            final int modulesSize = configSnapshot.getElementsByTagName("module").getLength();
             assertEquals("Expected modules count", expectedModulesSize, modulesSize);
-            int servicesSize = configSnapshot.getElementsByTagName("instance").getLength();
+            final int servicesSize = configSnapshot.getElementsByTagName("instance").getLength();
             assertEquals("Expected services count", expectedServicesSize, servicesSize);
         }
     }
@@ -214,12 +188,12 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest {
         private Persister mockedPersister;
 
         public VerifyingPersister() throws IOException {
-            Persister mockedAggregator = mock(Persister.class);
+            final Persister mockedAggregator = mock(Persister.class);
 
             doAnswer(new Answer<Object>() {
                 @Override
-                public Object answer(InvocationOnMock invocation) throws Throwable {
-                    ConfigSnapshotHolder configSnapshot = (ConfigSnapshotHolder) invocation.getArguments()[0];
+                public Object answer(final InvocationOnMock invocation) throws Throwable {
+                    final ConfigSnapshotHolder configSnapshot = (ConfigSnapshotHolder) invocation.getArguments()[0];
                     snapshots.add(configSnapshot);
                     return null;
                 }
@@ -228,22 +202,22 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest {
             this.mockedPersister = mockedAggregator;
         }
 
-        void assertSnapshotCount(Object size) {
+        void assertSnapshotCount(final Object size) {
             assertEquals(size, snapshots.size());
         }
 
-        void assertSnapshotContent(int notificationIndex, int expectedModulesSize, int expectedServicesSize, int expectedCapsSize)
+        void assertSnapshotContent(final int notificationIndex, final int expectedModulesSize, final int expectedServicesSize, final int expectedCapsSize)
                 throws SAXException, IOException {
-            ConfigSnapshotHolder snapshot = snapshots.get(notificationIndex);
-            int capsSize = snapshot.getCapabilities().size();
+            final ConfigSnapshotHolder snapshot = snapshots.get(notificationIndex);
+            final int capsSize = snapshot.getCapabilities().size();
             assertEquals("Expected capabilities count", expectedCapsSize, capsSize);
-            Document configSnapshot = readXmlToDocument(snapshot.getConfigSnapshot());
+            final Document configSnapshot = readXmlToDocument(snapshot.getConfigSnapshot());
             assertElementsCount(configSnapshot, "module", expectedModulesSize);
             assertElementsCount(configSnapshot, "instance", expectedServicesSize);
         }
 
         @Override
-        public void persistConfig(ConfigSnapshotHolder configSnapshotHolder) throws IOException {
+        public void persistConfig(final ConfigSnapshotHolder configSnapshotHolder) throws IOException {
             mockedPersister.persistConfig(configSnapshotHolder);
         }
 
diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITMonitoringTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITMonitoringTest.java
new file mode 100644 (file)
index 0000000..72a2f8f
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * 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
+ */
+package org.opendaylight.controller.netconf.it;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithText;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import org.junit.Test;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession;
+import org.opendaylight.controller.netconf.client.test.TestingNetconfClient;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl;
+import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
+import org.opendaylight.controller.netconf.mapping.api.Capability;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringActivator;
+import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOperationService;
+import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.slf4j.Logger;
+import org.w3c.dom.Document;
+
+public class NetconfITMonitoringTest extends AbstractNetconfConfigTest {
+
+    public static final int PORT = 12025;
+    public static final InetSocketAddress TCP_ADDRESS = new InetSocketAddress(LOOPBACK_ADDRESS, PORT);
+    public static final TestingCapability TESTING_CAPABILITY = new TestingCapability();
+
+    private NetconfMonitoringServiceImpl netconfMonitoringService;
+
+    @Override
+    protected void setUpTestInitial() {
+        netconfMonitoringService = new NetconfMonitoringServiceImpl(getNetconfOperationProvider());
+    }
+
+    @Override
+    protected SessionMonitoringService getNetconfMonitoringService() throws Exception {
+        return netconfMonitoringService;
+    }
+
+    @Override
+    protected Iterable<NetconfOperationServiceFactory> getAdditionalServiceFactories() {
+        return Collections.<NetconfOperationServiceFactory>singletonList(new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(
+                new NetconfMonitoringOperationService(netconfMonitoringService)));
+    }
+
+    @Override
+    protected InetSocketAddress getTcpServerAddress() {
+        return TCP_ADDRESS;
+    }
+
+    static SessionMonitoringService getNetconfMonitoringListenerService(final Logger logger, final NetconfMonitoringServiceImpl monitor) {
+        return new SessionMonitoringService() {
+            @Override
+            public void onSessionUp(final NetconfManagementSession session) {
+                logger.debug("Management session up {}", session);
+                monitor.onSessionUp(session);
+            }
+
+            @Override
+            public void onSessionDown(final NetconfManagementSession session) {
+                logger.debug("Management session down {}", session);
+                monitor.onSessionDown(session);
+            }
+        };
+    }
+
+    @Test
+    public void testGetResponseFromMonitoring() throws Exception {
+        try (TestingNetconfClient netconfClient = new TestingNetconfClient("client-monitoring", getClientDispatcher(), getClientConfiguration(TCP_ADDRESS, 10000))) {
+            try (TestingNetconfClient netconfClient2 = new TestingNetconfClient("client-monitoring2", getClientDispatcher(), getClientConfiguration(TCP_ADDRESS, 10000))) {
+                Thread.sleep(500);
+                final NetconfMessage response = netconfClient2.sendMessage(getGet());
+                assertSessionElementsInResponse(response.getDocument(), 2);
+            }
+            Thread.sleep(500);
+            final NetconfMessage response = netconfClient.sendMessage(getGet());
+            assertSessionElementsInResponse(response.getDocument(), 1);
+        }
+    }
+
+
+    @Test(timeout = 13 * 10000)
+    public void testClientHelloWithAuth() throws Exception {
+        String fileName = "netconfMessages/client_hello_with_auth.xml";
+        final String hello = XmlFileLoader.fileToString(fileName);
+
+        fileName = "netconfMessages/get.xml";
+        final String get = XmlFileLoader.fileToString(fileName);
+
+        final Socket sock = new Socket(TCP_ADDRESS.getHostName(), TCP_ADDRESS.getPort());
+        sock.getOutputStream().write(hello.getBytes(Charsets.UTF_8));
+        final String separator = "]]>]]>";
+
+        sock.getOutputStream().write(separator.getBytes(Charsets.UTF_8));
+        sock.getOutputStream().write(get.getBytes(Charsets.UTF_8));
+        sock.getOutputStream().write(separator.getBytes(Charsets.UTF_8));
+
+        final StringBuilder responseBuilder = new StringBuilder();
+
+        try (InputStream inputStream = sock.getInputStream();
+             InputStreamReader reader = new InputStreamReader(inputStream);
+             BufferedReader buff = new BufferedReader(reader)) {
+            String line;
+            while ((line = buff.readLine()) != null) {
+
+                responseBuilder.append(line);
+                responseBuilder.append(System.lineSeparator());
+
+                if(line.contains("</rpc-reply>"))
+                    break;
+            }
+        }
+
+        sock.close();
+
+        final String helloMsg = responseBuilder.substring(0, responseBuilder.indexOf(separator));
+        Document doc = XmlUtil.readXmlToDocument(helloMsg);
+        assertContainsElementWithText(doc, "urn:ietf:params:netconf:capability:candidate:1.0");
+
+        final String replyMsg = responseBuilder.substring(responseBuilder.indexOf(separator) + separator.length());
+        doc = XmlUtil.readXmlToDocument(replyMsg);
+        assertContainsElementWithText(doc, "tomas");
+    }
+
+    private void assertSessionElementsInResponse(final Document document, final int i) {
+        final int elementSize = document.getElementsByTagName("session-id").getLength();
+        assertEquals("Incorrect number of session-id tags in " + XmlUtil.toString(document), i, elementSize);
+    }
+
+    public static NetconfOperationProvider getNetconfOperationProvider() {
+        final NetconfOperationProvider factoriesListener = mock(NetconfOperationProvider.class);
+        final NetconfOperationServiceSnapshotImpl snap = mock(NetconfOperationServiceSnapshotImpl.class);
+        try {
+            doNothing().when(snap).close();
+        } catch (final Exception e) {
+            // not happening
+            throw new IllegalStateException(e);
+        }
+        final NetconfOperationService service = mock(NetconfOperationService.class);
+        final Set<Capability> caps = Sets.newHashSet();
+        caps.add(TESTING_CAPABILITY);
+
+        doReturn(caps).when(service).getCapabilities();
+        final Set<NetconfOperationService> services = Sets.newHashSet(service);
+        doReturn(services).when(snap).getServices();
+        doReturn(snap).when(factoriesListener).openSnapshot(anyString());
+
+        return factoriesListener;
+    }
+
+    private static class TestingCapability implements Capability {
+        @Override
+        public String getCapabilityUri() {
+            return "namespaceModuleRevision";
+        }
+
+        @Override
+        public Optional<String> getModuleNamespace() {
+            return Optional.of("namespace");
+        }
+
+        @Override
+        public Optional<String> getModuleName() {
+            return Optional.of("name");
+        }
+
+        @Override
+        public Optional<String> getRevision() {
+            return Optional.of("revision");
+        }
+
+        @Override
+        public Optional<String> getCapabilitySchema() {
+            return Optional.of("content");
+        }
+
+        @Override
+        public Optional<List<String>> getLocation() {
+            return Optional.absent();
+        }
+    }
+}
index 6826b4a09ca6013f57c192ef07fcef3bdd7e7387..67ccf0c02ca4a2531986000bfc66db5bddce29f4 100644 (file)
 
 package org.opendaylight.controller.netconf.it;
 
-import static java.util.Arrays.asList;
-import static org.mockito.Matchers.any;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
-import ch.ethz.ssh2.Connection;
-import io.netty.channel.ChannelFuture;
-import io.netty.channel.EventLoopGroup;
-import io.netty.channel.nio.NioEventLoopGroup;
+import com.google.common.collect.Lists;
+import io.netty.channel.local.LocalAddress;
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.GenericFutureListener;
 import io.netty.util.concurrent.GlobalEventExecutor;
 import java.io.IOException;
-import java.io.InputStream;
-import java.lang.management.ManagementFactory;
 import java.net.InetSocketAddress;
-import java.util.Collection;
 import java.util.List;
-import junit.framework.Assert;
+import java.util.concurrent.atomic.AtomicInteger;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
-import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.auth.AuthProvider;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
 import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionListener;
 import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
 import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder;
 import org.opendaylight.controller.netconf.client.test.TestingNetconfClient;
-import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
-import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException;
-import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
-import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
-import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
 import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.LoginPassword;
 import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
-import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
-import org.opendaylight.controller.netconf.ssh.authentication.AuthProviderImpl;
 import org.opendaylight.controller.netconf.ssh.authentication.PEMGenerator;
 import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
 import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil;
-import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.protocol.framework.NeverReconnectStrategy;
 
 public class NetconfITSecureTest extends AbstractNetconfConfigTest {
 
-    private static final InetSocketAddress tlsAddress = new InetSocketAddress("127.0.0.1", 12024);
+    public static final int PORT = 12024;
+    private static final InetSocketAddress TLS_ADDRESS = new InetSocketAddress("127.0.0.1", PORT);
+
+    public static final String USERNAME = "user";
+    public static final String PASSWORD = "pwd";
 
-    private DefaultCommitNotificationProducer commitNot;
     private NetconfSSHServer sshServer;
-    private NetconfMessage getConfig;
 
     @Before
     public void setUp() throws Exception {
-        this.getConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
-
-        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, getModuleFactories().toArray(
-                new ModuleFactory[0])));
-
-        NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
-        factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
-
-        commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
-
-
-        final NetconfServerDispatcher dispatchS = createDispatcher(factoriesListener);
-        ChannelFuture s = dispatchS.createLocalServer(NetconfConfigUtil.getNetconfLocalAddress());
-        s.await();
-        EventLoopGroup bossGroup  = new NioEventLoopGroup();
-        sshServer = NetconfSSHServer.start(tlsAddress.getPort(), NetconfConfigUtil.getNetconfLocalAddress(), getAuthProvider(), bossGroup);
-    }
-
-    private NetconfServerDispatcher createDispatcher(NetconfOperationServiceFactoryListenerImpl factoriesListener) {
-        return super.createDispatcher(factoriesListener, NetconfITTest.getNetconfMonitoringListenerService(), commitNot);
+        final char[] pem = PEMGenerator.generate().toCharArray();
+        sshServer = NetconfSSHServer.start(TLS_ADDRESS.getPort(), NetconfConfigUtil.getNetconfLocalAddress(), getNettyThreadgroup(), pem);
+        sshServer.setAuthProvider(getAuthProvider());
     }
 
     @After
     public void tearDown() throws Exception {
-        sshServer.stop();
-        commitNot.close();
-    }
-
-    private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException {
-        final Collection<InputStream> yangDependencies = NetconfITTest.getBasicYangs();
-        return new HardcodedYangStoreService(yangDependencies);
-    }
-
-    protected List<ModuleFactory> getModuleFactories() {
-        return asList(NetconfITTest.FACTORIES);
+        sshServer.close();
+        sshServer.join();
     }
 
     @Test
     public void testSecure() throws Exception {
-        NetconfClientDispatcher dispatch = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer());
+        final NetconfClientDispatcher dispatch = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer());
         try (TestingNetconfClient netconfClient = new TestingNetconfClient("testing-ssh-client", dispatch, getClientConfiguration())) {
-            NetconfMessage response = netconfClient.sendMessage(getConfig);
-            Assert.assertFalse("Unexpected error message " + XmlUtil.toString(response.getDocument()),
+            NetconfMessage response = netconfClient.sendMessage(getGetConfig());
+            assertFalse("Unexpected error message " + XmlUtil.toString(response.getDocument()),
                     NetconfMessageUtil.isErrorMessage(response));
 
-            NetconfMessage gs = new NetconfMessage(XmlUtil.readXmlToDocument("<rpc message-id=\"2\"\n" +
+            final NetconfMessage gs = new NetconfMessage(XmlUtil.readXmlToDocument("<rpc message-id=\"2\"\n" +
                     "     xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n" +
                     "    <get-schema xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n" +
                     "        <identifier>config</identifier>\n" +
@@ -120,14 +83,49 @@ public class NetconfITSecureTest extends AbstractNetconfConfigTest {
                     "</rpc>\n"));
 
             response = netconfClient.sendMessage(gs);
-            Assert.assertFalse("Unexpected error message " + XmlUtil.toString(response.getDocument()),
+            assertFalse("Unexpected error message " + XmlUtil.toString(response.getDocument()),
                     NetconfMessageUtil.isErrorMessage(response));
         }
     }
 
+    /**
+     * Test all requests are handled properly and no mismatch occurs in listener
+     */
+    @Test(timeout = 3*60*1000)
+    public void testSecureStress() throws Exception {
+        final NetconfClientDispatcher dispatch = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer());
+        try (TestingNetconfClient netconfClient = new TestingNetconfClient("testing-ssh-client", dispatch, getClientConfiguration())) {
+
+            final AtomicInteger responseCounter = new AtomicInteger(0);
+            final List<Future<?>> futures = Lists.newArrayList();
+
+            final int requests = 1000;
+            for (int i = 0; i < requests; i++) {
+                final Future<NetconfMessage> netconfMessageFuture = netconfClient.sendRequest(getGetConfig());
+                futures.add(netconfMessageFuture);
+                netconfMessageFuture.addListener(new GenericFutureListener<Future<? super NetconfMessage>>() {
+                    @Override
+                    public void operationComplete(final Future<? super NetconfMessage> future) throws Exception {
+                        assertTrue("Request unsuccessful " + future.cause(), future.isSuccess());
+                        responseCounter.incrementAndGet();
+                    }
+                });
+            }
+
+            for (final Future<?> future : futures) {
+                future.await();
+            }
+
+            // Give future listeners some time to finish counter incrementation
+            Thread.sleep(5000);
+
+            assertEquals(requests, responseCounter.get());
+        }
+    }
+
     public NetconfClientConfiguration getClientConfiguration() throws IOException {
         final NetconfClientConfigurationBuilder b = NetconfClientConfigurationBuilder.create();
-        b.withAddress(tlsAddress);
+        b.withAddress(TLS_ADDRESS);
         b.withSessionListener(new SimpleNetconfClientSessionListener());
         b.withReconnectStrategy(new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, 5000));
         b.withProtocol(NetconfClientConfiguration.NetconfClientProtocol.SSH);
@@ -137,23 +135,18 @@ public class NetconfITSecureTest extends AbstractNetconfConfigTest {
     }
 
     public AuthProvider getAuthProvider() throws Exception {
-        AuthProvider mock = mock(AuthProviderImpl.class);
-        doReturn(true).when(mock).authenticated(anyString(), anyString());
-        doReturn(PEMGenerator.generate().toCharArray()).when(mock).getPEMAsCharArray();
-        return mock;
+        final AuthProvider mockAuth = mock(AuthProvider.class);
+        doReturn("mockedAuth").when(mockAuth).toString();
+        doReturn(true).when(mockAuth).authenticated(anyString(), anyString());
+        return mockAuth;
     }
 
     public AuthenticationHandler getAuthHandler() throws IOException {
-        final AuthenticationHandler authHandler = mock(AuthenticationHandler.class);
-        doAnswer(new Answer() {
-            @Override
-            public Object answer(final InvocationOnMock invocation) throws Throwable {
-                Connection conn = (Connection) invocation.getArguments()[0];
-                conn.authenticateWithPassword("user", "pwd");
-                return null;
-            }
-        }).when(authHandler).authenticate(any(Connection.class));
-        doReturn("auth handler").when(authHandler).toString();
-        return authHandler;
+        return new LoginPassword(USERNAME, PASSWORD);
+    }
+
+    @Override
+    protected LocalAddress getTcpServerAddress() {
+        return NetconfConfigUtil.getNetconfLocalAddress();
     }
 }
index 8e69e6a345ffef868c2ed4e5bc454c440dc989a4..a7a9d7494af73e8553bf9ce9a638b02958c5ece0 100644 (file)
@@ -8,11 +8,11 @@
 
 package org.opendaylight.controller.netconf.it;
 
+import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.fail;
-import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
@@ -20,15 +20,8 @@ import com.google.common.base.Function;
 import com.google.common.base.Throwables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
-import io.netty.channel.ChannelFuture;
 import java.io.IOException;
-import java.io.InputStream;
-import java.lang.management.ManagementFactory;
 import java.net.InetSocketAddress;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -36,35 +29,19 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
 import javax.management.ObjectName;
 import javax.xml.parsers.ParserConfigurationException;
-import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
-import org.junit.matchers.JUnitMatchers;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
-import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
-import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
 import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactory;
-import org.opendaylight.controller.config.yang.test.impl.IdentityTestModuleFactory;
 import org.opendaylight.controller.config.yang.test.impl.MultipleDependenciesModuleFactory;
 import org.opendaylight.controller.config.yang.test.impl.MultipleDependenciesModuleMXBean;
 import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
 import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleMXBean;
-import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.controller.netconf.client.test.TestingNetconfClient;
-import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
-import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException;
-import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
-import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
-import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
-import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
-import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
@@ -80,129 +57,57 @@ import org.xml.sax.SAXException;
 
 public class NetconfITTest extends AbstractNetconfConfigTest {
 
-    // TODO refactor, pull common code up to AbstractNetconfITTest
+    public static final int PORT = 12023;
+    public static final InetSocketAddress TCP_ADDRESS = new InetSocketAddress(LOOPBACK_ADDRESS, PORT);
 
-    private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023);
-
-
-    private NetconfMessage getConfig, getConfigCandidate, editConfig, closeSession;
-    private DefaultCommitNotificationProducer commitNotificationProducer;
-    private NetconfServerDispatcher dispatch;
-
-    private NetconfClientDispatcherImpl clientDispatcher;
-
-    static ModuleFactory[] FACTORIES = {new TestImplModuleFactory(), new DepTestImplModuleFactory(),
-            new NetconfTestImplModuleFactory(), new IdentityTestModuleFactory(),
-            new MultipleDependenciesModuleFactory()};
+    private NetconfMessage getConfigCandidate, editConfig, closeSession;
+    private NetconfClientDispatcher clientDispatcher;
 
     @Before
     public void setUp() throws Exception {
-        initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,
-                FACTORIES
-        ));
-
         loadMessages();
-
-        NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
-        factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
-
-        commitNotificationProducer = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
-
-        dispatch = createDispatcher(factoriesListener);
-        ChannelFuture s = dispatch.createServer(tcpAddress);
-        s.await();
-
-        clientDispatcher = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer());
-    }
-
-    private NetconfServerDispatcher createDispatcher(NetconfOperationServiceFactoryListenerImpl factoriesListener) {
-        return super.createDispatcher(factoriesListener, getNetconfMonitoringListenerService(), commitNotificationProducer);
+        clientDispatcher = getClientDispatcher();
     }
 
-    static NetconfMonitoringServiceImpl getNetconfMonitoringListenerService() {
-        NetconfOperationProvider netconfOperationProvider = mock(NetconfOperationProvider.class);
-        NetconfOperationServiceSnapshotImpl snap = mock(NetconfOperationServiceSnapshotImpl.class);
-        doReturn(Collections.<NetconfOperationService>emptySet()).when(snap).getServices();
-        doReturn(snap).when(netconfOperationProvider).openSnapshot(anyString());
-        return new NetconfMonitoringServiceImpl(netconfOperationProvider);
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        commitNotificationProducer.close();
-        clientDispatcher.close();
+    @Override
+    protected InetSocketAddress getTcpServerAddress() {
+        return TCP_ADDRESS;
     }
 
     private void loadMessages() throws IOException, SAXException, ParserConfigurationException {
         this.editConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/edit_config.xml");
-        this.getConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
         this.getConfigCandidate = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig_candidate.xml");
         this.closeSession = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/closeSession.xml");
     }
 
-    private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException {
-        final Collection<InputStream> yangDependencies = getBasicYangs();
-        return new HardcodedYangStoreService(yangDependencies);
-    }
-
-    static Collection<InputStream> getBasicYangs() throws IOException {
-
-        List<String> paths = Arrays.asList("/META-INF/yang/config.yang", "/META-INF/yang/rpc-context.yang",
-                "/META-INF/yang/config-test.yang", "/META-INF/yang/config-test-impl.yang", "/META-INF/yang/test-types.yang",
-                "/META-INF/yang/ietf-inet-types.yang");
-        final Collection<InputStream> yangDependencies = new ArrayList<>();
-        List<String> failedToFind = new ArrayList<>();
-        for (String path : paths) {
-            InputStream resourceAsStream = NetconfITTest.class.getResourceAsStream(path);
-            if (resourceAsStream == null) {
-                failedToFind.add(path);
-            } else {
-                yangDependencies.add(resourceAsStream);
-            }
-        }
-        assertEquals("Some yang files were not found", Collections.<String>emptyList(), failedToFind);
-        return yangDependencies;
-    }
-
-
     @Test
     public void testNetconfClientDemonstration() throws Exception {
-        try (TestingNetconfClient netconfClient = new TestingNetconfClient("client", clientDispatcher, getClientConfiguration(tcpAddress, 4000))) {
+        try (TestingNetconfClient netconfClient = new TestingNetconfClient("client", clientDispatcher, getClientConfiguration(TCP_ADDRESS, 4000))) {
 
-            Set<String> capabilitiesFromNetconfServer = netconfClient.getCapabilities();
-            long sessionId = netconfClient.getSessionId();
+            final Set<String> capabilitiesFromNetconfServer = netconfClient.getCapabilities();
+            final long sessionId = netconfClient.getSessionId();
 
             // NetconfMessage can be created :
             // new NetconfMessage(XmlUtil.readXmlToDocument("<xml/>"));
 
-            NetconfMessage response = netconfClient.sendMessage(getConfig);
+            final NetconfMessage response = netconfClient.sendMessage(getGetConfig());
             response.getDocument();
         }
     }
 
     @Test
     public void testTwoSessions() throws Exception {
-        try (TestingNetconfClient netconfClient = new TestingNetconfClient("1", clientDispatcher, getClientConfiguration(tcpAddress, 10000)))  {
-            try (TestingNetconfClient netconfClient2 = new TestingNetconfClient("2", clientDispatcher, getClientConfiguration(tcpAddress, 10000))) {
+        try (TestingNetconfClient netconfClient = new TestingNetconfClient("1", clientDispatcher, getClientConfiguration(TCP_ADDRESS, 10000)))  {
+            try (TestingNetconfClient netconfClient2 = new TestingNetconfClient("2", clientDispatcher, getClientConfiguration(TCP_ADDRESS, 10000))) {
                 assertNotNull(netconfClient2.getCapabilities());
             }
         }
     }
 
-    @Ignore
-    @Test
-    public void waitingTest() throws Exception {
-        final ConfigTransactionJMXClient transaction = this.configRegistryClient.createTransaction();
-        transaction.createModule(DepTestImplModuleFactory.NAME, "eb");
-        transaction.commit();
-        Thread.currentThread().suspend();
-    }
-
     @Test
     public void rpcReplyContainsAllAttributesTest() throws Exception {
-        try (TestingNetconfClient netconfClient = createSession(tcpAddress, "1")) {
-            final String rpc = "<rpc message-id=\"5\" a=\"a\" b=\"44\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
-                    + "<get/>" + "</rpc>";
+        try (TestingNetconfClient netconfClient = createSession(TCP_ADDRESS, "1")) {
+            final String rpc = "<rpc message-id=\"5\" a=\"a\" b=\"44\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><get/>" + "</rpc>";
             final Document doc = XmlUtil.readXmlToDocument(rpc);
             final NetconfMessage message = netconfClient.sendMessage(new NetconfMessage(doc));
             assertNotNull(message);
@@ -228,9 +133,8 @@ public class NetconfITTest extends AbstractNetconfConfigTest {
 
     @Test
     public void rpcReplyErrorContainsAllAttributesTest() throws Exception {
-        try (TestingNetconfClient netconfClient = createSession(tcpAddress, "1")) {
-            final String rpc = "<rpc message-id=\"1\" a=\"adada\" b=\"4\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
-                    + "<commit/>" + "</rpc>";
+        try (TestingNetconfClient netconfClient = createSession(TCP_ADDRESS, "1")) {
+            final String rpc = "<rpc message-id=\"1\" a=\"adada\" b=\"4\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><commit/>" + "</rpc>";
             final Document doc = XmlUtil.readXmlToDocument(rpc);
             final NetconfMessage message = netconfClient.sendMessage(new NetconfMessage(doc));
             final NamedNodeMap expectedAttributes = doc.getDocumentElement().getAttributes();
@@ -243,16 +147,16 @@ public class NetconfITTest extends AbstractNetconfConfigTest {
     @Test
     public void rpcOutputContainsCorrectNamespace() throws Exception {
         final ConfigTransactionJMXClient transaction = this.configRegistryClient.createTransaction();
-        ObjectName dep = transaction.createModule(DepTestImplModuleFactory.NAME, "instanceD");
-        ObjectName impl = transaction.createModule(NetconfTestImplModuleFactory.NAME, "instance");
-        NetconfTestImplModuleMXBean proxy = configRegistryClient
+        final ObjectName dep = transaction.createModule(DepTestImplModuleFactory.NAME, "instanceD");
+        final ObjectName impl = transaction.createModule(NetconfTestImplModuleFactory.NAME, "instance");
+        final NetconfTestImplModuleMXBean proxy = configRegistryClient
                 .newMXBeanProxy(impl, NetconfTestImplModuleMXBean.class);
         proxy.setTestingDep(dep);
         proxy.setSimpleShort((short) 0);
 
         transaction.commit();
 
-        try (TestingNetconfClient netconfClient = createSession(tcpAddress, "1")) {
+        try (TestingNetconfClient netconfClient = createSession(TCP_ADDRESS, "1")) {
             final String expectedNamespace = "urn:opendaylight:params:xml:ns:yang:controller:test:impl";
 
             final String rpc = "<rpc message-id=\"5\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
@@ -275,7 +179,7 @@ public class NetconfITTest extends AbstractNetconfConfigTest {
 
     @Test
     public void testCloseSession() throws Exception {
-        try (TestingNetconfClient netconfClient = createSession(tcpAddress, "1")) {
+        try (TestingNetconfClient netconfClient = createSession(TCP_ADDRESS, "1")) {
 
             // edit config
             Document rpcReply = netconfClient.sendMessage(this.editConfig)
@@ -291,7 +195,7 @@ public class NetconfITTest extends AbstractNetconfConfigTest {
 
     @Test
     public void testEditConfig() throws Exception {
-        try (TestingNetconfClient netconfClient = createSession(tcpAddress, "1")) {
+        try (TestingNetconfClient netconfClient = createSession(TCP_ADDRESS, "1")) {
             // send edit_config.xml
             final Document rpcReply = netconfClient.sendMessage(this.editConfig).getDocument();
             assertIsOK(rpcReply);
@@ -300,7 +204,7 @@ public class NetconfITTest extends AbstractNetconfConfigTest {
 
     @Test
     public void testValidate() throws Exception {
-        try (TestingNetconfClient netconfClient = createSession(tcpAddress, "1")) {
+        try (TestingNetconfClient netconfClient = createSession(TCP_ADDRESS, "1")) {
             // begin transaction
             Document rpcReply = netconfClient.sendMessage(getConfigCandidate).getDocument();
             assertEquals("data", XmlElement.fromDomDocument(rpcReply).getOnlyChildElement().getName());
@@ -318,7 +222,7 @@ public class NetconfITTest extends AbstractNetconfConfigTest {
     }
 
     private Document assertGetConfigWorks(final TestingNetconfClient netconfClient) throws InterruptedException, ExecutionException, TimeoutException, NetconfDocumentedException {
-        return assertGetConfigWorks(netconfClient, this.getConfig);
+        return assertGetConfigWorks(netconfClient, getGetConfig());
     }
 
     private Document assertGetConfigWorks(final TestingNetconfClient netconfClient, final NetconfMessage getConfigMessage)
@@ -331,14 +235,14 @@ public class NetconfITTest extends AbstractNetconfConfigTest {
 
     @Test
     public void testGetConfig() throws Exception {
-        try (TestingNetconfClient netconfClient = createSession(tcpAddress, "1")) {
+        try (TestingNetconfClient netconfClient = createSession(TCP_ADDRESS, "1")) {
             assertGetConfigWorks(netconfClient);
         }
     }
 
     @Test
     public void createYangTestBasedOnYuma() throws Exception {
-        try (TestingNetconfClient netconfClient = createSession(tcpAddress, "1")) {
+        try (TestingNetconfClient netconfClient = createSession(TCP_ADDRESS, "1")) {
             Document rpcReply = netconfClient.sendMessage(
                     XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/editConfig_merge_yang-test.xml"))
                     .getDocument();
@@ -351,7 +255,7 @@ public class NetconfITTest extends AbstractNetconfConfigTest {
 
             final ObjectName on = new ObjectName(
                     "org.opendaylight.controller:instanceName=impl-dep-instance,type=Module,moduleFactoryName=impl-dep");
-            Set<ObjectName> cfgBeans = configRegistryClient.lookupConfigBeans();
+            final Set<ObjectName> cfgBeans = configRegistryClient.lookupConfigBeans();
             assertEquals(cfgBeans, Sets.newHashSet(on));
         }
     }
@@ -364,21 +268,21 @@ public class NetconfITTest extends AbstractNetconfConfigTest {
 
     @Test
     public void testIdRef() throws Exception {
-        NetconfMessage editId = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/editConfig_identities.xml");
-        NetconfMessage commit = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/commit.xml");
+        final NetconfMessage editId = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/editConfig_identities.xml");
+        final NetconfMessage commit = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/commit.xml");
 
-        try (TestingNetconfClient netconfClient = createSession(tcpAddress, "1")) {
+        try (TestingNetconfClient netconfClient = createSession(TCP_ADDRESS, "1")) {
             assertIsOK(netconfClient.sendMessage(editId).getDocument());
             assertIsOK(netconfClient.sendMessage(commit).getDocument());
 
-            NetconfMessage response = netconfClient.sendMessage(getConfig);
+            final NetconfMessage response = netconfClient.sendMessage(getGetConfig());
 
-            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</afi>"));
-            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</afi>"));
-            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</safi>"));
-            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</safi>"));
+            assertThat(XmlUtil.toString(response.getDocument()), containsString("<afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</afi>"));
+            assertThat(XmlUtil.toString(response.getDocument()), containsString("<afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</afi>"));
+            assertThat(XmlUtil.toString(response.getDocument()), containsString("<safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</safi>"));
+            assertThat(XmlUtil.toString(response.getDocument()), containsString("<safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</safi>"));
 
-        } catch (Exception e) {
+        } catch (final Exception e) {
             fail(Throwables.getStackTraceAsString(e));
         }
     }
@@ -394,25 +298,24 @@ public class NetconfITTest extends AbstractNetconfConfigTest {
         return ret;
     }
 
-
     @Test
     public void testMultipleDependencies() throws Exception {
         // push first xml, should add parent and d1,d2 dependencies
-        try (TestingNetconfClient netconfClient = createSession(tcpAddress, "1")) {
-            Document rpcReply = netconfClient.sendMessage(
+        try (TestingNetconfClient netconfClient = createSession(TCP_ADDRESS, "1")) {
+            final Document rpcReply = netconfClient.sendMessage(
                     XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/editConfig_merge_multiple-deps1.xml"))
                     .getDocument();
             assertIsOK(rpcReply);
             commit(netconfClient);
         }
         // verify that parent.getTestingDeps == d1,d2
-        MultipleDependenciesModuleMXBean parentProxy = configRegistryClient.newMXBeanProxy(
+        final MultipleDependenciesModuleMXBean parentProxy = configRegistryClient.newMXBeanProxy(
                 configRegistryClient.lookupConfigBean(MultipleDependenciesModuleFactory.NAME, "parent"),
                 MultipleDependenciesModuleMXBean.class);
         {
-            List<ObjectName> testingDeps = parentProxy.getTestingDeps();
+            final List<ObjectName> testingDeps = parentProxy.getTestingDeps();
             assertEquals(2, testingDeps.size());
-            Set<String> actualRefs = getServiceReferences(testingDeps);
+            final Set<String> actualRefs = getServiceReferences(testingDeps);
             assertEquals(Sets.newHashSet("ref_d1", "ref_d2"), actualRefs);
         }
 
@@ -422,35 +325,35 @@ public class NetconfITTest extends AbstractNetconfConfigTest {
         mergeD3(parentProxy);
     }
 
-    public void mergeD3(MultipleDependenciesModuleMXBean parentProxy) throws Exception {
+    public void mergeD3(final MultipleDependenciesModuleMXBean parentProxy) throws Exception {
         try (TestingNetconfClient netconfClient = new TestingNetconfClient(
-                "test " + tcpAddress.toString(), clientDispatcher, getClientConfiguration(tcpAddress, 5000))) {
+                "test " + TCP_ADDRESS.toString(), clientDispatcher, getClientConfiguration(TCP_ADDRESS, 5000))) {
 
-            Document rpcReply = netconfClient.sendMessage(
+            final Document rpcReply = netconfClient.sendMessage(
                     XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/editConfig_merge_multiple-deps2.xml"))
                     .getDocument();
             assertIsOK(rpcReply);
             commit(netconfClient);
         }
         {
-            List<ObjectName> testingDeps = parentProxy.getTestingDeps();
+            final List<ObjectName> testingDeps = parentProxy.getTestingDeps();
             assertEquals(3, testingDeps.size());
-            Set<String> actualRefs = getServiceReferences(testingDeps);
+            final Set<String> actualRefs = getServiceReferences(testingDeps);
             assertEquals(Sets.newHashSet("ref_d1", "ref_d2", "ref_d3"), actualRefs);
         }
     }
 
-    public Set<String> getServiceReferences(List<ObjectName> testingDeps) {
+    public Set<String> getServiceReferences(final List<ObjectName> testingDeps) {
         return new HashSet<>(Lists.transform(testingDeps, new Function<ObjectName, String>() {
             @Override
-            public String apply(ObjectName input) {
+            public String apply(final ObjectName input) {
                 return ObjectNameUtil.getReferenceName(input);
             }
         }));
     }
 
-    public void commit(TestingNetconfClient netconfClient) throws Exception {
-        Document rpcReply;
+    public void commit(final TestingNetconfClient netconfClient) throws Exception {
+        final Document rpcReply;
         rpcReply = netconfClient.sendMessage(XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/commit.xml"))
                 .getDocument();
         assertIsOK(rpcReply);
diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java
deleted file mode 100644 (file)
index 05e3257..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * 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
- */
-package org.opendaylight.controller.netconf.it;
-
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithText;
-
-import com.google.common.base.Charsets;
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
-import io.netty.channel.ChannelFuture;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-import junit.framework.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
-import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession;
-import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
-import org.opendaylight.controller.netconf.client.test.TestingNetconfClient;
-import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
-import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException;
-import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
-import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
-import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
-import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
-import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl;
-import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
-import org.opendaylight.controller.netconf.mapping.api.Capability;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
-import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringActivator;
-import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOperationService;
-import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-
-public class NetconfMonitoringITTest extends AbstractNetconfConfigTest {
-
-    private static final Logger logger =  LoggerFactory.getLogger(NetconfITTest.class);
-
-    private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023);
-
-    @Mock
-    private DefaultCommitNotificationProducer commitNot;
-    private NetconfServerDispatcher dispatch;
-
-    private NetconfClientDispatcherImpl clientDispatcher;
-
-    private NetconfMonitoringServiceImpl monitoringService;
-
-    @Before
-    public void setUp() throws Exception {
-        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, NetconfITTest.FACTORIES));
-
-        monitoringService = new NetconfMonitoringServiceImpl(getNetconfOperationProvider());
-
-        NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
-        factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
-        factoriesListener
-                .onAddNetconfOperationServiceFactory(new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(
-                        new NetconfMonitoringOperationService(monitoringService)));
-
-
-        dispatch = createDispatcher(factoriesListener);
-        ChannelFuture s = dispatch.createServer(tcpAddress);
-        s.await();
-
-        clientDispatcher = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer());
-    }
-
-    private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException {
-        final Collection<InputStream> yangDependencies = NetconfITTest.getBasicYangs();
-        return new HardcodedYangStoreService(yangDependencies);
-    }
-
-    private NetconfServerDispatcher createDispatcher(
-                                                     NetconfOperationServiceFactoryListenerImpl factoriesListener) {
-        return super.createDispatcher(factoriesListener, getNetconfMonitoringListenerService(logger, monitoringService), commitNot);
-    }
-
-    static SessionMonitoringService getNetconfMonitoringListenerService(final Logger logger, final NetconfMonitoringServiceImpl monitor) {
-        return new SessionMonitoringService() {
-            @Override
-            public void onSessionUp(NetconfManagementSession session) {
-                logger.debug("Management session up {}", session);
-                monitor.onSessionUp(session);
-            }
-
-            @Override
-            public void onSessionDown(NetconfManagementSession session) {
-                logger.debug("Management session down {}", session);
-                monitor.onSessionDown(session);
-            }
-        };
-    }
-
-
-    @Test
-    public void testGetResponseFromMonitoring() throws Exception {
-        try (TestingNetconfClient netconfClient = new TestingNetconfClient("client-monitoring", clientDispatcher, getClientConfiguration(tcpAddress, 4000))) {
-        try (TestingNetconfClient netconfClient2 = new TestingNetconfClient("client-monitoring2", clientDispatcher, getClientConfiguration(tcpAddress, 4000))) {
-            NetconfMessage response = netconfClient.sendMessage(loadGetMessage());
-            assertSessionElementsInResponse(response.getDocument(), 2);
-        }
-            NetconfMessage response = netconfClient.sendMessage(loadGetMessage());
-            assertSessionElementsInResponse(response.getDocument(), 1);
-        }
-    }
-
-
-    @Test(timeout = 13 * 10000)
-    public void testClientHelloWithAuth() throws Exception {
-        String fileName = "netconfMessages/client_hello_with_auth.xml";
-        String hello = XmlFileLoader.fileToString(fileName);
-
-        fileName = "netconfMessages/get.xml";
-        String get = XmlFileLoader.fileToString(fileName);
-
-        Socket sock = new Socket(tcpAddress.getHostName(), tcpAddress.getPort());
-        sock.getOutputStream().write(hello.getBytes(Charsets.UTF_8));
-        String separator = "]]>]]>";
-
-        sock.getOutputStream().write(separator.getBytes(Charsets.UTF_8));
-        sock.getOutputStream().write(get.getBytes(Charsets.UTF_8));
-        sock.getOutputStream().write(separator.getBytes(Charsets.UTF_8));
-
-        StringBuilder responseBuilder = new StringBuilder();
-
-        try (InputStream inputStream = sock.getInputStream();
-             InputStreamReader reader = new InputStreamReader(inputStream);
-             BufferedReader buff = new BufferedReader(reader)) {
-            String line;
-            while ((line = buff.readLine()) != null) {
-
-                responseBuilder.append(line);
-                responseBuilder.append(System.lineSeparator());
-
-                if(line.contains("</rpc-reply>"))
-                    break;
-            }
-        }
-
-        sock.close();
-
-        String helloMsg = responseBuilder.substring(0, responseBuilder.indexOf(separator));
-        Document doc = XmlUtil.readXmlToDocument(helloMsg);
-        assertContainsElementWithText(doc, "urn:ietf:params:netconf:capability:candidate:1.0");
-
-        String replyMsg = responseBuilder.substring(responseBuilder.indexOf(separator) + separator.length());
-        doc = XmlUtil.readXmlToDocument(replyMsg);
-        assertContainsElementWithText(doc, "tomas");
-    }
-
-    private void assertSessionElementsInResponse(Document document, int i) {
-        int elementSize = document.getElementsByTagName("session-id").getLength();
-        Assert.assertEquals("Incorrect number of session-id tags in " + XmlUtil.toString(document),i, elementSize);
-    }
-
-    private NetconfMessage loadGetMessage() throws Exception {
-        return XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/get.xml");
-    }
-
-    public static NetconfOperationProvider getNetconfOperationProvider() throws Exception {
-        NetconfOperationProvider factoriesListener = mock(NetconfOperationProvider.class);
-        NetconfOperationServiceSnapshotImpl snap = mock(NetconfOperationServiceSnapshotImpl.class);
-        doNothing().when(snap).close();
-        NetconfOperationService service = mock(NetconfOperationService.class);
-        Set<Capability> caps = Sets.newHashSet();
-        caps.add(new Capability() {
-            @Override
-            public String getCapabilityUri() {
-                return "namespaceModuleRevision";
-            }
-
-            @Override
-            public Optional<String> getModuleNamespace() {
-                return Optional.of("namespace");
-            }
-
-            @Override
-            public Optional<String> getModuleName() {
-                return Optional.of("name");
-            }
-
-            @Override
-            public Optional<String> getRevision() {
-                return Optional.of("revision");
-            }
-
-            @Override
-            public Optional<String> getCapabilitySchema() {
-                return Optional.of("content");
-            }
-
-            @Override
-            public Optional<List<String>> getLocation() {
-                return Optional.absent();
-            }
-        });
-
-        doReturn(caps).when(service).getCapabilities();
-        Set<NetconfOperationService> services = Sets.newHashSet(service);
-        doReturn(services).when(snap).getServices();
-        doReturn(snap).when(factoriesListener).openSnapshot(anyString());
-
-        return factoriesListener;
-    }
-
-
-}
index 4d232a619a49affd154c46d9fd6aa92ec08592b6..f76bf4f4c37ebf96c99ba0eeccc90c9280f773da 100644 (file)
@@ -24,8 +24,7 @@ import com.google.common.base.Preconditions;
 
 public final class SSLUtil {
 
-    private SSLUtil() {
-    }
+    private SSLUtil() {}
 
     public static SSLContext initializeSecureContext(final String pass, final InputStream ksKeysFile, final InputStream ksTrustFile,
                                                      final String algorithm) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException,
index fa78fa4bd3983c7eee4cb166e54bc5692f0bad54..3b3f71b0ed0f3aad635d88d6b0bb93a3e4229aa3 100644 (file)
@@ -7,8 +7,7 @@
  */
 package org.opendaylight.controller.netconf.monitoring;
 
-import com.google.common.collect.Maps;
-
+import java.util.Collections;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
 import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
@@ -18,36 +17,26 @@ import org.opendaylight.controller.netconf.monitoring.xml.JaxBSerializer;
 import org.opendaylight.controller.netconf.monitoring.xml.model.NetconfState;
 import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import java.util.Map;
-
 public class Get extends AbstractNetconfOperation {
 
     private static final Logger logger = LoggerFactory.getLogger(Get.class);
     private final NetconfMonitoringService netconfMonitor;
 
-    public Get(NetconfMonitoringService netconfMonitor) {
+    public Get(final NetconfMonitoringService netconfMonitor) {
         super(MonitoringConstants.MODULE_NAME);
         this.netconfMonitor = netconfMonitor;
     }
 
-    private Element getPlaceholder(Document innerResult) throws NetconfDocumentedException {
-        try {
-            XmlElement rootElement = null;
-            rootElement = XmlElement.fromDomElementWithExpected(innerResult.getDocumentElement(),
-                    XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.RFC4741_TARGET_NAMESPACE);
-            return rootElement.getOnlyChildElement(XmlNetconfConstants.DATA_KEY).getDomElement();
-        } catch (RuntimeException e) {
-            throw new IllegalArgumentException(String.format(
-                    "Input xml in wrong format, Expecting root element %s with child element %s, but was %s",
-                    XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.DATA_KEY,
-                    XmlUtil.toString(innerResult.getDocumentElement())), e);
-        }
+    private Element getPlaceholder(final Document innerResult)
+            throws NetconfDocumentedException {
+        final XmlElement rootElement = XmlElement.fromDomElementWithExpected(
+                innerResult.getDocumentElement(), XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.RFC4741_TARGET_NAMESPACE);
+        return rootElement.getOnlyChildElement(XmlNetconfConstants.DATA_KEY).getDomElement();
     }
 
     @Override
@@ -61,7 +50,7 @@ public class Get extends AbstractNetconfOperation {
     }
 
     @Override
-    public Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation)
+    public Document handle(final Document requestMessage, final NetconfOperationChainedExecution subsequentOperation)
             throws NetconfDocumentedException {
         if (subsequentOperation.isExecutionTermination()){
             throw new NetconfDocumentedException(String.format("Subsequent netconf operation expected by %s", this),
@@ -71,29 +60,29 @@ public class Get extends AbstractNetconfOperation {
         }
 
         try {
-            Document innerResult = subsequentOperation.execute(requestMessage);
+            final Document innerResult = subsequentOperation.execute(requestMessage);
 
-            NetconfState netconfMonitoring = new NetconfState(netconfMonitor);
+            final NetconfState netconfMonitoring = new NetconfState(netconfMonitor);
             Element monitoringXmlElement = new JaxBSerializer().toXml(netconfMonitoring);
 
             monitoringXmlElement = (Element) innerResult.importNode(monitoringXmlElement, true);
-            Element monitoringXmlElementPlaceholder = getPlaceholder(innerResult);
+            final Element monitoringXmlElementPlaceholder = getPlaceholder(innerResult);
             monitoringXmlElementPlaceholder.appendChild(monitoringXmlElement);
 
             return innerResult;
-        } catch (RuntimeException e) {
-            String errorMessage = "Get operation for netconf-state subtree failed";
+        } catch (final RuntimeException e) {
+            final String errorMessage = "Get operation for netconf-state subtree failed";
             logger.warn(errorMessage, e);
-            Map<String, String> info = Maps.newHashMap();
-            info.put(NetconfDocumentedException.ErrorSeverity.error.toString(), e.getMessage());
+
             throw new NetconfDocumentedException(errorMessage, NetconfDocumentedException.ErrorType.application,
                     NetconfDocumentedException.ErrorTag.operation_failed,
-                    NetconfDocumentedException.ErrorSeverity.error, info);
+                    NetconfDocumentedException.ErrorSeverity.error,
+                    Collections.singletonMap(NetconfDocumentedException.ErrorSeverity.error.toString(), e.getMessage()));
         }
     }
 
     @Override
-    protected Element handle(Document document, XmlElement message, NetconfOperationChainedExecution subsequentOperation)
+    protected Element handle(final Document document, final XmlElement message, final NetconfOperationChainedExecution subsequentOperation)
             throws NetconfDocumentedException {
         throw new UnsupportedOperationException("Never gets called");
     }
index 14c47352a8409d633dca64a01db06759ad79f8f6..9d332c644029ff3c26a2725703e4b348ff046cf0 100644 (file)
@@ -24,7 +24,6 @@ public class NetconfMonitoringActivator implements BundleActivator {
     public void start(final BundleContext context)  {
         monitor = new NetconfMonitoringServiceTracker(context);
         monitor.open();
-
     }
 
     @Override
index 920236b9b67ab0a277a5e166459463bc3ebac562..f99ae54e6dafac6e9ea01f36e85ab46261d9ce67 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.controller.netconf.monitoring.osgi;
 
 import com.google.common.base.Preconditions;
+import java.util.Hashtable;
 import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
 import org.osgi.framework.BundleContext;
@@ -17,43 +18,39 @@ import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.Dictionary;
-import java.util.Hashtable;
-
 public class NetconfMonitoringServiceTracker extends ServiceTracker<NetconfMonitoringService, NetconfMonitoringService> {
 
     private static final Logger logger = LoggerFactory.getLogger(NetconfMonitoringServiceTracker.class);
 
     private ServiceRegistration<NetconfOperationServiceFactory> reg;
 
-    NetconfMonitoringServiceTracker(BundleContext context) {
+    NetconfMonitoringServiceTracker(final BundleContext context) {
         super(context, NetconfMonitoringService.class, null);
     }
 
     @Override
-    public NetconfMonitoringService addingService(ServiceReference<NetconfMonitoringService> reference) {
+    public NetconfMonitoringService addingService(final ServiceReference<NetconfMonitoringService> reference) {
         Preconditions.checkState(reg == null, "Monitoring service was already added");
 
-        NetconfMonitoringService netconfMonitoringService = super.addingService(reference);
+        final NetconfMonitoringService netconfMonitoringService = super.addingService(reference);
 
         final NetconfMonitoringOperationService operationService = new NetconfMonitoringOperationService(
                 netconfMonitoringService);
-        NetconfOperationServiceFactory factory = new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(
+        final NetconfOperationServiceFactory factory = new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(
                 operationService);
 
-        Dictionary<String, ?> props = new Hashtable<>();
-        reg = context.registerService(NetconfOperationServiceFactory.class, factory, props);
+        reg = context.registerService(NetconfOperationServiceFactory.class, factory, new Hashtable<String, Object>());
 
         return netconfMonitoringService;
     }
 
     @Override
-    public void removedService(ServiceReference<NetconfMonitoringService> reference,
-            NetconfMonitoringService netconfMonitoringService) {
+    public void removedService(final ServiceReference<NetconfMonitoringService> reference,
+            final NetconfMonitoringService netconfMonitoringService) {
         if(reg!=null) {
             try {
                 reg.unregister();
-            } catch (Exception e) {
+            } catch (final Exception e) {
                 logger.warn("Ignoring exception while unregistering {}", reg, e);
             }
         }
index 4b07ab090aabfd3727524d255319352747839f4a..962ad17b66c280c5e7fb68cfc279ff30d79c2285 100644 (file)
@@ -18,17 +18,17 @@ import javax.xml.transform.dom.DOMResult;
 
 public class JaxBSerializer {
 
-    public Element toXml(NetconfState monitoringModel) {
-        DOMResult res = null;
+    public Element toXml(final NetconfState monitoringModel) {
+        final DOMResult res;
         try {
-            JAXBContext jaxbContext = JAXBContext.newInstance(NetconfState.class);
-            Marshaller marshaller = jaxbContext.createMarshaller();
+            final JAXBContext jaxbContext = JAXBContext.newInstance(NetconfState.class);
+            final Marshaller marshaller = jaxbContext.createMarshaller();
 
             marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
 
             res = new DOMResult();
             marshaller.marshal(monitoringModel, res);
-        } catch (JAXBException e) {
+        } catch (final JAXBException e) {
            throw new RuntimeException("Unable to serialize netconf state " + monitoringModel, e);
         }
         return ((Document)res.getNode()).getDocumentElement();
index 98bda5833e00a83487d9d356a44f0b55db0e82d9..8f5a1c029d8611b9f75c7b4570fc63002d9f1e18 100644 (file)
@@ -28,15 +28,12 @@ public final class NetconfState {
     private Schemas schemas;
     private Sessions sessions;
 
-    public NetconfState(NetconfMonitoringService monitoringService) {
+    public NetconfState(final NetconfMonitoringService monitoringService) {
         this.sessions = monitoringService.getSessions();
         this.schemas = monitoringService.getSchemas();
     }
 
-    public NetconfState() {
-    }
-
-
+    public NetconfState() {}
 
     @XmlElementWrapper(name="schemas")
     @XmlElement(name="schema")
@@ -44,7 +41,7 @@ public final class NetconfState {
         return Collections2.transform(schemas.getSchema(), new Function<Schema, MonitoringSchema>() {
             @Nullable
             @Override
-            public MonitoringSchema apply(@Nullable Schema input) {
+            public MonitoringSchema apply(@Nullable final Schema input) {
                 return new MonitoringSchema(input);
             }
         });
@@ -56,7 +53,7 @@ public final class NetconfState {
         return Collections2.transform(sessions.getSession(), new Function<Session, MonitoringSession>() {
             @Nullable
             @Override
-            public MonitoringSession apply(@Nullable Session input) {
+            public MonitoringSession apply(@Nullable final Session input) {
                 return new MonitoringSession(input);
             }
         });
diff --git a/opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/GetTest.java b/opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/GetTest.java
new file mode 100644 (file)
index 0000000..5fceac0
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * 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.netconf.monitoring;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.TestCase.fail;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+
+import java.util.Collections;
+import org.hamcrest.CoreMatchers;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
+import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.SchemasBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.SessionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.Schema;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions.Session;
+import org.w3c.dom.Document;
+
+public class GetTest {
+
+    @Mock
+    private NetconfMonitoringService monitor;
+    @Mock
+    private Document request;
+    @Mock
+    private NetconfOperationChainedExecution subsequentOperation;
+    private Document incorrectSubsequentResult;
+    private Document correctSubsequentResult;
+
+    private Get get;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        incorrectSubsequentResult = XmlUtil.readXmlToDocument("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>");
+        correctSubsequentResult = XmlUtil.readXmlToDocument("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><data></data></rpc-reply>");
+
+        doReturn(new SessionsBuilder().setSession(Collections.<Session>emptyList()).build()).when(monitor).getSessions();
+        doReturn(new SchemasBuilder().setSchema(Collections.<Schema>emptyList()).build()).when(monitor).getSchemas();
+        doReturn(false).when(subsequentOperation).isExecutionTermination();
+
+        get = new Get(monitor);
+    }
+
+    @Test
+    public void testHandleNoSubsequent() throws Exception {
+        try {
+            get.handle(null, NetconfOperationChainedExecution.EXECUTION_TERMINATION_POINT);
+        } catch (final NetconfDocumentedException e) {
+            assertNetconfDocumentedEx(e, NetconfDocumentedException.ErrorSeverity.error, NetconfDocumentedException.ErrorTag.operation_failed, NetconfDocumentedException.ErrorType.application);
+            return;
+        }
+
+        fail("Get should fail without subsequent operation");
+    }
+
+    @Test
+    public void testHandleWrongPlaceholder() throws Exception {
+        doReturn(incorrectSubsequentResult).when(subsequentOperation).execute(request);
+        try {
+            get.handle(request, subsequentOperation);
+        } catch (final NetconfDocumentedException e) {
+            assertNetconfDocumentedEx(e, NetconfDocumentedException.ErrorSeverity.error, NetconfDocumentedException.ErrorTag.invalid_value, NetconfDocumentedException.ErrorType.application);
+            return;
+        }
+
+        fail("Get should fail with wrong xml");
+    }
+
+    @Test
+    public void testHandleRuntimeEx() throws Exception {
+        doThrow(RuntimeException.class).when(subsequentOperation).execute(request);
+        try {
+            get.handle(request, subsequentOperation);
+        } catch (final NetconfDocumentedException e) {
+            assertNetconfDocumentedEx(e, NetconfDocumentedException.ErrorSeverity.error, NetconfDocumentedException.ErrorTag.operation_failed, NetconfDocumentedException.ErrorType.application);
+            assertEquals(1, e.getErrorInfo().size());
+            return;
+        }
+
+        fail("Get should fail with wrong xml");
+    }
+
+    @Test
+    public void testSuccessHandle() throws Exception {
+        doReturn(correctSubsequentResult).when(subsequentOperation).execute(request);
+        assertTrue(get.getHandlingPriority().getPriority().get() > HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY.getPriority().get());
+        final Document result = get.handle(request, subsequentOperation);
+        assertThat(XmlUtil.toString(result), CoreMatchers.containsString("sessions"));
+        assertThat(XmlUtil.toString(result), CoreMatchers.containsString("schemas"));
+
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testHandle() throws Exception {
+        get.handle(null, null, null);
+
+    }
+
+    private void assertNetconfDocumentedEx(final NetconfDocumentedException e, final NetconfDocumentedException.ErrorSeverity severity, final NetconfDocumentedException.ErrorTag errorTag, final NetconfDocumentedException.ErrorType type) {
+        assertEquals(severity, e.getErrorSeverity());
+        assertEquals(errorTag, e.getErrorTag());
+        assertEquals(type, e.getErrorType());
+    }
+}
index 02129574da40ec274a22b077614c38653a14770d..d0d587fb84263c02ef99cb0727de1d4c81b28223 100644 (file)
@@ -7,37 +7,40 @@
 */
 package org.opendaylight.controller.netconf.monitoring.xml;
 
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
 import com.google.common.collect.Lists;
+import org.hamcrest.CoreMatchers;
 import org.junit.Test;
 import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
 import org.opendaylight.controller.netconf.monitoring.xml.model.NetconfState;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.DomainName;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Host;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.NetconfTcp;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.Session1;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfSsh;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.Transport;
+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.SchemasBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Sessions;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.SessionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.Schema;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.SchemaKey;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions.Session;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.DateAndTime;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.ZeroBasedCounter32;
-import org.w3c.dom.Element;
-
-import java.util.Date;
-
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
 
 public class JaxBSerializerTest {
 
     @Test
     public void testName() throws Exception {
 
-        NetconfMonitoringService service = new NetconfMonitoringService() {
+        final NetconfMonitoringService service = new NetconfMonitoringService() {
 
             @Override
             public Sessions getSessions() {
@@ -46,19 +49,54 @@ public class JaxBSerializerTest {
 
             @Override
             public Schemas getSchemas() {
-                return new SchemasBuilder().setSchema(Lists.<Schema>newArrayList()).build();
+                return new SchemasBuilder().setSchema(Lists.newArrayList(getMockSchema("id", "v1", Yang.class), getMockSchema("id2", "", Yang.class))).build();
             }
         };
-        NetconfState model = new NetconfState(service);
-        Element xml = new JaxBSerializer().toXml(model);
+        final NetconfState model = new NetconfState(service);
+        final String xml = XmlUtil.toString(new JaxBSerializer().toXml(model));
+
+        assertThat(xml, CoreMatchers.containsString(
+                "<schema>\n" +
+                "<format>yang</format>\n" +
+                "<identifier>id</identifier>\n" +
+                "<location>NETCONF</location>\n" +
+                "<namespace>localhost</namespace>\n" +
+                "<version>v1</version>\n" +
+                "</schema>\n"));
+
+        assertThat(xml, CoreMatchers.containsString(
+                "<session>\n" +
+                "<session-id>1</session-id>\n" +
+                "<in-bad-rpcs>0</in-bad-rpcs>\n" +
+                "<in-rpcs>0</in-rpcs>\n" +
+                "<login-time>loginTime</login-time>\n" +
+                "<out-notifications>0</out-notifications>\n" +
+                "<out-rpc-errors>0</out-rpc-errors>\n" +
+                "<ncme:session-identifier>client</ncme:session-identifier>\n" +
+                "<source-host>address/port</source-host>\n" +
+                "<transport>ncme:netconf-tcp</transport>\n" +
+                "<username>username</username>\n" +
+                "</session>"));
+    }
+
+    private Schema getMockSchema(final String id, final String version, final Class<Yang> format) {
+        final Schema mock = mock(Schema.class);
+
+        doReturn(format).when(mock).getFormat();
+        doReturn(id).when(mock).getIdentifier();
+        doReturn(new Uri("localhost")).when(mock).getNamespace();
+        doReturn(version).when(mock).getVersion();
+        doReturn(Lists.newArrayList(new Schema.Location(Schema.Location.Enumeration.NETCONF))).when(mock).getLocation();
+        doReturn(new SchemaKey(format, id, version)).when(mock).getKey();
+        return mock;
     }
 
-    private Session getMockSession(Class<? extends Transport> transportType) {
-        Session mocked = mock(Session.class);
-        Session1 mockedSession1 = mock(Session1.class);
+    private Session getMockSession(final Class<? extends Transport> transportType) {
+        final Session mocked = mock(Session.class);
+        final Session1 mockedSession1 = mock(Session1.class);
         doReturn("client").when(mockedSession1).getSessionIdentifier();
         doReturn(1L).when(mocked).getSessionId();
-        doReturn(new DateAndTime(new Date().toString())).when(mocked).getLoginTime();
+        doReturn(new DateAndTime("loginTime")).when(mocked).getLoginTime();
         doReturn(new Host(new DomainName("address/port"))).when(mocked).getSourceHost();
         doReturn(new ZeroBasedCounter32(0L)).when(mocked).getInBadRpcs();
         doReturn(new ZeroBasedCounter32(0L)).when(mocked).getInRpcs();
index 13041598d1a149932aa37e6efa8cb6e414decd87..cb8461a29965816320f1de6087e7a13629c4be9e 100644 (file)
       <groupId>org.opendaylight.controller.thirdparty</groupId>
       <artifactId>ganymed</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.sshd</groupId>
+      <artifactId>sshd-core</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.openexi</groupId>
       <artifactId>nagasena</artifactId>
@@ -60,7 +64,6 @@
       <groupId>org.openexi</groupId>
       <artifactId>nagasena-rta</artifactId>
     </dependency>
-
     <dependency>
       <groupId>org.osgi</groupId>
       <artifactId>org.osgi.core</artifactId>
       <groupId>xmlunit</groupId>
       <artifactId>xmlunit</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>mockito-configuration</artifactId>
+    </dependency>
   </dependencies>
 
   <build>
@@ -82,7 +89,7 @@
         <artifactId>maven-bundle-plugin</artifactId>
         <configuration>
           <instructions>
-            <Import-Package>ch.ethz.ssh2, com.google.common.base, com.google.common.collect, io.netty.buffer,
+            <Import-Package>org.apache.sshd.*, ch.ethz.ssh2, com.google.common.base, com.google.common.collect, io.netty.buffer,
               io.netty.channel, io.netty.channel.socket, io.netty.handler.codec, io.netty.handler.ssl, io.netty.util,
               io.netty.util.concurrent, javax.xml.transform, javax.xml.transform.dom, javax.xml.transform.sax,
               javax.xml.transform.stream, org.opendaylight.controller.netconf.api,
index d765ca8b2573702368ca9aca3e65212a8eed1e0a..f39e2c425d039cca549fd574607c52af02eced9e 100644 (file)
@@ -53,8 +53,7 @@ public final class NetconfHelloMessageToXMLEncoder extends NetconfMessageToXMLEn
         Optional<NetconfHelloMessageAdditionalHeader> headerOptional = ((NetconfHelloMessage) msg)
                 .getAdditionalHeader();
 
-        // If additional header present, serialize it along with netconf hello
-        // message
+        // If additional header present, serialize it along with netconf hello message
         if (headerOptional.isPresent()) {
             out.writeBytes(headerOptional.get().toFormattedString().getBytes(Charsets.UTF_8));
         }
index 69c0d53fc12144ad7e780126e5f8d3fe6372a571..bfc8d77e17bc7e4ae799d9b0859bdf3085f5e6af 100644 (file)
@@ -7,26 +7,21 @@
  */
 package org.opendaylight.controller.netconf.nettyutil.handler;
 
-import java.util.List;
-
-import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.annotations.VisibleForTesting;
-
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufInputStream;
 import io.netty.buffer.ByteBufUtil;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.ByteToMessageDecoder;
+import java.util.List;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public final class NetconfXMLToMessageDecoder extends ByteToMessageDecoder {
     private static final Logger LOG = LoggerFactory.getLogger(NetconfXMLToMessageDecoder.class);
 
     @Override
-    @VisibleForTesting
     public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
 
         if (in.readableBytes() != 0) {
index b22b792d52980227d2aa85da39436535a19097b2..0548b1d371a415569dffc1826c02fae4700df45d 100644 (file)
@@ -8,13 +8,15 @@
 
 package org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication;
 
-import ch.ethz.ssh2.Connection;
-
 import java.io.IOException;
+import org.apache.sshd.ClientSession;
 
 /**
  * Class providing authentication facility to SSH handler.
  */
 public abstract class AuthenticationHandler {
-    public abstract void authenticate(Connection connection) throws IOException;
+
+    public abstract String getUsername();
+
+    public abstract org.apache.sshd.client.future.AuthFuture authenticate(final ClientSession session) throws IOException;
 }
index b67aa0f96dcd53a084965fc3766399a26f2a5869..ab94e59a93dcf4e70494f7bf65ba66a28b5915c0 100644 (file)
@@ -8,13 +8,13 @@
 
 package org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication;
 
-import ch.ethz.ssh2.Connection;
-
 import java.io.IOException;
+import org.apache.sshd.ClientSession;
+import org.apache.sshd.client.future.AuthFuture;
 
 /**
  * Class Providing username/password authentication option to
- * {@link org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshHandler}
+ * {@link org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.AsyncSshHandler}
  */
 public class LoginPassword extends AuthenticationHandler {
     private final String username;
@@ -26,11 +26,13 @@ public class LoginPassword extends AuthenticationHandler {
     }
 
     @Override
-    public void authenticate(Connection connection) throws IOException {
-        boolean isAuthenticated = connection.authenticateWithPassword(username, password);
+    public String getUsername() {
+        return username;
+    }
 
-        if (!isAuthenticated) {
-            throw new IOException("Authentication failed.");
-        }
+    @Override
+    public AuthFuture authenticate(final ClientSession session) throws IOException {
+        session.addPasswordIdentity(password);
+        return session.auth();
     }
 }
diff --git a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/AsyncSshHandler.java b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/AsyncSshHandler.java
new file mode 100644 (file)
index 0000000..0d877c9
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * 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.netconf.nettyutil.handler.ssh.client;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelOutboundHandler;
+import io.netty.channel.ChannelOutboundHandlerAdapter;
+import io.netty.channel.ChannelPromise;
+import java.io.IOException;
+import java.net.SocketAddress;
+import org.apache.sshd.ClientChannel;
+import org.apache.sshd.ClientSession;
+import org.apache.sshd.SshClient;
+import org.apache.sshd.client.future.AuthFuture;
+import org.apache.sshd.client.future.ConnectFuture;
+import org.apache.sshd.client.future.OpenFuture;
+import org.apache.sshd.common.future.CloseFuture;
+import org.apache.sshd.common.future.SshFutureListener;
+import org.apache.sshd.common.io.IoInputStream;
+import org.apache.sshd.common.io.IoOutputStream;
+import org.apache.sshd.common.io.IoReadFuture;
+import org.apache.sshd.common.io.IoWriteFuture;
+import org.apache.sshd.common.io.WritePendingException;
+import org.apache.sshd.common.util.Buffer;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Netty SSH handler class. Acts as interface between Netty and SSH library.
+ */
+public class AsyncSshHandler extends ChannelOutboundHandlerAdapter {
+
+    private static final Logger logger = LoggerFactory.getLogger(AsyncSshHandler.class);
+    public static final String SUBSYSTEM = "netconf";
+
+    public static final SshClient DEFAULT_CLIENT = SshClient.setUpDefaultClient();
+
+    public static final int SSH_DEFAULT_NIO_WORKERS = 8;
+
+    static {
+        // TODO make configurable, or somehow reuse netty threadpool
+        DEFAULT_CLIENT.setNioWorkers(SSH_DEFAULT_NIO_WORKERS);
+        DEFAULT_CLIENT.start();
+    }
+
+    private final AuthenticationHandler authenticationHandler;
+    private final SshClient sshClient;
+
+    private SshReadAsyncListener sshReadAsyncListener;
+    private SshWriteAsyncHandler sshWriteAsyncHandler;
+
+    private ClientChannel channel;
+    private ClientSession session;
+    private ChannelPromise connectPromise;
+
+
+    public static AsyncSshHandler createForNetconfSubsystem(final AuthenticationHandler authenticationHandler) throws IOException {
+        return new AsyncSshHandler(authenticationHandler, DEFAULT_CLIENT);
+    }
+
+    /**
+     *
+     * @param authenticationHandler
+     * @param sshClient started SshClient
+     * @throws IOException
+     */
+    public AsyncSshHandler(final AuthenticationHandler authenticationHandler, final SshClient sshClient) throws IOException {
+        this.authenticationHandler = Preconditions.checkNotNull(authenticationHandler);
+        this.sshClient = Preconditions.checkNotNull(sshClient);
+        // Start just in case
+        sshClient.start();
+    }
+
+    private void startSsh(final ChannelHandlerContext ctx, final SocketAddress address) {
+        logger.debug("Starting SSH to {} on channel: {}", address, ctx.channel());
+
+        final ConnectFuture sshConnectionFuture = sshClient.connect(authenticationHandler.getUsername(), address);
+        sshConnectionFuture.addListener(new SshFutureListener<ConnectFuture>() {
+            @Override
+            public void operationComplete(final ConnectFuture future) {
+                if (future.isConnected()) {
+                    handleSshSessionCreated(future, ctx);
+                } else {
+                    handleSshSetupFailure(ctx, future.getException());
+                }
+            }
+        });
+    }
+
+    private synchronized void handleSshSessionCreated(final ConnectFuture future, final ChannelHandlerContext ctx) {
+        try {
+            logger.trace("SSH session created on channel: {}", ctx.channel());
+
+            session = future.getSession();
+            final AuthFuture authenticateFuture = authenticationHandler.authenticate(session);
+            authenticateFuture.addListener(new SshFutureListener<AuthFuture>() {
+                @Override
+                public void operationComplete(final AuthFuture future) {
+                    if (future.isSuccess()) {
+                        handleSshAuthenticated(session, ctx);
+                    } else {
+                        handleSshSetupFailure(ctx, future.getException());
+                    }
+                }
+            });
+        } catch (final IOException e) {
+            handleSshSetupFailure(ctx, e);
+        }
+    }
+
+    private synchronized void handleSshAuthenticated(final ClientSession session, final ChannelHandlerContext ctx) {
+        try {
+            logger.debug("SSH session authenticated on channel: {}, server version: {}", ctx.channel(), session.getServerVersion());
+
+            channel = session.createSubsystemChannel(SUBSYSTEM);
+            channel.setStreaming(ClientChannel.Streaming.Async);
+            channel.open().addListener(new SshFutureListener<OpenFuture>() {
+                @Override
+                public void operationComplete(final OpenFuture future) {
+                    if(future.isOpened()) {
+                        handleSshChanelOpened(ctx);
+                    } else {
+                        handleSshSetupFailure(ctx, future.getException());
+                    }
+                }
+            });
+
+
+        } catch (final IOException e) {
+            handleSshSetupFailure(ctx, e);
+        }
+    }
+
+    private synchronized void handleSshChanelOpened(final ChannelHandlerContext ctx) {
+        logger.trace("SSH subsystem channel opened successfully on channel: {}", ctx.channel());
+
+        connectPromise.setSuccess();
+        connectPromise = null;
+
+        sshReadAsyncListener = new SshReadAsyncListener(this, ctx, channel.getAsyncOut());
+        sshWriteAsyncHandler = new SshWriteAsyncHandler(this, channel.getAsyncIn());
+
+        ctx.fireChannelActive();
+    }
+
+    private synchronized void handleSshSetupFailure(final ChannelHandlerContext ctx, final Throwable e) {
+        logger.warn("Unable to setup SSH connection on channel: {}", ctx.channel(), e);
+        connectPromise.setFailure(e);
+        connectPromise = null;
+        throw new IllegalStateException("Unable to setup SSH connection on channel: " + ctx.channel(), e);
+    }
+
+    @Override
+    public synchronized void write(final ChannelHandlerContext ctx, final Object msg, final ChannelPromise promise) {
+        sshWriteAsyncHandler.write(ctx, msg, promise);
+    }
+
+    @Override
+    public synchronized void connect(final ChannelHandlerContext ctx, final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) throws Exception {
+        this.connectPromise = promise;
+        startSsh(ctx, remoteAddress);
+    }
+
+    @Override
+    public void close(final ChannelHandlerContext ctx, final ChannelPromise promise) throws Exception {
+        disconnect(ctx, promise);
+    }
+
+    @Override
+    public synchronized void disconnect(final ChannelHandlerContext ctx, final ChannelPromise promise) {
+        if(sshReadAsyncListener != null) {
+            sshReadAsyncListener.close();
+        }
+
+        if(sshWriteAsyncHandler != null) {
+            sshWriteAsyncHandler.close();
+        }
+
+        if(session!= null && !session.isClosed() && !session.isClosing()) {
+            session.close(false).addListener(new SshFutureListener<CloseFuture>() {
+                @Override
+                public void operationComplete(final CloseFuture future) {
+                    if (future.isClosed() == false) {
+                        session.close(true);
+                    }
+                    session = null;
+                }
+            });
+        }
+
+        channel = null;
+        promise.setSuccess();
+
+        logger.debug("SSH session closed on channel: {}", ctx.channel());
+        ctx.fireChannelInactive();
+    }
+
+    /**
+     * Listener over async input stream from SSH session.
+     * This listeners schedules reads in a loop until the session is closed or read fails.
+     */
+    private static class SshReadAsyncListener implements SshFutureListener<IoReadFuture>, AutoCloseable {
+        private static final int BUFFER_SIZE = 8192;
+
+        private final ChannelOutboundHandler asyncSshHandler;
+        private final ChannelHandlerContext ctx;
+
+        private IoInputStream asyncOut;
+        private Buffer buf;
+        private IoReadFuture currentReadFuture;
+
+        public SshReadAsyncListener(final ChannelOutboundHandler asyncSshHandler, final ChannelHandlerContext ctx, final IoInputStream asyncOut) {
+            this.asyncSshHandler = asyncSshHandler;
+            this.ctx = ctx;
+            this.asyncOut = asyncOut;
+            buf = new Buffer(BUFFER_SIZE);
+            asyncOut.read(buf).addListener(this);
+        }
+
+        @Override
+        public synchronized void operationComplete(final IoReadFuture future) {
+            if(future.getException() != null) {
+
+                if(asyncOut.isClosed() || asyncOut.isClosing()) {
+
+                    // Ssh dropped
+                    logger.debug("Ssh session dropped on channel: {}", ctx.channel(), future.getException());
+                    invokeDisconnect();
+                    return;
+                } else {
+                    logger.warn("Exception while reading from SSH remote on channel {}", ctx.channel(), future.getException());
+                    invokeDisconnect();
+                }
+            }
+
+            if (future.getRead() > 0) {
+                ctx.fireChannelRead(Unpooled.wrappedBuffer(buf.array(), 0, future.getRead()));
+
+                // Schedule next read
+                buf = new Buffer(BUFFER_SIZE);
+                currentReadFuture = asyncOut.read(buf);
+                currentReadFuture.addListener(this);
+            }
+        }
+
+        private void invokeDisconnect() {
+            try {
+                asyncSshHandler.disconnect(ctx, ctx.newPromise());
+            } catch (final Exception e) {
+                // This should not happen
+                throw new IllegalStateException(e);
+            }
+        }
+
+        @Override
+        public synchronized void close() {
+            // Remove self as listener on close to prevent reading from closed input
+            if(currentReadFuture != null) {
+                currentReadFuture.removeListener(this);
+            }
+
+            asyncOut = null;
+        }
+    }
+
+    private static final class SshWriteAsyncHandler implements AutoCloseable {
+        public static final int MAX_PENDING_WRITES = 100;
+
+        private final ChannelOutboundHandler channelHandler;
+        private IoOutputStream asyncIn;
+
+        // Counter that holds the amount of pending write messages
+        // Pending write can occur in case remote window is full
+        // In such case, we need to wait for the pending write to finish
+        private int pendingWriteCounter;
+        // Last write future, that can be pending
+        private IoWriteFuture lastWriteFuture;
+
+        public SshWriteAsyncHandler(final ChannelOutboundHandler channelHandler, final IoOutputStream asyncIn) {
+            this.channelHandler = channelHandler;
+            this.asyncIn = asyncIn;
+        }
+
+        int c = 0;
+
+        public synchronized void write(final ChannelHandlerContext ctx, final Object msg, final ChannelPromise promise) {
+            try {
+                if(asyncIn == null || asyncIn.isClosed() || asyncIn.isClosing()) {
+                    // If we are closed/closing, set immediate fail
+                    promise.setFailure(new IllegalStateException("Channel closed"));
+                } else {
+                    lastWriteFuture = asyncIn.write(toBuffer(msg));
+                    lastWriteFuture.addListener(new SshFutureListener<IoWriteFuture>() {
+
+                        @Override
+                        public void operationComplete(final IoWriteFuture future) {
+                            ((ByteBuf) msg).release();
+
+                            // Notify success or failure
+                            if (future.isWritten()) {
+                                promise.setSuccess();
+                            } else {
+                                promise.setFailure(future.getException());
+                            }
+
+                            // Reset last pending future
+                            synchronized (SshWriteAsyncHandler.this) {
+                                lastWriteFuture = null;
+                            }
+                        }
+                    });
+                }
+            } catch (final WritePendingException e) {
+                // Check limit for pending writes
+                pendingWriteCounter++;
+                if(pendingWriteCounter > MAX_PENDING_WRITES) {
+                    handlePendingFailed(ctx, new IllegalStateException("Too much pending writes(" + MAX_PENDING_WRITES + ") on channel: " + ctx.channel() +
+                            ", remote window is not getting read or is too small"));
+                }
+
+                logger.debug("Write pending to SSH remote on channel: {}, current pending count: {}", ctx.channel(), pendingWriteCounter);
+
+                // In case of pending, re-invoke write after pending is finished
+                lastWriteFuture.addListener(new SshFutureListener<IoWriteFuture>() {
+                    @Override
+                    public void operationComplete(final IoWriteFuture future) {
+                        if (future.isWritten()) {
+                            synchronized (SshWriteAsyncHandler.this) {
+                                // Pending done, decrease counter
+                                pendingWriteCounter--;
+                            }
+                            write(ctx, msg, promise);
+                        } else {
+                            // Cannot reschedule pending, fail
+                            handlePendingFailed(ctx, e);
+                        }
+                    }
+
+                });
+            }
+        }
+
+        private void handlePendingFailed(final ChannelHandlerContext ctx, final Exception e) {
+            logger.warn("Exception while writing to SSH remote on channel {}", ctx.channel(), e);
+            try {
+                channelHandler.disconnect(ctx, ctx.newPromise());
+            } catch (final Exception ex) {
+                // This should not happen
+                throw new IllegalStateException(ex);
+            }
+        }
+
+        @Override
+        public void close() {
+            asyncIn = null;
+        }
+
+        private Buffer toBuffer(final Object msg) {
+            // TODO Buffer vs ByteBuf translate, Can we handle that better ?
+            Preconditions.checkState(msg instanceof ByteBuf);
+            final ByteBuf byteBuf = (ByteBuf) msg;
+            final byte[] temp = new byte[byteBuf.readableBytes()];
+            byteBuf.readBytes(temp, 0, byteBuf.readableBytes());
+            return new Buffer(temp);
+        }
+
+    }
+}
diff --git a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/Invoker.java b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/Invoker.java
deleted file mode 100644 (file)
index eab2546..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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
- */
-package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
-
-import java.io.IOException;
-
-/**
- * Abstract class providing mechanism of invoking various SSH level services.
- * Class is not allowed to be extended, as it provides its own implementations via instance initiators.
- */
-abstract class Invoker {
-    private boolean invoked = false;
-
-    private Invoker() {
-    }
-
-    protected boolean isInvoked() {
-        return invoked;
-    }
-
-    public void setInvoked() {
-        this.invoked = true;
-    }
-
-    abstract void invoke(SshSession session) throws IOException;
-
-    public static Invoker netconfSubsystem(){
-        return subsystem("netconf");
-    }
-
-    public static Invoker subsystem(final String subsystem) {
-        return new Invoker() {
-            @Override
-            synchronized void invoke(SshSession session) throws IOException {
-                if (isInvoked()) {
-                    throw new IllegalStateException("Already invoked.");
-                }
-                try {
-                    session.startSubSystem(subsystem);
-                } finally {
-                    setInvoked();
-                }
-            }
-        };
-    }
-}
diff --git a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshClient.java b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshClient.java
deleted file mode 100644 (file)
index 271b781..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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
- */
-
-package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
-
-import ch.ethz.ssh2.Connection;
-import ch.ethz.ssh2.Session;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.VirtualSocket;
-
-/**
- * Wrapper class around GANYMED SSH java library.
- */
-class SshClient {
-    private final VirtualSocket socket;
-    private final Map<Integer, SshSession> openSessions = new HashMap<>();
-    private final AuthenticationHandler authenticationHandler;
-    private Connection connection;
-
-    public SshClient(VirtualSocket socket, AuthenticationHandler authenticationHandler) throws IOException {
-        this.socket = socket;
-        this.authenticationHandler = authenticationHandler;
-    }
-
-    public SshSession openSession() throws IOException {
-        if (connection == null) {
-            connect();
-        }
-
-        Session session = connection.openSession();
-        SshSession sshSession = new SshSession(session);
-        openSessions.put(openSessions.size(), sshSession);
-
-        return sshSession;
-    }
-
-    private void connect() throws IOException {
-        connection = new Connection(socket);
-
-        connection.connect();
-        authenticationHandler.authenticate(connection);
-    }
-
-
-    public void close() {
-        for (SshSession session : openSessions.values()){
-            session.close();
-        }
-
-        openSessions.clear();
-
-        if (connection != null) {
-            connection.close();
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "SshClient{" +
-                "socket=" + socket +
-                '}';
-    }
-}
diff --git a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshClientAdapter.java b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshClientAdapter.java
deleted file mode 100644 (file)
index 4ca7bdf..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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
- */
-
-package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
-import io.netty.channel.ChannelFuture;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelPromise;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.LinkedList;
-import java.util.Queue;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-/**
- * Worker thread class. Handles all downstream and upstream events in SSH Netty
- * pipeline.
- */
-class SshClientAdapter implements Runnable {
-    private static final Logger logger = LoggerFactory.getLogger(SshClientAdapter.class);
-
-    private static final int BUFFER_SIZE = 1024;
-
-    private final SshClient sshClient;
-    private final Invoker invoker;
-
-    private OutputStream stdIn;
-
-    private final Queue<ByteBuf> postponed = new LinkedList<>();
-
-    private ChannelHandlerContext ctx;
-    private ChannelPromise disconnectPromise;
-
-    private final AtomicBoolean stopRequested = new AtomicBoolean(false);
-
-    private final Object lock = new Object();
-
-    public SshClientAdapter(final SshClient sshClient, final Invoker invoker) {
-        this.sshClient = sshClient;
-        this.invoker = invoker;
-    }
-
-    // TODO ganymed spawns a Thread that receives the data from remote inside TransportManager
-    // Get rid of this thread and reuse Ganymed internal thread (not sure if its possible without modifications in ganymed)
-    public void run() {
-        try {
-            final SshSession session = sshClient.openSession();
-            invoker.invoke(session);
-            final InputStream stdOut = session.getStdout();
-
-            synchronized (lock) {
-                stdIn = session.getStdin();
-                while (postponed.peek() != null) {
-                    writeImpl(postponed.poll());
-                }
-            }
-
-            while (!stopRequested.get()) {
-                final byte[] readBuff = new byte[BUFFER_SIZE];
-                final int c = stdOut.read(readBuff);
-                if (c == -1) {
-                    continue;
-                }
-
-                ctx.fireChannelRead(Unpooled.copiedBuffer(readBuff, 0, c));
-            }
-        } catch (final Exception e) {
-            logger.error("Unexpected exception", e);
-        } finally {
-            sshClient.close();
-
-            synchronized (lock) {
-                if (disconnectPromise != null) {
-                    ctx.disconnect(disconnectPromise);
-                }
-            }
-        }
-    }
-
-    // TODO: needs rework to match netconf framer API.
-    public void write(final ByteBuf message) throws IOException {
-        synchronized (lock) {
-            if (stdIn == null) {
-                postponed.add(message);
-                return;
-            }
-            writeImpl(message);
-        }
-    }
-
-    private void writeImpl(final ByteBuf message) throws IOException {
-        message.getBytes(0, stdIn, message.readableBytes());
-        message.release();
-        stdIn.flush();
-    }
-
-    public void stop(final ChannelPromise promise) {
-        synchronized (lock) {
-            stopRequested.set(true);
-            disconnectPromise = promise;
-        }
-    }
-
-    public Thread start(final ChannelHandlerContext ctx, final ChannelFuture channelFuture) {
-        checkArgument(channelFuture.isSuccess());
-        checkNotNull(ctx.channel().remoteAddress());
-        synchronized (this) {
-            checkState(this.ctx == null);
-            this.ctx = ctx;
-        }
-        final String threadName = toString();
-        final Thread thread = new Thread(this, threadName);
-        thread.start();
-        return thread;
-    }
-
-    @Override
-    public String toString() {
-        return "SshClientAdapter{" +
-                "sshClient=" + sshClient +
-                '}';
-    }
-}
diff --git a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshHandler.java b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshHandler.java
deleted file mode 100644 (file)
index c710a01..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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
- */
-
-package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelFuture;
-import io.netty.channel.ChannelFutureListener;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelOutboundHandlerAdapter;
-import io.netty.channel.ChannelPromise;
-import java.io.IOException;
-import java.net.SocketAddress;
-import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.VirtualSocket;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Netty SSH handler class. Acts as interface between Netty and SSH library. All standard Netty message handling
- * stops at instance of this class. All downstream events are handed of to wrapped {@link org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshClientAdapter};
- */
-public class SshHandler extends ChannelOutboundHandlerAdapter {
-    private static final Logger logger = LoggerFactory.getLogger(SshHandler.class);
-    private static final String SOCKET = "socket";
-
-    private final VirtualSocket virtualSocket = new VirtualSocket();
-    private final SshClientAdapter sshClientAdapter;
-
-
-    public static SshHandler createForNetconfSubsystem(AuthenticationHandler authenticationHandler) throws IOException {
-        return new SshHandler(authenticationHandler, Invoker.netconfSubsystem());
-    }
-
-
-    public SshHandler(AuthenticationHandler authenticationHandler, Invoker invoker) throws IOException {
-        SshClient sshClient = new SshClient(virtualSocket, authenticationHandler);
-        this.sshClientAdapter = new SshClientAdapter(sshClient, invoker);
-    }
-
-    @Override
-    public void handlerAdded(ChannelHandlerContext ctx){
-        if (ctx.channel().pipeline().get(SOCKET) == null) {
-            ctx.channel().pipeline().addFirst(SOCKET, virtualSocket);
-        }
-    }
-
-    @Override
-    public void handlerRemoved(ChannelHandlerContext ctx) {
-        if (ctx.channel().pipeline().get(SOCKET) != null) {
-            ctx.channel().pipeline().remove(SOCKET);
-        }
-    }
-
-    @Override
-    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws IOException {
-        this.sshClientAdapter.write((ByteBuf) msg);
-    }
-
-    @Override
-    public void connect(final ChannelHandlerContext ctx,
-                        SocketAddress remoteAddress,
-                        SocketAddress localAddress,
-                        ChannelPromise promise) {
-        ctx.connect(remoteAddress, localAddress, promise);
-
-        promise.addListener(new ChannelFutureListener() {
-            public void operationComplete(ChannelFuture channelFuture) {
-                if (channelFuture.isSuccess()) {
-                    sshClientAdapter.start(ctx, channelFuture);
-                } else {
-                    logger.debug("Failed to connect to remote host");
-                }
-            }}
-        );
-    }
-
-    @Override
-    public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) {
-        sshClientAdapter.stop(promise);
-    }
-}
diff --git a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshSession.java b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshSession.java
deleted file mode 100644 (file)
index 9cdc592..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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
- */
-
-package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
-
-import ch.ethz.ssh2.Session;
-import ch.ethz.ssh2.channel.Channel;
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Wrapper class for proprietary SSH sessions implementations
- */
-class SshSession implements Closeable {
-    private final Session session;
-
-    public SshSession(final Session session) {
-        this.session = session;
-    }
-
-    public void startSubSystem(final String name) throws IOException {
-        session.startSubSystem(name);
-    }
-
-    public InputStream getStdout() {
-        return session.getStdout();
-    }
-
-    // FIXME according to http://www.ganymed.ethz.ch/ssh2/FAQ.html#blocking you should read data from both stdout and stderr to prevent window filling up (since stdout and stderr share a window)
-    // FIXME stdErr is not used anywhere
-    public InputStream getStderr() {
-        return session.getStderr();
-    }
-
-    public OutputStream getStdin() {
-        return session.getStdin();
-    }
-
-    @Override
-    public void close() {
-        if (session.getState() == Channel.STATE_OPEN || session.getState() == Channel.STATE_OPENING) {
-            session.close();
-        }
-    }
-}
diff --git a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/virtualsocket/ChannelInputStream.java b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/virtualsocket/ChannelInputStream.java
deleted file mode 100644 (file)
index ba65b9e..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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
- */
-
-package org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelInboundHandler;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Class provides {@link InputStream} functionality to users of virtual socket.
- */
-public class ChannelInputStream extends InputStream implements ChannelInboundHandler {
-    private final Object lock = new Object();
-    private final ByteBuf bb = Unpooled.buffer();
-
-    @Override
-    public int read(byte b[], int off, int len) throws IOException {
-        if (b == null) {
-            throw new NullPointerException();
-        } else if (off < 0 || len < 0 || len > b.length - off) {
-            throw new IndexOutOfBoundsException();
-        } else if (len == 0) {
-            return 0;
-        }
-
-        int bytesRead = 1;
-        synchronized (lock) {
-            int c = read();
-
-            b[off] = (byte)c;
-
-            if(this.bb.readableBytes() == 0) {
-                return bytesRead;
-            }
-
-            int ltr = len-1;
-            ltr = (ltr <= bb.readableBytes()) ? ltr : bb.readableBytes();
-
-            bb.readBytes(b, 1, ltr);
-            bytesRead += ltr;
-        }
-        return bytesRead;
-    }
-
-    @Override
-    public int read() throws IOException {
-        synchronized (lock) {
-            while (this.bb.readableBytes() == 0) {
-                try {
-                    lock.wait();
-                } catch (InterruptedException e) {
-                    Thread.currentThread().interrupt();
-                    throw new IllegalStateException(e);
-                }
-            }
-            return this.bb.readByte() & 0xFF;
-        }
-    }
-
-    @Override
-    public int available() throws IOException {
-        synchronized (lock) {
-            return this.bb.readableBytes();
-        }
-    }
-
-    public void channelRegistered(ChannelHandlerContext ctx) {
-        ctx.fireChannelRegistered();
-    }
-
-    public void channelUnregistered(ChannelHandlerContext ctx) {
-        ctx.fireChannelUnregistered();
-    }
-
-    public void channelActive(ChannelHandlerContext ctx) {
-        ctx.fireChannelActive();
-    }
-
-    public void channelInactive(ChannelHandlerContext ctx) {
-        ctx.fireChannelInactive();
-    }
-
-    public void channelRead(ChannelHandlerContext ctx, Object o) {
-        synchronized(lock) {
-            this.bb.discardReadBytes();
-            this.bb.writeBytes((ByteBuf) o);
-            ((ByteBuf) o).release();
-            lock.notifyAll();
-        }
-    }
-
-    public void channelReadComplete(ChannelHandlerContext ctx) {
-        ctx.fireChannelReadComplete();
-    }
-
-    public void userEventTriggered(ChannelHandlerContext ctx, Object o) {
-        ctx.fireUserEventTriggered(o);
-    }
-
-    public void channelWritabilityChanged(ChannelHandlerContext ctx) {
-        ctx.fireChannelWritabilityChanged();
-    }
-
-    public void handlerAdded(ChannelHandlerContext ctx) {
-    }
-
-    public void handlerRemoved(ChannelHandlerContext ctx) {
-    }
-
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) {
-        ctx.fireExceptionCaught(throwable);
-    }
-}
-
diff --git a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/virtualsocket/ChannelOutputStream.java b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/virtualsocket/ChannelOutputStream.java
deleted file mode 100644 (file)
index 2dc5235..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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
- */
-
-package org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelOutboundHandler;
-import io.netty.channel.ChannelPromise;
-
-import java.io.OutputStream;
-import java.net.SocketAddress;
-
-/**
- * Class provides {@link OutputStream) functionality to users of virtual socket.
- */
-public class ChannelOutputStream extends OutputStream implements ChannelOutboundHandler {
-    private final Object lock = new Object();
-    private ByteBuf buff = Unpooled.buffer();
-    private ChannelHandlerContext ctx;
-
-    @Override
-    public void flush() {
-        synchronized(lock) {
-            ctx.writeAndFlush(buff).awaitUninterruptibly();
-            buff = Unpooled.buffer();
-        }
-    }
-
-    @Override
-    public void write(int b) {
-        synchronized(lock) {
-            buff.writeByte(b);
-        }
-    }
-
-    public void bind(ChannelHandlerContext ctx, SocketAddress localAddress,
-                     ChannelPromise promise) {
-        ctx.bind(localAddress, promise);
-    }
-
-    public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress,
-                        SocketAddress localAddress, ChannelPromise promise) {
-        this.ctx = ctx;
-        ctx.connect(remoteAddress, localAddress, promise);
-    }
-
-    public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) {
-        ctx.disconnect(promise);
-    }
-
-    public void close(ChannelHandlerContext ctx, ChannelPromise promise) {
-        ctx.close(promise);
-    }
-
-    public void deregister(ChannelHandlerContext ctx, ChannelPromise channelPromise) {
-        ctx.deregister(channelPromise);
-    }
-
-    public void read(ChannelHandlerContext ctx) {
-        ctx.read();
-    }
-
-    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
-        // pass
-    }
-
-    public void flush(ChannelHandlerContext ctx) {
-        // pass
-    }
-
-    public void handlerAdded(ChannelHandlerContext ctx)
-            throws Exception {
-    }
-
-    public void handlerRemoved(ChannelHandlerContext ctx)
-            throws Exception {
-    }
-
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
-        ctx.fireExceptionCaught(cause);
-    }
-}
diff --git a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/virtualsocket/VirtualSocket.java b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/virtualsocket/VirtualSocket.java
deleted file mode 100644 (file)
index 69cce80..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * 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
- */
-
-package org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket;
-
-import io.netty.channel.ChannelHandler;
-import io.netty.channel.ChannelHandlerContext;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.net.SocketException;
-import java.nio.channels.SocketChannel;
-
-/**
- * Handler class providing Socket functionality to OIO client application. By using VirtualSocket user can
- * use OIO application in asynchronous environment and NIO EventLoop. Using VirtualSocket OIO applications
- * are able to use full potential of NIO environment.
- */
-//TODO: refactor - socket should be created when connection is established
-public class VirtualSocket extends Socket implements ChannelHandler {
-    private static final String INPUT_STREAM = "inputStream";
-    private static final String OUTPUT_STREAM = "outputStream";
-
-    private final ChannelInputStream chais = new ChannelInputStream();
-    private final ChannelOutputStream chaos = new ChannelOutputStream();
-    private ChannelHandlerContext ctx;
-
-
-    public InputStream getInputStream() {
-        return this.chais;
-    }
-
-    public OutputStream getOutputStream() {
-        return this.chaos;
-    }
-
-    public void handlerAdded(ChannelHandlerContext ctx) {
-        this.ctx = ctx;
-
-        if (ctx.channel().pipeline().get(OUTPUT_STREAM) == null) {
-            ctx.channel().pipeline().addFirst(OUTPUT_STREAM, chaos);
-        }
-
-        if (ctx.channel().pipeline().get(INPUT_STREAM) == null) {
-            ctx.channel().pipeline().addFirst(INPUT_STREAM, chais);
-        }
-    }
-
-    public void handlerRemoved(ChannelHandlerContext ctx) {
-        if (ctx.channel().pipeline().get(OUTPUT_STREAM) != null) {
-            ctx.channel().pipeline().remove(OUTPUT_STREAM);
-        }
-
-        if (ctx.channel().pipeline().get(INPUT_STREAM) != null) {
-            ctx.channel().pipeline().remove(INPUT_STREAM);
-        }
-    }
-
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) {
-        // TODO exceptionCaught is deprecated transform this handler
-        ctx.fireExceptionCaught(throwable);
-    }
-
-
-    @Override
-    public void connect(SocketAddress endpoint) throws IOException {}
-
-    @Override
-    public void connect(SocketAddress endpoint, int timeout) throws IOException {}
-
-    @Override
-    public void bind(SocketAddress bindpoint) throws IOException {}
-
-    @Override
-    public InetAddress getInetAddress() {
-        InetSocketAddress isa = getInetSocketAddress();
-        return isa.getAddress();
-    }
-
-    @Override
-    public InetAddress getLocalAddress() {return null;}
-
-    @Override
-    public int getPort() {
-        return getInetSocketAddress().getPort();
-    }
-
-    private InetSocketAddress getInetSocketAddress() {
-        return (InetSocketAddress)getRemoteSocketAddress();
-    }
-
-    @Override
-    public int getLocalPort() {return -1;}
-
-    @Override
-    public SocketAddress getRemoteSocketAddress() {
-        return this.ctx.channel().remoteAddress();
-    }
-
-    @Override
-    public SocketAddress getLocalSocketAddress() {
-        return this.ctx.channel().localAddress();
-    }
-
-    @Override
-    public SocketChannel getChannel() {return null;}
-
-    @Override
-    public void setTcpNoDelay(boolean on) throws SocketException {}
-
-    @Override
-    public boolean getTcpNoDelay() throws SocketException {return false;}
-
-    @Override
-    public void setSoLinger(boolean on, int linger) throws SocketException {}
-
-    @Override
-    public int getSoLinger() throws SocketException {return -1;}
-
-    @Override
-    public void sendUrgentData(int data) throws IOException {}
-
-    @Override
-    public void setOOBInline(boolean on) throws SocketException {}
-
-    @Override
-    public boolean getOOBInline() throws SocketException {return false;}
-
-    @Override
-    public synchronized void setSoTimeout(int timeout) throws SocketException {}
-
-    @Override
-    public synchronized int getSoTimeout() throws SocketException {return -1;}
-
-    @Override
-    public synchronized void setSendBufferSize(int size) throws SocketException {}
-
-    @Override
-    public synchronized int getSendBufferSize() throws SocketException {return -1;}
-
-    @Override
-    public synchronized void setReceiveBufferSize(int size) throws SocketException {}
-
-    @Override
-    public synchronized int getReceiveBufferSize() throws SocketException {return -1;}
-
-    @Override
-    public void setKeepAlive(boolean on) throws SocketException {}
-
-    @Override
-    public boolean getKeepAlive() throws SocketException {return false;}
-
-    @Override
-    public void setTrafficClass(int tc) throws SocketException {}
-
-    @Override
-    public int getTrafficClass() throws SocketException {return -1;}
-
-    @Override
-    public void setReuseAddress(boolean on) throws SocketException {}
-
-    @Override
-    public boolean getReuseAddress() throws SocketException {return false;}
-
-    @Override
-    public synchronized void close() throws IOException {}
-
-    @Override
-    public void shutdownInput() throws IOException {}
-
-    @Override
-    public void shutdownOutput() throws IOException {}
-
-    @Override
-    public String toString() {
-        return "VirtualSocket{" + getInetAddress() + ":" + getPort() + "}";
-    }
-
-    @Override
-    public boolean isConnected() {return false;}
-
-    @Override
-    public boolean isBound() {return false;}
-
-    @Override
-    public boolean isClosed() {return false;}
-
-    @Override
-    public boolean isInputShutdown() {return false;}
-
-    @Override
-    public boolean isOutputShutdown() {return false;}
-
-    @Override
-    public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {}
-}
diff --git a/opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/ChunkedFramingMechanismEncoderTest.java b/opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/ChunkedFramingMechanismEncoderTest.java
new file mode 100644 (file)
index 0000000..9347512
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.nettyutil.handler;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Mockito.doAnswer;
+
+import com.google.common.collect.Lists;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandlerContext;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
+
+public class ChunkedFramingMechanismEncoderTest {
+
+    private int chunkSize;
+    @Mock
+    private ChannelHandlerContext ctx;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        chunkSize = 256;
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testIllegalSize() throws Exception {
+        new ChunkedFramingMechanismEncoder(10);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testIllegalSizeMax() throws Exception {
+        new ChunkedFramingMechanismEncoder(Integer.MAX_VALUE);
+    }
+
+    @Test
+    public void testEncode() throws Exception {
+        final List<ByteBuf> chunks = Lists.newArrayList();
+        doAnswer(new Answer() {
+            @Override
+            public Object answer(final InvocationOnMock invocation) throws Throwable {
+                chunks.add((ByteBuf) invocation.getArguments()[0]);
+                return null;
+            }
+        }).when(ctx).write(anyObject());
+
+        final ChunkedFramingMechanismEncoder encoder = new ChunkedFramingMechanismEncoder(chunkSize);
+        final int lastChunkSize = 20;
+        final ByteBuf src = Unpooled.wrappedBuffer(getByteArray(chunkSize * 4 + lastChunkSize));
+        final ByteBuf destination = Unpooled.buffer();
+        encoder.encode(ctx, src, destination);
+        assertEquals(4, chunks.size());
+
+        final int framingSize = "#256\n".getBytes().length + 1/* new line at end */;
+
+        for (final ByteBuf chunk : chunks) {
+            assertEquals(chunkSize + framingSize, chunk.readableBytes());
+        }
+
+        final int lastFramingSize = "#20\n".length() + NetconfMessageConstants.END_OF_CHUNK.length + 1/* new line at end */;
+        assertEquals(lastChunkSize + lastFramingSize, destination.readableBytes());
+    }
+
+    private byte[] getByteArray(final int size) {
+        final byte[] bytes = new byte[size];
+        for (int i = 0; i < size; i++) {
+            bytes[i] = 'a';
+        }
+        return bytes;
+    }
+}
diff --git a/opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/EOMFramingMechanismEncoderTest.java b/opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/EOMFramingMechanismEncoderTest.java
new file mode 100644 (file)
index 0000000..158f3a8
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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.netconf.nettyutil.handler;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.junit.Test;
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
+
+public class EOMFramingMechanismEncoderTest {
+
+    @Test
+    public void testEncode() throws Exception {
+        final byte[] content = new byte[50];
+        final ByteBuf source = Unpooled.wrappedBuffer(content);
+        final ByteBuf destination = Unpooled.buffer();
+        new EOMFramingMechanismEncoder().encode(null, source, destination);
+
+        assertEquals(Unpooled.wrappedBuffer(source.array(), NetconfMessageConstants.END_OF_MESSAGE), destination);
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/FramingMechanismHandlerFactoryTest.java b/opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/FramingMechanismHandlerFactoryTest.java
new file mode 100644 (file)
index 0000000..4f123f0
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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.netconf.nettyutil.handler;
+
+import org.hamcrest.CoreMatchers;
+import org.hamcrest.MatcherAssert;
+import org.junit.Test;
+import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
+
+public class FramingMechanismHandlerFactoryTest {
+
+    @Test
+    public void testCreate() throws Exception {
+        MatcherAssert.assertThat(FramingMechanismHandlerFactory
+                .createHandler(FramingMechanism.CHUNK), CoreMatchers
+                .instanceOf(ChunkedFramingMechanismEncoder.class));
+        MatcherAssert.assertThat(FramingMechanismHandlerFactory
+                .createHandler(FramingMechanism.EOM), CoreMatchers
+                .instanceOf(EOMFramingMechanismEncoder.class));
+    }
+}
\ No newline at end of file
index e088859e82a628a1fa166def6ae743f58e2d0045..a647b9ee172f44fc9e15baf7a284368ab00a8b19 100644 (file)
@@ -7,16 +7,16 @@
  */
 package org.opendaylight.controller.netconf.nettyutil.handler;
 
+import static org.junit.Assert.assertEquals;
+
 import com.google.common.base.Charsets;
 import com.google.common.collect.Lists;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
-import junit.framework.Assert;
+import java.util.List;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import java.util.List;
-
 public class NetconfChunkAggregatorTest {
 
     private static final String CHUNKED_MESSAGE = "\n#4\n" +
@@ -45,26 +45,26 @@ public class NetconfChunkAggregatorTest {
 
     @Test
     public void testMultipleChunks() throws Exception {
-        List<Object> output = Lists.newArrayList();
-        ByteBuf input = Unpooled.copiedBuffer(CHUNKED_MESSAGE.getBytes(Charsets.UTF_8));
+        final List<Object> output = Lists.newArrayList();
+        final ByteBuf input = Unpooled.copiedBuffer(CHUNKED_MESSAGE.getBytes(Charsets.UTF_8));
         agr.decode(null, input, output);
 
-        Assert.assertEquals(1, output.size());
-        ByteBuf chunk = (ByteBuf) output.get(0);
+        assertEquals(1, output.size());
+        final ByteBuf chunk = (ByteBuf) output.get(0);
 
-        Assert.assertEquals(EXPECTED_MESSAGE, chunk.toString(Charsets.UTF_8));
+        assertEquals(EXPECTED_MESSAGE, chunk.toString(Charsets.UTF_8));
     }
 
     @Test
     public void testOneChunks() throws Exception {
-        List<Object> output = Lists.newArrayList();
-        ByteBuf input = Unpooled.copiedBuffer(CHUNKED_MESSAGE_ONE.getBytes(Charsets.UTF_8));
+        final List<Object> output = Lists.newArrayList();
+        final ByteBuf input = Unpooled.copiedBuffer(CHUNKED_MESSAGE_ONE.getBytes(Charsets.UTF_8));
         agr.decode(null, input, output);
 
-        Assert.assertEquals(1, output.size());
-        ByteBuf chunk = (ByteBuf) output.get(0);
+        assertEquals(1, output.size());
+        final ByteBuf chunk = (ByteBuf) output.get(0);
 
-        Assert.assertEquals(EXPECTED_MESSAGE, chunk.toString(Charsets.UTF_8));
+        assertEquals(EXPECTED_MESSAGE, chunk.toString(Charsets.UTF_8));
     }
 
 
diff --git a/opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfHelloMessageToXMLEncoderTest.java b/opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfHelloMessageToXMLEncoderTest.java
new file mode 100644 (file)
index 0000000..00d95df
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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.netconf.nettyutil.handler;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertThat;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandlerContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
+import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+
+public class NetconfHelloMessageToXMLEncoderTest {
+
+    @Mock
+    private ChannelHandlerContext ctx;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void testEncode() throws Exception {
+        final NetconfMessage msg = new NetconfHelloMessage(XmlUtil.readXmlToDocument("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>"),
+                NetconfHelloMessageAdditionalHeader.fromString("[tomas;10.0.0.0:10000;tcp;client;]"));
+        final ByteBuf destination = Unpooled.buffer();
+        new NetconfHelloMessageToXMLEncoder().encode(ctx, msg, destination);
+
+        final String encoded = new String(destination.array());
+        assertThat(encoded, containsString("[tomas;10.0.0.0:10000;tcp;client;]"));
+        assertThat(encoded, containsString("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>"));
+    }
+
+    @Test
+    public void testEncodeNoHeader() throws Exception {
+        final NetconfMessage msg = new NetconfHelloMessage(XmlUtil.readXmlToDocument("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>"));
+        final ByteBuf destination = Unpooled.buffer();
+        new NetconfHelloMessageToXMLEncoder().encode(ctx, msg, destination);
+
+        final String encoded = new String(destination.array());
+        assertThat(encoded, not(containsString("[tomas;10.0.0.0:10000;tcp;client;]")));
+        assertThat(encoded, containsString("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>"));
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testEncodeNotHello() throws Exception {
+        final NetconfMessage msg = new NetconfMessage(XmlUtil.readXmlToDocument("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>"));
+        new NetconfHelloMessageToXMLEncoder().encode(ctx, msg, null);
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfXMLToHelloMessageDecoderTest.java b/opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfXMLToHelloMessageDecoderTest.java
new file mode 100644 (file)
index 0000000..f0c0d63
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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.netconf.nettyutil.handler;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.List;
+import org.hamcrest.CoreMatchers;
+import org.junit.Test;
+import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+
+public class NetconfXMLToHelloMessageDecoderTest {
+
+    @Test
+    public void testDecodeWithHeader() throws Exception {
+        final ByteBuf src = Unpooled.wrappedBuffer(String.format("%s\n%s",
+                "[tomas;10.0.0.0:10000;tcp;client;]", "<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>").getBytes());
+        final List<Object> out = Lists.newArrayList();
+        new NetconfXMLToHelloMessageDecoder().decode(null, src, out);
+
+        assertEquals(1, out.size());
+        assertThat(out.get(0), CoreMatchers.instanceOf(NetconfHelloMessage.class));
+        final NetconfHelloMessage hello = (NetconfHelloMessage) out.get(0);
+        assertTrue(hello.getAdditionalHeader().isPresent());
+        assertEquals("[tomas;10.0.0.0:10000;tcp;client;]\n", hello.getAdditionalHeader().get().toFormattedString());
+        assertThat(XmlUtil.toString(hello.getDocument()), CoreMatchers.containsString("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\""));
+    }
+
+    @Test
+    public void testDecodeNoHeader() throws Exception {
+        final ByteBuf src = Unpooled.wrappedBuffer("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>".getBytes());
+        final List<Object> out = Lists.newArrayList();
+        new NetconfXMLToHelloMessageDecoder().decode(null, src, out);
+
+        assertEquals(1, out.size());
+        assertThat(out.get(0), CoreMatchers.instanceOf(NetconfHelloMessage.class));
+        final NetconfHelloMessage hello = (NetconfHelloMessage) out.get(0);
+        assertFalse(hello.getAdditionalHeader().isPresent());
+    }
+
+    @Test
+    public void testDecodeCaching() throws Exception {
+        final ByteBuf msg1 = Unpooled.wrappedBuffer("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>".getBytes());
+        final ByteBuf msg2 = Unpooled.wrappedBuffer("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>".getBytes());
+        final ByteBuf src = Unpooled.wrappedBuffer("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>".getBytes());
+        final List<Object> out = Lists.newArrayList();
+        final NetconfXMLToHelloMessageDecoder decoder = new NetconfXMLToHelloMessageDecoder();
+        decoder.decode(null, src, out);
+        decoder.decode(null, msg1, out);
+        decoder.decode(null, msg2, out);
+
+        assertEquals(1, out.size());
+
+        assertEquals(2, Iterables.size(decoder.getPostHelloNetconfMessages()));
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testDecodeNotHelloReceived() throws Exception {
+        final ByteBuf msg1 = Unpooled.wrappedBuffer("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>".getBytes());
+        final List<Object> out = Lists.newArrayList();
+        NetconfXMLToHelloMessageDecoder decoder = new NetconfXMLToHelloMessageDecoder();
+        decoder.decode(null, msg1, out);
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfXMLToMessageDecoderTest.java b/opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfXMLToMessageDecoderTest.java
new file mode 100644 (file)
index 0000000..f85a387
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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.netconf.nettyutil.handler;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.common.collect.Lists;
+import io.netty.buffer.Unpooled;
+import java.util.ArrayList;
+import org.junit.Test;
+
+public class NetconfXMLToMessageDecoderTest {
+
+    @Test
+    public void testDecodeNoMoreContent() throws Exception {
+        final ArrayList<Object> out = Lists.newArrayList();
+        new NetconfXMLToMessageDecoder().decode(null, Unpooled.buffer(), out);
+        assertEquals(0, out.size());
+    }
+
+    @Test
+    public void testDecode() throws Exception {
+        final ArrayList<Object> out = Lists.newArrayList();
+        new NetconfXMLToMessageDecoder().decode(null, Unpooled.wrappedBuffer("<msg/>".getBytes()), out);
+        assertEquals(1, out.size());
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/authentication/LoginPasswordTest.java b/opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/authentication/LoginPasswordTest.java
new file mode 100644 (file)
index 0000000..01df1e3
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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.netconf.nettyutil.handler.ssh.authentication;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import org.apache.sshd.ClientSession;
+import org.apache.sshd.client.future.AuthFuture;
+import org.junit.Test;
+
+public class LoginPasswordTest {
+
+    @Test
+    public void testLoginPassword() throws Exception {
+        final LoginPassword loginPassword = new LoginPassword("user", "pwd");
+        assertEquals("user", loginPassword.getUsername());
+
+        final ClientSession session = mock(ClientSession.class);
+        doNothing().when(session).addPasswordIdentity("pwd");
+        doReturn(mock(AuthFuture.class)).when(session).auth();
+        loginPassword.authenticate(session);
+
+        verify(session).addPasswordIdentity("pwd");
+        verify(session).auth();
+    }
+}
\ No newline at end of file
index febf3abf8e6fcbb6b035dfafffebb784e6392f44..6dd23776ce0c0b2f642ffb71d833b577bae10fa8 100644 (file)
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>netconf-api</artifactId>
+    </dependency>
+      <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>netconf-auth</artifactId>
     </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
       <groupId>org.bouncycastle</groupId>
       <artifactId>bcprov-jdk15on</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>usermanager</artifactId>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.thirdparty</groupId>
       <artifactId>ganymed</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.sshd</groupId>
+      <artifactId>sshd-core</artifactId>
+    </dependency>
+      <dependency>
+          <groupId>com.google.guava</groupId>
+          <artifactId>guava</artifactId>
+      </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
         <configuration>
           <instructions>
             <Bundle-Activator>org.opendaylight.controller.netconf.ssh.osgi.NetconfSSHActivator</Bundle-Activator>
-            <Import-Package>com.google.common.base,
-              ch.ethz.ssh2,
-              ch.ethz.ssh2.signature,
-              org.apache.commons.io,
-              org.opendaylight.controller.netconf.util.osgi,
-              org.opendaylight.controller.usermanager,
-              org.opendaylight.controller.sal.authorization,
-              org.opendaylight.controller.sal.utils,
-              org.osgi.framework,
-              org.osgi.util.tracker,
-              org.slf4j,
-              org.bouncycastle.openssl,
-              io.netty.bootstrap, io.netty.buffer, io.netty.channel, io.netty.channel.local, io.netty.channel.nio,
-              io.netty.handler.stream, io.netty.util.concurrent, org.apache.commons.lang3,
-              org.opendaylight.controller.netconf.util.messages</Import-Package>
+            <Import-Package>*</Import-Package>
           </instructions>
         </configuration>
       </plugin>
index 670f50ddd09f9b3b80d855ce244f4a4cce47da14..86206a7d5cad932c3b8510a7c2518d36c06c4f51 100644 (file)
@@ -7,9 +7,7 @@
  */
 package org.opendaylight.controller.netconf.ssh;
 
-import com.google.common.annotations.VisibleForTesting;
-import io.netty.channel.EventLoopGroup;
-import io.netty.channel.local.LocalAddress;
+import com.google.common.base.Preconditions;
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
@@ -17,12 +15,20 @@ import java.net.Socket;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.atomic.AtomicLong;
+
 import javax.annotation.concurrent.ThreadSafe;
-import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
+
+import org.opendaylight.controller.netconf.auth.AuthProvider;
 import org.opendaylight.controller.netconf.ssh.threads.Handshaker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
+
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.local.LocalAddress;
+
 /**
  * Thread that accepts client connections. Accepted socket is forwarded to {@link org.opendaylight.controller.netconf.ssh.threads.Handshaker},
  * which is executed in {@link #handshakeExecutor}.
@@ -36,13 +42,15 @@ public final class NetconfSSHServer extends Thread implements AutoCloseable {
     private final ServerSocket serverSocket;
     private final LocalAddress localAddress;
     private final EventLoopGroup bossGroup;
-    private final AuthProvider authProvider;
+    private Optional<AuthProvider> authProvider = Optional.absent();
     private final ExecutorService handshakeExecutor;
+    private final char[] pem;
     private volatile boolean up;
 
-    private NetconfSSHServer(int serverPort, LocalAddress localAddress, AuthProvider authProvider, EventLoopGroup bossGroup) throws IOException {
+    private NetconfSSHServer(final int serverPort, final LocalAddress localAddress, final EventLoopGroup bossGroup, final char[] pem) throws IOException {
         super(NetconfSSHServer.class.getSimpleName());
         this.bossGroup = bossGroup;
+        this.pem = pem;
         logger.trace("Creating SSH server socket on port {}", serverPort);
         this.serverSocket = new ServerSocket(serverPort);
         if (serverSocket.isBound() == false) {
@@ -50,17 +58,28 @@ public final class NetconfSSHServer extends Thread implements AutoCloseable {
         }
         logger.trace("Server socket created.");
         this.localAddress = localAddress;
-        this.authProvider = authProvider;
         this.up = true;
         handshakeExecutor = Executors.newFixedThreadPool(10);
     }
 
-    public static NetconfSSHServer start(int serverPort, LocalAddress localAddress, AuthProvider authProvider, EventLoopGroup bossGroup) throws IOException {
-        NetconfSSHServer netconfSSHServer = new NetconfSSHServer(serverPort, localAddress, authProvider, bossGroup);
+    public static NetconfSSHServer start(final int serverPort, final LocalAddress localAddress, final EventLoopGroup bossGroup, final char[] pemArray) throws IOException {
+        final NetconfSSHServer netconfSSHServer = new NetconfSSHServer(serverPort, localAddress, bossGroup, pemArray);
         netconfSSHServer.start();
         return netconfSSHServer;
     }
 
+    public synchronized AuthProvider getAuthProvider() {
+        Preconditions.checkState(authProvider.isPresent(), "AuthenticationProvider is not set up, cannot authenticate user");
+        return authProvider.get();
+    }
+
+    public synchronized void setAuthProvider(final AuthProvider authProvider) {
+        if(this.authProvider != null) {
+            logger.debug("Changing auth provider to {}", authProvider);
+        }
+        this.authProvider = Optional.fromNullable(authProvider);
+    }
+
     @Override
     public void close() throws IOException {
         up = false;
@@ -81,7 +100,7 @@ public final class NetconfSSHServer extends Thread implements AutoCloseable {
             Socket acceptedSocket = null;
             try {
                 acceptedSocket = serverSocket.accept();
-            } catch (IOException e) {
+            } catch (final IOException e) {
                 if (up == false) {
                     logger.trace("Exiting server thread", e);
                 } else {
@@ -90,18 +109,26 @@ public final class NetconfSSHServer extends Thread implements AutoCloseable {
             }
             if (acceptedSocket != null) {
                 try {
-                    Handshaker task = new Handshaker(acceptedSocket, localAddress, sessionIdCounter.incrementAndGet(), authProvider, bossGroup);
+                    final Handshaker task = new Handshaker(acceptedSocket, localAddress, sessionIdCounter.incrementAndGet(), getAuthProvider(), bossGroup, pem);
                     handshakeExecutor.submit(task);
-                } catch (IOException e) {
+                } catch (final IOException e) {
                     logger.warn("Cannot set PEMHostKey, closing connection", e);
-                    try {
-                        acceptedSocket.close();
-                    } catch (IOException e1) {
-                        logger.warn("Ignoring exception while closing socket", e);
-                    }
+                    closeSocket(acceptedSocket);
+                } catch (final IllegalStateException e) {
+                    logger.warn("Cannot accept connection, closing", e);
+                    closeSocket(acceptedSocket);
                 }
             }
         }
         logger.debug("Server thread is exiting");
     }
+
+    private void closeSocket(final Socket acceptedSocket) {
+        try {
+            acceptedSocket.close();
+        } catch (final IOException e) {
+            logger.warn("Ignoring exception while closing socket", e);
+        }
+    }
+
 }
index 503e764409e37d848ffeaf444c5e34e529bd6849..c686bcbc66fcb849da3f357bdd3bea2df7f62f2e 100644 (file)
@@ -9,26 +9,33 @@ package org.opendaylight.controller.netconf.ssh.osgi;
 
 import static com.google.common.base.Preconditions.checkState;
 
-import com.google.common.base.Optional;
-import io.netty.channel.EventLoopGroup;
-import io.netty.channel.local.LocalAddress;
-import io.netty.channel.nio.NioEventLoopGroup;
+import com.google.common.base.Preconditions;
 import java.io.File;
 import java.io.IOException;
 import java.net.InetSocketAddress;
+
 import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.lang3.StringUtils;
+import org.opendaylight.controller.netconf.auth.AuthConstants;
+import org.opendaylight.controller.netconf.auth.AuthProvider;
 import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
-import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
-import org.opendaylight.controller.netconf.ssh.authentication.AuthProviderImpl;
 import org.opendaylight.controller.netconf.ssh.authentication.PEMGenerator;
 import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil;
 import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil.InfixProp;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.local.LocalAddress;
+import io.netty.channel.nio.NioEventLoopGroup;
+
 /**
  * Activator for netconf SSH bundle which creates SSH bridge between netconf client and netconf server. Activator
  * starts SSH Server in its own thread. This thread is closed when activator calls stop() method. Server opens socket
@@ -41,6 +48,7 @@ import org.slf4j.LoggerFactory;
  */
 public class NetconfSSHActivator implements BundleActivator {
     private static final Logger logger = LoggerFactory.getLogger(NetconfSSHActivator.class);
+    private static AuthProviderTracker authProviderTracker;
 
     private NetconfSSHServer server;
 
@@ -50,39 +58,115 @@ public class NetconfSSHActivator implements BundleActivator {
     }
 
     @Override
-    public void stop(BundleContext context) throws IOException {
+    public void stop(final BundleContext context) throws IOException {
         if (server != null) {
             server.close();
         }
+
+        if(authProviderTracker != null) {
+            authProviderTracker.stop();
+        }
     }
 
-    private static NetconfSSHServer startSSHServer(BundleContext bundleContext) throws IOException {
-        Optional<InetSocketAddress> maybeSshSocketAddress = NetconfConfigUtil.extractNetconfServerAddress(bundleContext,
+    private static NetconfSSHServer startSSHServer(final BundleContext bundleContext) throws IOException {
+        final Optional<InetSocketAddress> maybeSshSocketAddress = NetconfConfigUtil.extractNetconfServerAddress(bundleContext,
                 InfixProp.ssh);
 
         if (maybeSshSocketAddress.isPresent() == false) {
             logger.trace("SSH bridge not configured");
             return null;
         }
-        InetSocketAddress sshSocketAddress = maybeSshSocketAddress.get();
-        logger.trace("Starting netconf SSH  bridge at {}", sshSocketAddress);
 
-        LocalAddress localAddress = NetconfConfigUtil.getNetconfLocalAddress();
+        final InetSocketAddress sshSocketAddress = maybeSshSocketAddress.get();
+        logger.trace("Starting netconf SSH bridge at {}", sshSocketAddress);
+
+        final LocalAddress localAddress = NetconfConfigUtil.getNetconfLocalAddress();
 
-        String path = FilenameUtils.separatorsToSystem(NetconfConfigUtil.getPrivateKeyPath(bundleContext));
-        checkState(StringUtils.isNotBlank(path), "Path to ssh private key is blank. Reconfigure %s", NetconfConfigUtil.getPrivateKeyKey());
-        String privateKeyPEMString = PEMGenerator.readOrGeneratePK(new File(path));
+        final String path = FilenameUtils.separatorsToSystem(NetconfConfigUtil.getPrivateKeyPath(bundleContext));
+        checkState(!Strings.isNullOrEmpty(path), "Path to ssh private key is blank. Reconfigure %s", NetconfConfigUtil.getPrivateKeyKey());
+        final String privateKeyPEMString = PEMGenerator.readOrGeneratePK(new File(path));
 
-        final AuthProvider authProvider = new AuthProviderImpl(privateKeyPEMString, bundleContext);
-        EventLoopGroup bossGroup  = new NioEventLoopGroup();
-        NetconfSSHServer server = NetconfSSHServer.start(sshSocketAddress.getPort(), localAddress, authProvider, bossGroup);
+        final EventLoopGroup bossGroup  = new NioEventLoopGroup();
+        final NetconfSSHServer server = NetconfSSHServer.start(sshSocketAddress.getPort(), localAddress, bossGroup, privateKeyPEMString.toCharArray());
+
+        authProviderTracker = new AuthProviderTracker(bundleContext, server);
+
+        return server;
+    }
 
+    private static Thread runNetconfSshThread(final NetconfSSHServer server) {
         final Thread serverThread = new Thread(server, "netconf SSH server thread");
         serverThread.setDaemon(true);
         serverThread.start();
         logger.trace("Netconf SSH  bridge up and running.");
-        return server;
+        return serverThread;
     }
 
+    private static class AuthProviderTracker implements ServiceTrackerCustomizer<AuthProvider, AuthProvider> {
+        private final BundleContext bundleContext;
+        private final NetconfSSHServer server;
+
+        private Integer maxPreference;
+        private Thread sshThread;
+        private final ServiceTracker<AuthProvider, AuthProvider> listenerTracker;
+
+        public AuthProviderTracker(final BundleContext bundleContext, final NetconfSSHServer server) {
+            this.bundleContext = bundleContext;
+            this.server = server;
+            listenerTracker = new ServiceTracker<>(bundleContext, AuthProvider.class, this);
+            listenerTracker.open();
+        }
+
+        @Override
+        public AuthProvider addingService(final ServiceReference<AuthProvider> reference) {
+            logger.trace("Service {} added", reference);
+            final AuthProvider authService = bundleContext.getService(reference);
+            final Integer newServicePreference = getPreference(reference);
+            if(isBetter(newServicePreference)) {
+                server.setAuthProvider(authService);
+                if(sshThread == null) {
+                    sshThread = runNetconfSshThread(server);
+                }
+            }
+            return authService;
+        }
+
+        private Integer getPreference(final ServiceReference<AuthProvider> reference) {
+            final Object preferenceProperty = reference.getProperty(AuthConstants.SERVICE_PREFERENCE_KEY);
+            return preferenceProperty == null ? Integer.MIN_VALUE : Integer.valueOf(preferenceProperty.toString());
+        }
+
+        private boolean isBetter(final Integer newServicePreference) {
+            Preconditions.checkNotNull(newServicePreference);
+            if(maxPreference == null) {
+                return true;
+            }
 
+            return newServicePreference > maxPreference;
+        }
+
+        @Override
+        public void modifiedService(final ServiceReference<AuthProvider> reference, final AuthProvider service) {
+            final AuthProvider authService = bundleContext.getService(reference);
+            final Integer newServicePreference = getPreference(reference);
+            if(isBetter(newServicePreference)) {
+                logger.trace("Replacing modified service {} in netconf SSH.", reference);
+                server.setAuthProvider(authService);
+            }
+        }
+
+        @Override
+        public void removedService(final ServiceReference<AuthProvider> reference, final AuthProvider service) {
+            logger.trace("Removing service {} from netconf SSH. " +
+                    "SSH won't authenticate users until AuthProvider service will be started.", reference);
+            maxPreference = null;
+            server.setAuthProvider(null);
+        }
+
+        public void stop() {
+            listenerTracker.close();
+            // sshThread should finish normally since sshServer.close stops processing
+        }
+
+    }
 }
index 3fffbb2d2c7b03cf6249c000d8610adb386b1bba..eec6c3a0971d8a3369ee05a863540bed4b85f8b2 100644 (file)
@@ -10,6 +10,20 @@ package org.opendaylight.controller.netconf.ssh.threads;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+
+import javax.annotation.concurrent.NotThreadSafe;
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opendaylight.controller.netconf.auth.AuthProvider;
+import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import ch.ethz.ssh2.AuthenticationResult;
 import ch.ethz.ssh2.PtySettings;
 import ch.ethz.ssh2.ServerAuthenticationCallback;
@@ -18,7 +32,9 @@ import ch.ethz.ssh2.ServerConnectionCallback;
 import ch.ethz.ssh2.ServerSession;
 import ch.ethz.ssh2.ServerSessionCallback;
 import ch.ethz.ssh2.SimpleServerSessionCallback;
+
 import com.google.common.base.Supplier;
+
 import io.netty.bootstrap.Bootstrap;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufProcessor;
@@ -32,17 +48,6 @@ import io.netty.channel.EventLoopGroup;
 import io.netty.channel.local.LocalAddress;
 import io.netty.channel.local.LocalChannel;
 import io.netty.handler.stream.ChunkedStream;
-import java.io.BufferedOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.Socket;
-import javax.annotation.concurrent.NotThreadSafe;
-import javax.annotation.concurrent.ThreadSafe;
-import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
-import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * One instance represents per connection, responsible for ssh handshake.
@@ -58,7 +63,7 @@ public class Handshaker implements Runnable {
 
 
     public Handshaker(Socket socket, LocalAddress localAddress, long sessionId, AuthProvider authProvider,
-                      EventLoopGroup bossGroup) throws IOException {
+                      EventLoopGroup bossGroup, final char[] pem) throws IOException {
 
         this.session = "Session " + sessionId;
 
@@ -83,7 +88,7 @@ public class Handshaker implements Runnable {
                 getGanymedAutoCloseable(ganymedConnection), localAddress, bossGroup);
 
         // initialize ganymed
-        ganymedConnection.setPEMHostKey(authProvider.getPEMAsCharArray(), null);
+        ganymedConnection.setPEMHostKey(pem, null);
         ganymedConnection.setAuthenticationCallback(serverAuthenticationCallback);
         ganymedConnection.setServerConnectionCallback(serverConnectionCallback);
     }
diff --git a/opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/StubUserManager.java b/opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/StubUserManager.java
deleted file mode 100644 (file)
index 6628310..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * 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
- */
-package org.opendaylight.controller.netconf;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.opendaylight.controller.sal.authorization.AuthResultEnum;
-import org.opendaylight.controller.sal.authorization.UserLevel;
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.sal.utils.StatusCode;
-import org.opendaylight.controller.usermanager.AuthorizationConfig;
-import org.opendaylight.controller.usermanager.ISessionManager;
-import org.opendaylight.controller.usermanager.IUserManager;
-import org.opendaylight.controller.usermanager.ServerConfig;
-import org.opendaylight.controller.usermanager.UserConfig;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.security.web.context.SecurityContextRepository;
-
-public class StubUserManager implements IUserManager{
-
-
-    private static String user;
-    private static String password;
-
-    public StubUserManager(String user, String password){
-        StubUserManager.user = user;
-        StubUserManager.password = password;
-    }
-    @Override
-    public List<String> getUserRoles(String userName) {
-        return null;
-    }
-
-    @Override
-    public AuthResultEnum authenticate(String username, String password) {
-        if (StubUserManager.user.equals(username) && StubUserManager.password.equals(password)){
-            return AuthResultEnum.AUTH_ACCEPT_LOC;
-        }
-        return AuthResultEnum.AUTH_REJECT_LOC;
-    }
-
-    @Override
-    public Status addAAAServer(ServerConfig configObject) {
-        return null;
-    }
-
-    @Override
-    public Status removeAAAServer(ServerConfig configObject) {
-        return null;
-    }
-
-    @Override
-    public Status addLocalUser(UserConfig configObject) {
-        return new Status(StatusCode.SUCCESS);
-    }
-
-    @Override
-    public Status modifyLocalUser(UserConfig configObject) {
-        return null;
-    }
-
-    @Override
-    public Status removeLocalUser(UserConfig configObject) {
-        return null;
-    }
-
-    @Override
-    public Status removeLocalUser(String userName) {
-        return null;
-    }
-
-    @Override
-    public Status addAuthInfo(AuthorizationConfig AAAconf) {
-        return null;
-    }
-
-    @Override
-    public Status removeAuthInfo(AuthorizationConfig AAAconf) {
-        return null;
-    }
-
-    @Override
-    public List<AuthorizationConfig> getAuthorizationList() {
-        return null;
-    }
-
-    @Override
-    public Set<String> getAAAProviderNames() {
-        return null;
-    }
-
-    @Override
-    public Status changeLocalUserPassword(String user, String curPassword, String newPassword) {
-        return null;
-    }
-
-    @Override
-    public List<ServerConfig> getAAAServerList() {
-        return null;
-    }
-
-    @Override
-    public List<UserConfig> getLocalUserList() {
-        return null;
-    }
-
-    @Override
-    public Status saveLocalUserList() {
-        return null;
-    }
-
-    @Override
-    public Status saveAAAServerList() {
-        return null;
-    }
-
-    @Override
-    public Status saveAuthorizationList() {
-        return null;
-    }
-
-    @Override
-    public void userLogout(String username) {
-
-    }
-
-    @Override
-    public void userTimedOut(String username) {
-
-    }
-
-    @Override
-    public Map<String, List<String>> getUserLoggedIn() {
-        return null;
-    }
-
-    @Override
-    public String getAccessDate(String user) {
-        return null;
-    }
-
-    @Override
-    public UserLevel getUserLevel(String userName) {
-        return null;
-    }
-
-    @Override
-    public List<UserLevel> getUserLevels(String userName) {
-        return null;
-    }
-
-    @Override
-    public SecurityContextRepository getSecurityContextRepo() {
-        return null;
-    }
-
-    @Override
-    public ISessionManager getSessionManager() {
-        return null;
-    }
-
-    @Override
-    public boolean isRoleInUse(String role) {
-        return false;
-    }
-
-    @Override
-    public String getPassword(String username) {
-        return null;
-    }
-
-    @Override
-    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
-        return null;
-    }
-
-}
index 61297835a07b684dd009176c6c0e16c0971c2b5e..ce1400bbcb24a5d455ad179a93da6098530c5790 100644 (file)
@@ -27,12 +27,11 @@ import java.util.concurrent.TimeUnit;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.opendaylight.controller.netconf.auth.AuthProvider;
 import org.opendaylight.controller.netconf.netty.EchoClientHandler.State;
 import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.LoginPassword;
-import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.AsyncSshHandler;
 import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
-import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
-import org.opendaylight.controller.netconf.ssh.authentication.AuthProviderImpl;
 import org.opendaylight.controller.netconf.ssh.authentication.PEMGenerator;
 import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil;
 import org.slf4j.Logger;
@@ -59,11 +58,13 @@ public class SSHTest {
     @Test
     public void test() throws Exception {
         new Thread(new EchoServer(), "EchoServer").start();
-        AuthProvider authProvider = mock(AuthProviderImpl.class);
-        doReturn(PEMGenerator.generate().toCharArray()).when(authProvider).getPEMAsCharArray();
+        AuthProvider authProvider = mock(AuthProvider.class);
         doReturn(true).when(authProvider).authenticated(anyString(), anyString());
+        doReturn("auth").when(authProvider).toString();
+
         NetconfSSHServer netconfSSHServer = NetconfSSHServer.start(10831, NetconfConfigUtil.getNetconfLocalAddress(),
-                authProvider, new NioEventLoopGroup());
+                new NioEventLoopGroup(), PEMGenerator.generate().toCharArray());
+        netconfSSHServer.setAuthProvider(authProvider);
 
         InetSocketAddress address = netconfSSHServer.getLocalSocketAddress();
         final EchoClientHandler echoClientHandler = connectClient(address);
@@ -94,7 +95,7 @@ public class SSHTest {
         ChannelInitializer<NioSocketChannel> channelInitializer = new ChannelInitializer<NioSocketChannel>() {
             @Override
             public void initChannel(NioSocketChannel ch) throws Exception {
-                ch.pipeline().addFirst(SshHandler.createForNetconfSubsystem(new LoginPassword("a", "a")));
+                ch.pipeline().addFirst(AsyncSshHandler.createForNetconfSubsystem(new LoginPassword("a", "a")));
                 ch.pipeline().addLast(echoClientHandler);
             }
         };
@@ -118,7 +119,7 @@ public class SSHTest {
             Thread.sleep(100);
         }
         assertFalse(echoClientHandler.isConnected());
-        assertEquals(State.FAILED_TO_CONNECT, echoClientHandler.getState());
+        assertEquals(State.CONNECTION_CLOSED, echoClientHandler.getState());
     }
 
 }
index 75d18566eec79c775d7861d86fd0aaf2ddda2dbb..1151abcdf2767de1aa5a70fd19aa3219f9b23b1c 100644 (file)
@@ -23,7 +23,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.opendaylight.controller.netconf.StubUserManager;
+import org.opendaylight.controller.netconf.auth.AuthProvider;
 import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
 import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil;
 import org.osgi.framework.BundleContext;
@@ -55,16 +55,21 @@ public class SSHServerTest {
         doReturn(new ServiceReference[0]).when(mockedContext).getServiceReferences(anyString(), anyString());
 
         logger.info("Creating SSH server");
-        StubUserManager um = new StubUserManager(USER, PASSWORD);
         String pem;
         try (InputStream is = getClass().getResourceAsStream("/RSA.pk")) {
             pem = IOUtils.toString(is);
         }
-        AuthProviderImpl ap = new AuthProviderImpl(pem, mockedContext);
-        ap.setNullableUserManager(um);
+
+
         EventLoopGroup bossGroup = new NioEventLoopGroup();
         NetconfSSHServer server = NetconfSSHServer.start(PORT, NetconfConfigUtil.getNetconfLocalAddress(),
-                ap, bossGroup);
+                bossGroup, pem.toCharArray());
+        server.setAuthProvider(new AuthProvider() {
+            @Override
+            public boolean authenticated(final String username, final String password) {
+                return true;
+            }
+        });
 
         sshServerThread = new Thread(server);
         sshServerThread.setDaemon(true);
index 35f2345248f1ac30203d014e78e5283e8c66f82b..4721acf209055190d30b12c73b1d7e80898b953c 100644 (file)
@@ -8,29 +8,13 @@
 
 package org.opendaylight.controller.netconf.test.tool;
 
-import java.io.File;
-import java.io.IOException;
-import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
-import org.opendaylight.controller.netconf.ssh.authentication.PEMGenerator;
+import org.opendaylight.controller.netconf.auth.AuthProvider;
 
 class AcceptingAuthProvider implements AuthProvider {
-    private final String privateKeyPEMString;
-
-    public AcceptingAuthProvider() {
-        try {
-            this.privateKeyPEMString = PEMGenerator.readOrGeneratePK(new File("PK"));
-        } catch (final IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
 
     @Override
     public synchronized boolean authenticated(final String username, final String password) {
         return true;
     }
 
-    @Override
-    public char[] getPEMAsCharArray() {
-        return privateKeyPEMString.toCharArray();
-    }
 }
index 3a52f0a85ea4af1aca3f3fb452bf1e711a2da2df..2cd5b19bd12a4c44a222a43acd8004df82debef1 100644 (file)
@@ -23,6 +23,7 @@ import io.netty.channel.local.LocalAddress;
 import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.util.HashedWheelTimer;
 import java.io.Closeable;
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.lang.management.ManagementFactory;
@@ -55,6 +56,7 @@ import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceSnapshot;
 import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOperationService;
 import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
+import org.opendaylight.controller.netconf.ssh.authentication.PEMGenerator;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
@@ -165,7 +167,8 @@ public class NetconfDeviceSimulator implements Closeable {
 
                 server = dispatcher.createLocalServer(tcpLocalAddress);
                 try {
-                    NetconfSSHServer.start(currentPort, tcpLocalAddress, new AcceptingAuthProvider(), nettyThreadgroup);
+                    final NetconfSSHServer sshServer = NetconfSSHServer.start(currentPort, tcpLocalAddress, nettyThreadgroup, getPemArray());
+                    sshServer.setAuthProvider(new AcceptingAuthProvider());
                 } catch (final Exception e) {
                     LOG.warn("Cannot start simulated device on {}, skipping", address, e);
                     // Close local server and continue
@@ -219,6 +222,14 @@ public class NetconfDeviceSimulator implements Closeable {
         return openDevices;
     }
 
+    private char[] getPemArray() {
+        try {
+            return PEMGenerator.readOrGeneratePK(new File("PK")).toCharArray();
+        } catch (final IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
     private Map<ModuleBuilder, String> parseSchemasToModuleBuilders(final Main.Params params) {
         final SharedSchemaRepository consumer = new SharedSchemaRepository("netconf-simulator");
         consumer.registerSchemaSourceListener(TextToASTTransformer.create(consumer, consumer));
diff --git a/opendaylight/netconf/netconf-usermanager/pom.xml b/opendaylight/netconf/netconf-usermanager/pom.xml
new file mode 100644 (file)
index 0000000..f8c3e5a
--- /dev/null
@@ -0,0 +1,52 @@
+<?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>netconf-subsystem</artifactId>
+        <version>0.2.5-SNAPSHOT</version>
+        <relativePath>../</relativePath>
+    </parent>
+    <artifactId>netconf-usermanager</artifactId>
+    <packaging>bundle</packaging>
+    <name>${project.artifactId}</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netconf-auth</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>usermanager</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Bundle-Activator>org.opendaylight.controller.netconf.auth.usermanager.AuthProviderActivator</Bundle-Activator>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+
+</project>
diff --git a/opendaylight/netconf/netconf-usermanager/src/main/java/org/opendaylight/controller/netconf/auth/usermanager/AuthProviderActivator.java b/opendaylight/netconf/netconf-usermanager/src/main/java/org/opendaylight/controller/netconf/auth/usermanager/AuthProviderActivator.java
new file mode 100644 (file)
index 0000000..528d8ff
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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.netconf.auth.usermanager;
+
+import java.util.Hashtable;
+import org.opendaylight.controller.netconf.auth.AuthConstants;
+import org.opendaylight.controller.netconf.auth.AuthProvider;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+public class AuthProviderActivator implements BundleActivator {
+
+    public static final int PREFERENCE = 0;
+    private ServiceRegistration<AuthProvider> authProviderServiceRegistration;
+
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        final AuthProvider authProvider = new AuthProviderImpl(context);
+        // Set preference of this service to 0
+        final Hashtable<String, Object> properties = new Hashtable<>(1);
+        properties.put(AuthConstants.SERVICE_PREFERENCE_KEY, PREFERENCE);
+
+        authProviderServiceRegistration = context.registerService(AuthProvider.class, authProvider, properties);
+    }
+
+    @Override
+    public void stop(final BundleContext context) throws Exception {
+        if(authProviderServiceRegistration != null) {
+            authProviderServiceRegistration.unregister();
+        }
+    }
+}
@@ -5,11 +5,9 @@
  * 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.netconf.ssh.authentication;
+package org.opendaylight.controller.netconf.auth.usermanager;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.google.common.annotations.VisibleForTesting;
+import org.opendaylight.controller.netconf.auth.AuthProvider;
 import org.opendaylight.controller.sal.authorization.AuthResultEnum;
 import org.opendaylight.controller.usermanager.IUserManager;
 import org.osgi.framework.BundleContext;
@@ -19,40 +17,41 @@ import org.osgi.util.tracker.ServiceTrackerCustomizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * AuthProvider implementation delegating to AD-SAL UserManager instance.
+ */
 public class AuthProviderImpl implements AuthProvider {
     private static final Logger logger = LoggerFactory.getLogger(AuthProviderImpl.class);
 
-    private final String pem;
     private IUserManager nullableUserManager;
 
-    public AuthProviderImpl(String pemCertificate, final BundleContext bundleContext) {
-        checkNotNull(pemCertificate, "Parameter 'pemCertificate' is null");
-        pem = pemCertificate;
+    public AuthProviderImpl(final BundleContext bundleContext) {
 
-        ServiceTrackerCustomizer<IUserManager, IUserManager> customizer = new ServiceTrackerCustomizer<IUserManager, IUserManager>() {
+        final ServiceTrackerCustomizer<IUserManager, IUserManager> customizer = new ServiceTrackerCustomizer<IUserManager, IUserManager>() {
             @Override
             public IUserManager addingService(final ServiceReference<IUserManager> reference) {
-                logger.trace("Service {} added", reference);
+                logger.trace("UerManager {} added", reference);
                 nullableUserManager = bundleContext.getService(reference);
                 return nullableUserManager;
             }
 
             @Override
             public void modifiedService(final ServiceReference<IUserManager> reference, final IUserManager service) {
-                logger.trace("Replacing modified service {} in netconf SSH.", reference);
+                logger.trace("Replacing modified UerManager {}", reference);
                 nullableUserManager = service;
             }
 
             @Override
             public void removedService(final ServiceReference<IUserManager> reference, final IUserManager service) {
-                logger.trace("Removing service {} from netconf SSH. " +
-                        "SSH won't authenticate users until IUserManager service will be started.", reference);
+                logger.trace("Removing UerManager {}. This AuthProvider will fail to authenticate every time", reference);
                 synchronized (AuthProviderImpl.this) {
                     nullableUserManager = null;
                 }
             }
         };
-        ServiceTracker<IUserManager, IUserManager> listenerTracker = new ServiceTracker<>(bundleContext, IUserManager.class, customizer);
+        final ServiceTracker<IUserManager, IUserManager> listenerTracker = new ServiceTracker<>(bundleContext, IUserManager.class, customizer);
         listenerTracker.open();
     }
 
@@ -61,23 +60,18 @@ public class AuthProviderImpl implements AuthProvider {
      * available, IllegalStateException is thrown.
      */
     @Override
-    public synchronized boolean authenticated(String username, String password) {
+    public synchronized boolean authenticated(final String username, final String password) {
         if (nullableUserManager == null) {
             logger.warn("Cannot authenticate user '{}', user manager service is missing", username);
             throw new IllegalStateException("User manager service is not available");
         }
-        AuthResultEnum authResult = nullableUserManager.authenticate(username, password);
+        final AuthResultEnum authResult = nullableUserManager.authenticate(username, password);
         logger.debug("Authentication result for user '{}' : {}", username, authResult);
         return authResult.equals(AuthResultEnum.AUTH_ACCEPT) || authResult.equals(AuthResultEnum.AUTH_ACCEPT_LOC);
     }
 
-    @Override
-    public char[] getPEMAsCharArray() {
-        return pem.toCharArray();
-    }
-
     @VisibleForTesting
-    void setNullableUserManager(IUserManager nullableUserManager) {
+    void setNullableUserManager(final IUserManager nullableUserManager) {
         this.nullableUserManager = nullableUserManager;
     }
 }
index b1b410a1fcb9971cadcb0e973d2381cbbdf3d04e..8abf67ec8c5fe198315be84d8f8d5d9d424347e0 100644 (file)
@@ -35,6 +35,8 @@
     <module>ietf-netconf-monitoring</module>
     <module>ietf-netconf-monitoring-extension</module>
     <module>netconf-connector-config</module>
+    <module>netconf-auth</module>
+    <module>netconf-usermanager</module>
   </modules>
 
   <dependencies>
index 0a1da7760412edb0308b64d26ee83d92c51a8bee..69a57748ddabc88212411cf6b4ecf3d088a80381 100644 (file)
@@ -75,5 +75,5 @@ public interface INeutronLoadBalancerPoolMemberAware {
      *            instance of deleted LoadBalancerPool object
      * @return void
      */
-    public void NeutronLoadBalancerPoolMemberDeleted(NeutronLoadBalancerPoolMember loadBalancerPoolMember);
+    public void neutronLoadBalancerPoolMemberDeleted(NeutronLoadBalancerPoolMember loadBalancerPoolMember);
 }
index e2df13b9aa859d739114b72b89cb1072e891bd9f..c7ae4eb1726e33d82213f5bced6064eb68a79a52 100644 (file)
@@ -59,6 +59,10 @@ public class NeutronRouter_Interface implements Serializable {
         this.portUUID = portUUID;
     }
 
+    public String getID() {
+        return id;
+    }
+
     public void setID(String id) {
         this.id = id;
     }
index b79e4325500d01549363e24e97cbc58c8581f7a0..1292c2995b2d119a4d6803a5684ff8be2ccd6424 100644 (file)
@@ -52,4 +52,11 @@ public class Neutron_IPs extends ConfigurationObject implements Serializable {
     public void setSubnetUUID(String subnetUUID) {
         this.subnetUUID = subnetUUID;
     }
+
+    @Override
+    public String toString() {
+        return "Neutron_IPs{" +
+               "ipAddress='" + ipAddress + '\'' +
+               ", subnetUUID='" + subnetUUID + '\'' + "}";
+    }
 }
index 4a6a291e6a0a1518c68ee181c771139be5146ec5..d92c57bd8a59d9852326e2f2238af9dac2784971 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -57,6 +57,10 @@ public class Activator extends ComponentActivatorAbstractBase {
     protected static final Logger logger = LoggerFactory
             .getLogger(Activator.class);
 
+    /**
+     * Priority to determine whether to override existing protocol service.
+     */
+    private static final int  PLUGIN_PRIORITY = 10;
 
     /**
      * Function that is used to communicate to dependency manager the list of
@@ -136,6 +140,8 @@ public class Activator extends ComponentActivatorAbstractBase {
             // Set the protocolPluginType property which will be used
             // by SAL
             props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
+            props.put(GlobalConstants.PROTOCOLPLUGINPRIORITY.toString(),
+                      Integer.valueOf(PLUGIN_PRIORITY));
             c.setInterface(IPluginInDataPacketService.class.getName(), props);
             // Hook the services coming in from SAL, as optional in
             // case SAL is not yet there, could happen
@@ -165,6 +171,8 @@ public class Activator extends ComponentActivatorAbstractBase {
             // Set the protocolPluginType property which will be used
             // by SAL
             props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
+            props.put(GlobalConstants.PROTOCOLPLUGINPRIORITY.toString(),
+                      Integer.valueOf(PLUGIN_PRIORITY));
             c.setInterface(new String[] {
                     IReadFilterInternalListener.class.getName(),
                     IPluginInReadService.class.getName() }, props);
@@ -256,6 +264,8 @@ public class Activator extends ComponentActivatorAbstractBase {
             // Set the protocolPluginType property which will be used
             // by SAL
             props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
+            props.put(GlobalConstants.PROTOCOLPLUGINPRIORITY.toString(),
+                      Integer.valueOf(PLUGIN_PRIORITY));
             c.setInterface(
                     new String[] { IPluginInFlowProgrammerService.class.getName(), IMessageListener.class.getName(),
                             IContainerListener.class.getName(), IInventoryShimExternalListener.class.getName(),
index b491c5fcea2e4b53914102a91e88a76591ac5d22..8b6d3c4a1cd7fc98d6820562e73068be331e7372 100644 (file)
@@ -1,11 +1,10 @@
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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.action;
 
 /**
@@ -34,8 +33,8 @@ public enum ActionType {
     SET_NW_SRC("setNwSrc", 0, 0),
     SET_NW_DST("setNwDst", 0, 0),
     SET_NW_TOS("setNwTos", 0, 0x3f),
-    SET_TP_SRC("setTpSrc", 1, 0xffff),
-    SET_TP_DST("setTpDst", 1, 0xffff),
+    SET_TP_SRC("setTpSrc", 0, 0xffff), // Set transport source port
+    SET_TP_DST("setTpDst", 0, 0xffff), // Set transport destination port
     SET_NEXT_HOP("setNextHop", 0, 0);
 
     private String id;
index 174f2546bad1039f87352b5e0a8bd129ad383732..ceb4553470933330516bd945652a07045dcf7e85 100644 (file)
@@ -1,6 +1,5 @@
-
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -20,7 +19,8 @@ public enum GlobalConstants {
     STATICVLAN("staticvlan"),
     CLUSTERINGSERVICES("clusteringservices"),
     STARTUPHOME("configuration/startup/"),
-    PROTOCOLPLUGINTYPE("protocolPluginType");
+    PROTOCOLPLUGINTYPE("protocolPluginType"),
+    PROTOCOLPLUGINPRIORITY("protocolPluginPriority");
 
     private GlobalConstants(String name) {
         this.name = name;
@@ -31,4 +31,4 @@ public enum GlobalConstants {
     public String toString() {
         return name;
     }
-}
\ No newline at end of file
+}
index 5c09a43feddf4cf66b2486d4d6df6776786b55a1..3fe9a18b3fa545cbdcf279092c272c43a34d4cc1 100644 (file)
@@ -1,12 +1,10 @@
-
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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.action;
 
 import org.opendaylight.controller.sal.core.ConstructionException;
@@ -176,8 +174,11 @@ public class ActionTest {
         action = new SetTpDst(65535);
         Assert.assertTrue(action.isValid());
 
+        action = new SetTpSrc(0);
+        Assert.assertTrue(action.isValid());
+
         action = new SetTpDst(0);
-        Assert.assertFalse(action.isValid());
+        Assert.assertTrue(action.isValid());
 
         action = new SetTpSrc(-1);
         Assert.assertFalse(action.isValid());
index e9039261a3724fb733f5a260300c291e9712224a..0c9ebab8c3c126a2442a0b8ef87ab30577602a10 100644 (file)
@@ -1,6 +1,5 @@
-
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -40,7 +39,6 @@ import org.opendaylight.controller.sal.packet.LinkEncap;
 import org.opendaylight.controller.sal.packet.Packet;
 import org.opendaylight.controller.sal.packet.PacketResult;
 import org.opendaylight.controller.sal.packet.RawPacket;
-import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.NetUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -59,9 +57,9 @@ public class DataPacketService implements IPluginOutDataPacketService,
      * adding a new service, removing a service, going through all of
      * them maybe different.
      */
-    private ConcurrentHashMap<String, IPluginInDataPacketService>
+    private ConcurrentHashMap<String, ProtocolService<IPluginInDataPacketService>>
         pluginInDataService =
-        new ConcurrentHashMap<String, IPluginInDataPacketService>();
+        new ConcurrentHashMap<String, ProtocolService<IPluginInDataPacketService>>();
     private Map<String, AtomicInteger> statistics = new HashMap<String, AtomicInteger>();
 
     /**
@@ -186,11 +184,11 @@ public class DataPacketService implements IPluginOutDataPacketService,
                         String t = p.getNode()
                                 .getType();
                         // Now locate the TX dispatcher
-                        IPluginInDataPacketService s = pluginInDataService
-                                .get(t);
-                        if (s != null) {
+                        ProtocolService<IPluginInDataPacketService> service =
+                            pluginInDataService.get(t);
+                        if (service != null) {
                             try {
-                                s.transmitDataPacket(pkt);
+                                service.getService().transmitDataPacket(pkt);
                                 increaseStat("TXPacketSuccess");
                             } catch (Exception e) {
                                 increaseStat("TXPacketFailedForException");
@@ -207,54 +205,11 @@ public class DataPacketService implements IPluginOutDataPacketService,
     }
 
     void setPluginInDataService(Map props, IPluginInDataPacketService s) {
-        if (this.pluginInDataService == null) {
-            logger.error("pluginInDataService store null");
-            return;
-        }
-        String type = null;
-        logger.trace("Received setPluginInDataService request");
-        for (Object e : props.entrySet()) {
-            Map.Entry entry = (Map.Entry) e;
-            logger.trace("Prop key:({}) value:({})",entry.getKey(), entry.getValue());
-        }
-
-        Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
-        if (value instanceof String) {
-            type = (String) value;
-        }
-        if (type == null) {
-            logger.error("Received a PluginInDataService without any "
-                    + "protocolPluginType provided");
-        } else {
-            this.pluginInDataService.put(type, s);
-            logger.debug("Stored the PluginInDataService for type: {}", type);
-        }
+        ProtocolService.set(this.pluginInDataService, props, s, logger);
     }
 
     void unsetPluginInDataService(Map props, IPluginInDataPacketService s) {
-        if (this.pluginInDataService == null) {
-            logger.error("pluginInDataService store null");
-            return;
-        }
-
-        String type = null;
-        logger.trace("Received unsetPluginInDataService request");
-        for (Object e : props.entrySet()) {
-            Map.Entry entry = (Map.Entry) e;
-            logger.trace("Prop key:({}) value:({})",entry.getKey(), entry.getValue());
-        }
-
-        Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
-        if (value instanceof String) {
-            type = (String) value;
-        }
-        if (type == null) {
-            logger.error("Received a PluginInDataService without any "
-                    + "protocolPluginType provided");
-        } else if (this.pluginInDataService.get(type).equals(s)) {
-            this.pluginInDataService.remove(type);
-            logger.debug("Removed the PluginInDataService for type: {}", type);
-        }
+        ProtocolService.unset(this.pluginInDataService, props, s, logger);
     }
 
     void setListenDataPacket(Map props, IListenDataPacket s) {
index 854125b3567a196b940556363ed56c82e99d50c0..60a7882bda552b5e2fa5fddfb7ebafad6d51ccbb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -38,7 +38,6 @@ import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerSe
 import org.opendaylight.controller.sal.match.Match;
 import org.opendaylight.controller.sal.match.MatchType;
 import org.opendaylight.controller.sal.utils.EtherTypes;
-import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.IPProtocols;
 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
 import org.opendaylight.controller.sal.utils.Status;
@@ -58,12 +57,12 @@ public class FlowProgrammerService implements IFlowProgrammerService,
 
     protected static final Logger logger = LoggerFactory
             .getLogger(FlowProgrammerService.class);
-    private ConcurrentHashMap<String, IPluginInFlowProgrammerService> pluginFlowProgrammer;
+    private ConcurrentHashMap<String, ProtocolService<IPluginInFlowProgrammerService>> pluginFlowProgrammer;
     private Set<IFlowProgrammerListener> listener;
     private AtomicLong seq;
 
     public FlowProgrammerService() {
-        pluginFlowProgrammer = new ConcurrentHashMap<String, IPluginInFlowProgrammerService>();
+        pluginFlowProgrammer = new ConcurrentHashMap<String, ProtocolService<IPluginInFlowProgrammerService>>();
         listener = new HashSet<IFlowProgrammerListener>();
         seq = new AtomicLong();
         /*
@@ -117,58 +116,11 @@ public class FlowProgrammerService implements IFlowProgrammerService,
 
     // Set the reference to the plugin flow programmer
     public void setService(Map<String, Object> props, IPluginInFlowProgrammerService s) {
-        if (this.pluginFlowProgrammer == null) {
-            logger.error("pluginFlowProgrammer store null");
-            return;
-        }
-
-        if (logger.isTraceEnabled()) {
-            logger.trace("Got a service set request {}", s);
-            for (Map.Entry<String, Object> entry : props.entrySet()) {
-                logger.trace("Prop key:({}) value:({})", entry.getKey(), entry.getValue());
-            }
-        }
-
-        String type = null;
-        Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
-        if (value instanceof String) {
-            type = (String) value;
-        }
-        if (type == null) {
-            logger.error("Received a pluginFlowProgrammer without any "
-                    + "protocolPluginType provided");
-        } else {
-            this.pluginFlowProgrammer.put(type, s);
-            logger.debug("Stored the pluginFlowProgrammer for type: {}", type);
-        }
+        ProtocolService.set(this.pluginFlowProgrammer, props, s, logger);
     }
 
     public void unsetService(Map<String, Object> props, IPluginInFlowProgrammerService s) {
-        if (this.pluginFlowProgrammer == null) {
-            logger.error("pluginFlowProgrammer store null");
-            return;
-        }
-
-        logger.debug("Received unsetpluginFlowProgrammer request");
-        if (logger.isTraceEnabled()) {
-            logger.trace("Got a service set request {}", s);
-            for (Map.Entry<String, Object> entry : props.entrySet()) {
-                logger.trace("Prop key:({}) value:({})", entry.getKey(), entry.getValue());
-            }
-        }
-
-        String type = null;
-        Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
-        if (value instanceof String) {
-            type = (String) value;
-        }
-        if (type == null) {
-            logger.error("Received a pluginFlowProgrammer without any "
-                    + "protocolPluginType provided");
-        } else if (this.pluginFlowProgrammer.get(type).equals(s)) {
-            this.pluginFlowProgrammer.remove(type);
-            logger.debug("Removed the pluginFlowProgrammer for type: {}", type);
-        }
+        ProtocolService.unset(this.pluginFlowProgrammer, props, s, logger);
     }
 
     public void setListener(IFlowProgrammerListener s) {
@@ -182,9 +134,10 @@ public class FlowProgrammerService implements IFlowProgrammerService,
     @Override
     public Status addFlow(Node node, Flow flow) {
         if (pluginFlowProgrammer != null) {
-            if (this.pluginFlowProgrammer.get(node.getType()) != null) {
-                return this.pluginFlowProgrammer.get(node.getType()).addFlow(
-                        node, flow);
+            ProtocolService<IPluginInFlowProgrammerService> service =
+                this.pluginFlowProgrammer.get(node.getType());
+            if (service != null) {
+                return service.getService().addFlow(node, flow);
             }
         }
         return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
@@ -193,9 +146,10 @@ public class FlowProgrammerService implements IFlowProgrammerService,
     @Override
     public Status removeFlow(Node node, Flow flow) {
         if (pluginFlowProgrammer != null) {
-            if (this.pluginFlowProgrammer.get(node.getType()) != null) {
-                return this.pluginFlowProgrammer.get(node.getType())
-                        .removeFlow(node, flow);
+            ProtocolService<IPluginInFlowProgrammerService> service =
+                this.pluginFlowProgrammer.get(node.getType());
+            if (service != null) {
+                return service.getService().removeFlow(node, flow);
             }
         }
         return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
@@ -204,9 +158,10 @@ public class FlowProgrammerService implements IFlowProgrammerService,
     @Override
     public Status removeAllFlows(Node node) {
         if (pluginFlowProgrammer != null) {
-            if (this.pluginFlowProgrammer.get(node.getType()) != null) {
-                return this.pluginFlowProgrammer.get(node.getType())
-                        .removeAllFlows(node);
+            ProtocolService<IPluginInFlowProgrammerService> service =
+                this.pluginFlowProgrammer.get(node.getType());
+            if (service != null) {
+                return service.getService().removeAllFlows(node);
             }
         }
         return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
@@ -215,9 +170,10 @@ public class FlowProgrammerService implements IFlowProgrammerService,
     @Override
     public Status modifyFlow(Node node, Flow oldFlow, Flow newFlow) {
         if (pluginFlowProgrammer != null) {
-            if (this.pluginFlowProgrammer.get(node.getType()) != null) {
-                return this.pluginFlowProgrammer.get(node.getType())
-                        .modifyFlow(node, oldFlow, newFlow);
+            ProtocolService<IPluginInFlowProgrammerService> service =
+                this.pluginFlowProgrammer.get(node.getType());
+            if (service != null) {
+                return service.getService().modifyFlow(node, oldFlow, newFlow);
             }
         }
         return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
@@ -226,9 +182,10 @@ public class FlowProgrammerService implements IFlowProgrammerService,
     @Override
     public Status addFlowAsync(Node node, Flow flow) {
         if (pluginFlowProgrammer != null) {
-            if (this.pluginFlowProgrammer.get(node.getType()) != null) {
-                return this.pluginFlowProgrammer.get(node.getType()).addFlowAsync(
-                        node, flow, getNextRid());
+            ProtocolService<IPluginInFlowProgrammerService> service =
+                this.pluginFlowProgrammer.get(node.getType());
+            if (service != null) {
+                return service.getService().addFlowAsync(node, flow, getNextRid());
             }
         }
         return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
@@ -237,9 +194,10 @@ public class FlowProgrammerService implements IFlowProgrammerService,
     @Override
     public Status removeFlowAsync(Node node, Flow flow) {
         if (pluginFlowProgrammer != null) {
-            if (this.pluginFlowProgrammer.get(node.getType()) != null) {
-                return this.pluginFlowProgrammer.get(node.getType())
-                        .removeFlowAsync(node, flow, getNextRid());
+            ProtocolService<IPluginInFlowProgrammerService> service =
+                this.pluginFlowProgrammer.get(node.getType());
+            if (service != null) {
+                return service.getService().removeFlowAsync(node, flow, getNextRid());
             }
         }
         return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
@@ -248,9 +206,10 @@ public class FlowProgrammerService implements IFlowProgrammerService,
     @Override
     public Status modifyFlowAsync(Node node, Flow oldFlow, Flow newFlow) {
         if (pluginFlowProgrammer != null) {
-            if (this.pluginFlowProgrammer.get(node.getType()) != null) {
-                return this.pluginFlowProgrammer.get(node.getType())
-                        .modifyFlowAsync(node, oldFlow, newFlow, getNextRid());
+            ProtocolService<IPluginInFlowProgrammerService> service =
+                this.pluginFlowProgrammer.get(node.getType());
+            if (service != null) {
+                return service.getService().modifyFlowAsync(node, oldFlow, newFlow, getNextRid());
             }
         }
         return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
@@ -508,9 +467,10 @@ public class FlowProgrammerService implements IFlowProgrammerService,
     @Override
     public Status syncSendBarrierMessage(Node node) {
         if (this.pluginFlowProgrammer != null) {
-            if (this.pluginFlowProgrammer.get(node.getType()) != null) {
-                return this.pluginFlowProgrammer.get(node.getType())
-                        .syncSendBarrierMessage(node);
+            ProtocolService<IPluginInFlowProgrammerService> service =
+                this.pluginFlowProgrammer.get(node.getType());
+            if (service != null) {
+                return service.getService().syncSendBarrierMessage(node);
             }
         }
         return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
@@ -519,9 +479,10 @@ public class FlowProgrammerService implements IFlowProgrammerService,
     @Override
     public Status asyncSendBarrierMessage(Node node) {
         if (this.pluginFlowProgrammer != null) {
-            if (this.pluginFlowProgrammer.get(node.getType()) != null) {
-                return this.pluginFlowProgrammer.get(node.getType())
-                        .asyncSendBarrierMessage(node);
+            ProtocolService<IPluginInFlowProgrammerService> service =
+                this.pluginFlowProgrammer.get(node.getType());
+            if (service != null) {
+                return service.getService().asyncSendBarrierMessage(node);
             }
         }
         return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
diff --git a/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/ProtocolService.java b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/ProtocolService.java
new file mode 100644 (file)
index 0000000..e9dc2ad
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2014 NEC Corporation 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.implementation.internal;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+
+import org.slf4j.Logger;
+
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+
+/**
+ * An instance of this class keeps a protocol plugin service handler.
+ *
+ * @param <T>  Type of protocol plugin service.
+ */
+public final class ProtocolService<T> {
+    /**
+     * Default priority value.
+     */
+    private static final int  DEFAULT_PRIORITY = 0;
+
+    /**
+     * A protocol plugin service handler.
+     */
+    private final T  service;
+
+    /**
+     * A priority value assigned to this protocol plugin.
+     */
+    private final int  priority;
+
+    /**
+     * Set protocol plugin service.
+     *
+     * @param map     A map that keeps protocol plugin services.
+     * @param props   Service properties.
+     * @param s       Protocol plugin service.
+     * @param logger  A logger instance.
+     * @param <S>     Type of protocol plugin service.
+     */
+    public static <S> void set(ConcurrentMap<String, ProtocolService<S>> map,
+                               Map<?, ?> props, S s, Logger logger) {
+        if (map == null) {
+            logger.error("Protocol plugin service store is null.");
+            return;
+        }
+        if (s == null) {
+            logger.error("Protocol plugin service is null.");
+            return;
+        }
+        if (props == null) {
+            logger.error("Service property is null.");
+            return;
+        }
+
+        if (logger.isTraceEnabled()) {
+            logger.trace("Received set service request: {}", s);
+            for (Map.Entry<?, ?> entry: props.entrySet()) {
+                logger.trace("Prop key:({}) value:({})", entry.getKey(),
+                             entry.getValue());
+            }
+        }
+
+        Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
+        if (!(value instanceof String)) {
+            logger.error("Unexpected protocol type: {}", value);
+            return;
+        }
+
+        String type = (String)value;
+        ProtocolService<S> service = new ProtocolService<S>(props, s);
+        ProtocolService<S> old = map.putIfAbsent(type, service);
+        while (old != null) {
+            // Compare priority value.
+            if (old.getPriority() >= service.getPriority()) {
+                logger.trace("Protocol plugin service for {} is already set: " +
+                             "current={}, requested={}", type, old, service);
+                return;
+            }
+
+            if (map.replace(type, old, service)) {
+                break;
+            }
+            old = map.putIfAbsent(type, service);
+        }
+
+        logger.debug("Stored protocol plugin service for {}: {}",
+                     type, service);
+    }
+
+    /**
+     * Unset protocol plugin service.
+     *
+     * @param map     A map that keeps protocol plugin services.
+     * @param props   Service properties.
+     * @param s       Protocol plugin service.
+     * @param logger  A logger instance.
+     * @param <S>     Type of protocol plugin service.
+     */
+    public static <S> void unset(ConcurrentMap<String, ProtocolService<S>> map,
+                                 Map<?, ?> props, S s, Logger logger) {
+        if (map == null) {
+            logger.error("Protocol plugin service store is null.");
+            return;
+        }
+        if (s == null) {
+            logger.error("Protocol plugin service is null.");
+            return;
+        }
+        if (props == null) {
+            logger.error("Service property is null.");
+            return;
+        }
+
+        if (logger.isTraceEnabled()) {
+            logger.trace("Received unset service request: {}", s);
+            for (Map.Entry<?, ?> entry: props.entrySet()) {
+                logger.trace("Prop key:({}) value:({})",
+                             entry.getKey(), entry.getValue());
+            }
+        }
+
+        Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
+        if (!(value instanceof String)) {
+            logger.error("Unexpected protocol type {}: service={}", value, s);
+            return;
+        }
+
+        String type = (String)value;
+        ProtocolService<S> plugin = new ProtocolService<S>(props, s);
+        if (map.remove(type, plugin)) {
+            logger.debug("Removed protocol plugin service for {}: {}",
+                         type, plugin);
+        } else {
+            logger.trace("Ignore unset service request for {}: {}",
+                         type, plugin);
+        }
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param props  Protocol plugin service properties.
+     * @param s      A protocol plugin service handler.
+     */
+    public ProtocolService(Map<?, ?> props, T s) {
+        service = s;
+
+        String key = GlobalConstants.PROTOCOLPLUGINPRIORITY.toString();
+        Object value = props.get(key);
+        if (value instanceof Integer) {
+            priority = ((Integer)value).intValue();
+        } else {
+            priority = DEFAULT_PRIORITY;
+        }
+    }
+
+    /**
+     * Return a protocol plugin service handler.
+     *
+     * @return  A protocol plugin service handler.
+     */
+    public T getService() {
+        return service;
+    }
+
+    /**
+     * Return a priority value assigned to this protocol plugin.
+     *
+     * @return  A priority value.
+     */
+    public int getPriority() {
+        return priority;
+    }
+
+    /**
+     * Determine whether the given object is identical to this object.
+     *
+     * @param o  An object to be compared.
+     * @return   {@code true} if identical. Otherwise {@code false}.
+     */
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (o == null || o.getClass() != getClass()) {
+            return false;
+        }
+
+        ProtocolService plugin = (ProtocolService)o;
+        return (service.equals(plugin.service) && priority == plugin.priority);
+    }
+
+    /**
+     * Return the hash code of this object.
+     *
+     * @return  The hash code.
+     */
+    @Override
+    public int hashCode() {
+        return service.hashCode() + (priority * 31);
+    }
+
+    /**
+     * Return a string representation of this instance.
+     *
+     * @return  A string representation of this instance.
+     */
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder("[service=");
+        return builder.append(service).append(", priority=").append(priority).
+            append(']').toString();
+    }
+}
index 12de35f53677492581412017e9c763de96a05c0b..356c0e57c887f29f5d448ba523976f8fe077b5da 100644 (file)
@@ -1,6 +1,5 @@
-
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -43,7 +42,6 @@ import org.opendaylight.controller.sal.reader.NodeConnectorStatistics;
 import org.opendaylight.controller.sal.reader.NodeDescription;
 import org.opendaylight.controller.sal.reader.NodeTableStatistics;
 import org.opendaylight.controller.sal.utils.EtherTypes;
-import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.IPProtocols;
 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
 import org.opendaylight.controller.sal.utils.NodeCreator;
@@ -60,8 +58,8 @@ import org.slf4j.LoggerFactory;
 public class ReadService implements IReadService, CommandProvider, IPluginOutReadService {
 
     protected static final Logger logger = LoggerFactory.getLogger(ReadService.class);
-    private ConcurrentHashMap<String, IPluginInReadService> pluginReader =
-        new ConcurrentHashMap<String, IPluginInReadService>();
+    private ConcurrentHashMap<String, ProtocolService<IPluginInReadService>> pluginReader =
+        new ConcurrentHashMap<String, ProtocolService<IPluginInReadService>>();
     private Set<IReadServiceListener> readerListeners =
         new CopyOnWriteArraySet<IReadServiceListener>();
 
@@ -107,58 +105,13 @@ public class ReadService implements IReadService, CommandProvider, IPluginOutRea
 
     // Set the reference to the plugin flow Reader service
     public void setService(Map<?, ?> props, IPluginInReadService s) {
-        if (this.pluginReader == null) {
-            logger.error("pluginReader store null");
-            return;
-        }
-
-        logger.trace("Got a service set request {}", s);
-        String type = null;
-        for (Object e : props.entrySet()) {
-            Map.Entry<?, ?> entry = (Map.Entry<?, ?>) e;
-            logger.trace("Prop key:({}) value:({})", entry.getKey(),
-                    entry.getValue());
-        }
-
-        Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
-        if (value instanceof String) {
-            type = (String) value;
-        }
-        if (type == null) {
-            logger.error("Received a pluginReader without any "
-                    + "protocolPluginType provided");
-        } else {
-            this.pluginReader.put(type, s);
-            logger.debug("Stored the pluginReader for type: {}", type);
-        }
+        ProtocolService.set(this.pluginReader, props, s, logger);
     }
 
     public void unsetService(Map<?, ?> props, IPluginInReadService s) {
-        if (this.pluginReader == null) {
-            logger.error("pluginReader store null");
-            return;
-        }
-
-        String type = null;
-        logger.debug("Received unsetpluginReader request");
-        for (Object e : props.entrySet()) {
-            Map.Entry<?, ?> entry = (Map.Entry<?, ?>) e;
-            logger.trace("Prop key:({}) value:({})", entry.getKey(),
-                    entry.getValue());
-        }
-
-        Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
-        if (value instanceof String) {
-            type = (String) value;
-        }
-        if (type == null) {
-            logger.error("Received a pluginReader without any "
-                    + "protocolPluginType provided");
-        } else if (this.pluginReader.get(type).equals(s)) {
-            this.pluginReader.remove(type);
-            logger.debug("Removed the pluginReader for type: {}", type);
-        }
+        ProtocolService.unset(this.pluginReader, props, s, logger);
     }
+
     public void setReaderListener(IReadServiceListener service) {
         logger.trace("Got a listener set request {}", service);
         this.readerListeners.add(service);
@@ -172,9 +125,10 @@ public class ReadService implements IReadService, CommandProvider, IPluginOutRea
     @Override
     public FlowOnNode readFlow(Node node, Flow flow) {
         if (pluginReader != null) {
-            if (this.pluginReader.get(node.getType()) != null) {
-                return this.pluginReader.get(node.getType())
-                        .readFlow(node, flow, true);
+            ProtocolService<IPluginInReadService> service =
+                this.pluginReader.get(node.getType());
+            if (service != null) {
+                return service.getService().readFlow(node, flow, true);
             }
         }
         logger.warn("Plugin {} unavailable", node.getType());
@@ -184,9 +138,10 @@ public class ReadService implements IReadService, CommandProvider, IPluginOutRea
     @Override
     public FlowOnNode nonCachedReadFlow(Node node, Flow flow) {
         if (pluginReader != null) {
-            if (this.pluginReader.get(node.getType()) != null) {
-                return this.pluginReader.get(node.getType())
-                        .readFlow(node, flow, false);
+            ProtocolService<IPluginInReadService> service =
+                this.pluginReader.get(node.getType());
+            if (service != null) {
+                return service.getService().readFlow(node, flow, false);
             }
         }
         logger.warn("Plugin {} unavailable", node.getType());
@@ -196,9 +151,10 @@ public class ReadService implements IReadService, CommandProvider, IPluginOutRea
     @Override
     public List<FlowOnNode> readAllFlows(Node node) {
         if (pluginReader != null) {
-            if (this.pluginReader.get(node.getType()) != null) {
-                return this.pluginReader.get(node.getType())
-                        .readAllFlow(node, true);
+            ProtocolService<IPluginInReadService> service =
+                this.pluginReader.get(node.getType());
+            if (service != null) {
+                return service.getService().readAllFlow(node, true);
             }
         }
         logger.warn("Plugin {} unavailable", node.getType());
@@ -208,9 +164,10 @@ public class ReadService implements IReadService, CommandProvider, IPluginOutRea
     @Override
     public List<FlowOnNode> nonCachedReadAllFlows(Node node) {
         if (pluginReader != null) {
-            if (this.pluginReader.get(node.getType()) != null) {
-                return this.pluginReader.get(node.getType())
-                        .readAllFlow(node, false);
+            ProtocolService<IPluginInReadService> service =
+                this.pluginReader.get(node.getType());
+            if (service != null) {
+                return service.getService().readAllFlow(node, false);
             }
         }
         logger.warn("Plugin {} unavailable", node.getType());
@@ -220,9 +177,10 @@ public class ReadService implements IReadService, CommandProvider, IPluginOutRea
     @Override
     public NodeDescription readDescription(Node node) {
         if (pluginReader != null) {
-            if (this.pluginReader.get(node.getType()) != null) {
-                return this.pluginReader.get(node.getType())
-                        .readDescription(node, true);
+            ProtocolService<IPluginInReadService> service =
+                this.pluginReader.get(node.getType());
+            if (service != null) {
+                return service.getService().readDescription(node, true);
             }
         }
         logger.warn("Plugin {} unavailable", node.getType());
@@ -232,9 +190,10 @@ public class ReadService implements IReadService, CommandProvider, IPluginOutRea
     @Override
     public NodeDescription nonCachedReadDescription(Node node) {
         if (pluginReader != null) {
-            if (this.pluginReader.get(node.getType()) != null) {
-                return this.pluginReader.get(node.getType())
-                        .readDescription(node, false);
+            ProtocolService<IPluginInReadService> service =
+                this.pluginReader.get(node.getType());
+            if (service != null) {
+                return service.getService().readDescription(node, false);
             }
         }
         logger.warn("Plugin {} unavailable", node.getType());
@@ -245,9 +204,10 @@ public class ReadService implements IReadService, CommandProvider, IPluginOutRea
     public NodeConnectorStatistics readNodeConnector(NodeConnector connector) {
         Node node = connector.getNode();
         if (pluginReader != null && node != null) {
-            if (this.pluginReader.get(node.getType()) != null) {
-                return this.pluginReader.get(node.getType())
-                        .readNodeConnector(connector, true);
+            ProtocolService<IPluginInReadService> service =
+                this.pluginReader.get(node.getType());
+            if (service != null) {
+                return service.getService().readNodeConnector(connector, true);
             }
         }
         logger.warn("Plugin {} unavailable", node.getType());
@@ -259,9 +219,10 @@ public class ReadService implements IReadService, CommandProvider, IPluginOutRea
             NodeConnector connector) {
         Node node = connector.getNode();
         if (pluginReader != null && node != null) {
-            if (this.pluginReader.get(node.getType()) != null) {
-                return this.pluginReader.get(node.getType())
-                        .readNodeConnector(connector, false);
+            ProtocolService<IPluginInReadService> service =
+                this.pluginReader.get(node.getType());
+            if (service != null) {
+                return service.getService().readNodeConnector(connector, false);
             }
         }
         logger.warn("Plugin {} unavailable", node.getType());
@@ -271,9 +232,10 @@ public class ReadService implements IReadService, CommandProvider, IPluginOutRea
     @Override
     public List<NodeConnectorStatistics> readNodeConnectors(Node node) {
         if (pluginReader != null) {
-            if (this.pluginReader.get(node.getType()) != null) {
-                return this.pluginReader.get(node.getType())
-                        .readAllNodeConnector(node, true);
+            ProtocolService<IPluginInReadService> service =
+                this.pluginReader.get(node.getType());
+            if (service != null) {
+                return service.getService().readAllNodeConnector(node, true);
             }
         }
         logger.warn("Plugin {} unavailable", node.getType());
@@ -283,9 +245,10 @@ public class ReadService implements IReadService, CommandProvider, IPluginOutRea
     @Override
     public List<NodeTableStatistics> readNodeTable(Node node) {
         if (pluginReader != null) {
-            if (this.pluginReader.get(node.getType()) != null) {
-                return this.pluginReader.get(node.getType())
-                        .readAllNodeTable(node, true);
+            ProtocolService<IPluginInReadService> service =
+                this.pluginReader.get(node.getType());
+            if (service != null) {
+                return service.getService().readAllNodeTable(node, true);
             }
         }
         logger.warn("Plugin {} unavailable", node.getType());
@@ -297,9 +260,10 @@ public class ReadService implements IReadService, CommandProvider, IPluginOutRea
     public NodeTableStatistics nonCachedReadNodeTable(NodeTable table) {
         Node node = table.getNode();
         if (pluginReader != null && node != null) {
-            if (this.pluginReader.get(node.getType()) != null) {
-                return this.pluginReader.get(node.getType())
-                        .readNodeTable(table, false);
+            ProtocolService<IPluginInReadService> service =
+                this.pluginReader.get(node.getType());
+            if (service != null) {
+                return service.getService().readNodeTable(table, false);
             }
         }
         logger.warn("Plugin {} unavailable", node.getType());
@@ -310,9 +274,10 @@ public class ReadService implements IReadService, CommandProvider, IPluginOutRea
     public NodeTableStatistics readNodeTable(NodeTable table) {
         Node node = table.getNode();
         if (pluginReader != null && node != null) {
-            if (this.pluginReader.get(node.getType()) != null) {
-                return this.pluginReader.get(node.getType())
-                        .readNodeTable(table, true);
+            ProtocolService<IPluginInReadService> service =
+                this.pluginReader.get(node.getType());
+            if (service != null) {
+                return service.getService().readNodeTable(table, true);
             }
         }
         logger.warn("Plugin {} unavailable", node.getType());
@@ -322,9 +287,10 @@ public class ReadService implements IReadService, CommandProvider, IPluginOutRea
     @Override
     public List<NodeConnectorStatistics> nonCachedReadNodeConnectors(Node node) {
         if (pluginReader != null) {
-            if (this.pluginReader.get(node.getType()) != null) {
-                return this.pluginReader.get(node.getType())
-                        .readAllNodeConnector(node, false);
+            ProtocolService<IPluginInReadService> service =
+                this.pluginReader.get(node.getType());
+            if (service != null) {
+                return service.getService().readAllNodeConnector(node, false);
             }
         }
         logger.warn("Plugin {} unavailable", node.getType());
@@ -335,9 +301,10 @@ public class ReadService implements IReadService, CommandProvider, IPluginOutRea
     public long getTransmitRate(NodeConnector connector) {
         Node node = connector.getNode();
         if (pluginReader != null && node != null) {
-            if (this.pluginReader.get(node.getType()) != null) {
-                return this.pluginReader.get(node.getType())
-                        .getTransmitRate(connector);
+            ProtocolService<IPluginInReadService> service =
+                this.pluginReader.get(node.getType());
+            if (service != null) {
+                return service.getService().getTransmitRate(connector);
             }
         }
         logger.warn("Plugin {} unavailable", node.getType());
diff --git a/opendaylight/sal/implementation/src/test/java/org/opendaylight/controller/sal/implementation/ProtocolServiceTest.java b/opendaylight/sal/implementation/src/test/java/org/opendaylight/controller/sal/implementation/ProtocolServiceTest.java
new file mode 100644 (file)
index 0000000..079350b
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2014 NEC Corporation 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.implementation;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.controller.sal.implementation.internal.ProtocolService;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+
+/**
+ * Unit test for {@link ProtocolService}.
+ */
+public class ProtocolServiceTest {
+    private static final Logger LOG =
+        LoggerFactory.getLogger(ProtocolServiceTest.class);
+
+    @Test
+    public void testInstance() {
+        HashSet<ProtocolService<ITestService>> set = new HashSet<>();
+        TestService sv1 = new TestService();
+        HashMap<String, Object> prop1 = new HashMap<>();
+
+        ProtocolService<ITestService> ps1 =
+            new ProtocolService<ITestService>(prop1, sv1);
+        assertEquals(sv1, ps1.getService());
+        // Default priority is 0.
+        assertEquals(0, ps1.getPriority());
+        assertTrue(set.add(ps1));
+        assertFalse(set.add(ps1));
+
+        // Specify the same service and priority.
+        String priKey = GlobalConstants.PROTOCOLPLUGINPRIORITY.toString();
+        prop1.put(priKey, Integer.valueOf(0));
+        ProtocolService<ITestService> ps2 =
+            new ProtocolService<ITestService>(prop1, sv1);
+        assertEquals(sv1, ps2.getService());
+        assertEquals(0, ps2.getPriority());
+        assertEquals(ps1, ps2);
+        assertFalse(set.add(ps1));
+
+        // Specify different priority.
+        prop1.put(priKey, Integer.valueOf(Integer.MAX_VALUE));
+        ps2 = new ProtocolService<ITestService>(prop1, sv1);
+        assertEquals(sv1, ps2.getService());
+        assertEquals(Integer.MAX_VALUE, ps2.getPriority());
+        assertFalse(ps1.equals(ps2));
+        assertTrue(set.add(ps2));
+        assertFalse(set.add(ps2));
+
+        // Specify another service.
+        TestService sv2 = new TestService();
+        prop1.put(priKey, Integer.valueOf(0));
+        ps2 = new ProtocolService<ITestService>(prop1, sv2);
+        assertEquals(sv2, ps2.getService());
+        assertEquals(0, ps2.getPriority());
+        assertFalse(ps1.equals(ps2));
+        assertTrue(set.add(ps2));
+        assertFalse(set.add(ps2));
+    }
+
+    @Test
+    public void testSetUnsetError() {
+        ConcurrentMap<String, ProtocolService<ITestService>> services =
+            new ConcurrentHashMap<>();
+        TestService sv = new TestService();
+        Map<String, Object> props = new HashMap<>();
+
+        // null service.
+        ProtocolService.set(services, props, null, LOG);
+        assertTrue(services.isEmpty());
+
+        ProtocolService.unset(services, props, null, LOG);
+        assertTrue(services.isEmpty());
+
+        // null service property.
+        ProtocolService.set(services, null, sv, LOG);
+        assertTrue(services.isEmpty());
+
+        ProtocolService.unset(services, null, sv, LOG);
+        assertTrue(services.isEmpty());
+
+        // Type is not specified.
+        ProtocolService.set(services, props, sv, LOG);
+        assertTrue(services.isEmpty());
+
+        ProtocolService.unset(services, props, sv, LOG);
+        assertTrue(services.isEmpty());
+
+        // null service map.
+        final String typeKey = GlobalConstants.PROTOCOLPLUGINTYPE.toString();
+        assertEquals(null, props.put(typeKey, "OF"));
+        ProtocolService.set(null, props, sv, LOG);
+        assertTrue(services.isEmpty());
+
+        ProtocolService.unset(null, props, sv, LOG);
+        assertTrue(services.isEmpty());
+    }
+
+    @Test
+    public void testSetUnset() {
+        ConcurrentMap<String, ProtocolService<ITestService>> serviceMap =
+            new ConcurrentHashMap<>();
+        ConcurrentMap<String, ProtocolService<ITestService>> expected =
+            new ConcurrentHashMap<>();
+
+        final String typeKey = GlobalConstants.PROTOCOLPLUGINTYPE.toString();
+        final String priKey = GlobalConstants.PROTOCOLPLUGINPRIORITY.toString();
+        final String[] protocols = {"OF", "PE", "PK"};
+        final int basePri = 0;
+        final int loop = 5;
+
+        // Should override the service if higher priority is specified.
+        for (String proto: protocols) {
+            for (int pri = basePri - loop + 1; pri <= basePri; pri++) {
+                TestService sv = new TestService();
+                Map<String, Object> props = new HashMap<>();
+                assertEquals(null, props.put(typeKey, proto));
+                assertEquals(null, props.put(priKey, Integer.valueOf(pri)));
+                ProtocolService.set(serviceMap, props, sv, LOG);
+
+                ProtocolService<ITestService> service = serviceMap.get(proto);
+                assertNotNull(service);
+                assertEquals(sv, service.getService());
+                assertEquals(pri, service.getPriority());
+
+                ProtocolService<ITestService> service1 =
+                    new ProtocolService<ITestService>(props, sv);
+                expected.put(proto, service1);
+                assertEquals(expected, serviceMap);
+
+                // Unset service request should be ignored if different
+                // parameters are specified.
+                TestService another = new TestService();
+                ProtocolService.unset(serviceMap, props, another, LOG);
+                assertEquals(expected, serviceMap);
+
+                props.put(priKey, Integer.valueOf(Integer.MAX_VALUE));
+                ProtocolService.unset(serviceMap, props, sv, LOG);
+                assertEquals(expected, serviceMap);
+            }
+        }
+
+        // Should reject the set service request if lower priority is specified.
+        for (String proto: protocols) {
+            for (int pri = basePri - loop; pri < basePri; pri++) {
+                TestService sv = new TestService();
+                Map<String, Object> props = new HashMap<>();
+                assertEquals(null, props.put(typeKey, proto));
+                assertEquals(null, props.put(priKey, Integer.valueOf(pri)));
+                ProtocolService.set(serviceMap, props, sv, LOG);
+                assertEquals(expected, serviceMap);
+            }
+        }
+
+        // Unset protocol services.
+        for (String proto: protocols) {
+            ProtocolService<ITestService> service = expected.remove(proto);
+            assertNotNull(service);
+
+            ITestService sv = service.getService();
+            Map<String, Object> props = new HashMap<>();
+            assertEquals(null, props.put(typeKey, proto));
+            assertEquals(null, props.put(priKey, Integer.valueOf(basePri)));
+            ProtocolService.unset(serviceMap, props, sv, LOG);
+            assertEquals(expected, serviceMap);
+
+            // Should be ignored if the specified service does not exist.
+            ProtocolService.unset(serviceMap, props, sv, LOG);
+            assertEquals(expected, serviceMap);
+        }
+
+        assertTrue(serviceMap.isEmpty());
+    }
+}
+
+interface ITestService {
+}
+
+class TestService implements ITestService {
+}
index 5854d5577fe007be058adc5db033c4746d220dc3..d39241757fea07732c7920340fd3fdd5ebf37c7d 100644 (file)
@@ -81,7 +81,7 @@
           <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal</artifactId>
-            <version>0.7.1-SNAPSHOT</version>
+            <version>${sal.version}</version>
           </dependency>
         </dependencies>
       </plugin>
index 6e7fd25e049a17fc997b30c5d2003227e1b9a61f..5e638cf9cc86c3bfbbeef4085cc0dabea51e8c64 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -1191,7 +1191,7 @@ one.f.flows = {
             var h3 = "Set Transport Source Port";
             var placeholder = "Transport Source Port";
             var id = one.f.flows.id.modal.action.modifyTransportSourcePort;
-            var help = "Range: 1 - 65535";
+            var help = "Range: 0 - 65535";
             var action = 'SET_TP_SRC';
             var name = "Source Port";
             var body = function() {
@@ -1207,7 +1207,7 @@ one.f.flows = {
             var h3 = "Set Transport Destination Port";
             var placeholder = "Transport Destination Port";
             var id = one.f.flows.id.modal.action.modifyTransportDestinationPort;
-            var help = "Range: 1 - 65535";
+            var help = "Range: 0 - 65535";
             var action = 'SET_TP_DST';
             var name = "Destination Port";
             var body = function() {
diff --git a/pom.xml b/pom.xml
index f3f777f8570457488bfa21ec19c767218c39fbe1..10c05e254f84d88d25f1e3e9b5ef3da3af84b7a1 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -28,6 +28,7 @@
     <module>opendaylight/forwardingrulesmanager/implementation</module>
     <module>opendaylight/hosttracker/api</module>
     <module>opendaylight/hosttracker/implementation</module>
+    <module>opendaylight/hosttracker/shell</module>
     <module>opendaylight/hosttracker_new/api</module>
     <module>opendaylight/hosttracker_new/implementation</module>
     <module>opendaylight/containermanager/api</module>
@@ -45,6 +46,7 @@
     <module>opendaylight/connectionmanager/api</module>
     <module>opendaylight/connectionmanager/implementation</module>
     <module>opendaylight/security</module>
+    <module>opendaylight/karaf-tomcat-security</module>
 
     <!-- third-parties uncomment them if you need snapshot version of it -->
     <!-- <module>third-party/openflowj</module> -->
     <module>opendaylight/distribution/opendaylight-karaf</module>
     <module>opendaylight/distribution/opendaylight-karaf-resources</module>
     <module>features</module>
+
+    <!-- archetypes -->
+    <module>opendaylight/archetypes</module>
   </modules>
   <scm>
     <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>