Merge "Custom mailbox that is bounded and instrumented."
authorMoiz Raja <moraja@cisco.com>
Tue, 19 Aug 2014 16:54:17 +0000 (16:54 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 19 Aug 2014 16:54:17 +0000 (16:54 +0000)
187 files changed:
.gitignore
features/config-netty/pom.xml
features/config-persister/pom.xml
features/config/pom.xml
features/config/src/main/resources/features.xml
features/flow/pom.xml
features/mdsal/pom.xml
features/protocol-framework/pom.xml
opendaylight/commons/opendaylight/pom.xml
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtil.java
opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/JmxAttributeValidationExceptionTest.java [new file with mode: 0644]
opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/ValidationExceptionTest.java [new file with mode: 0644]
opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtilTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BlankTransactionServiceTracker.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/ModuleFactoryBundleTracker.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelper.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/ModuleQNameUtil.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/OsgiRegistrationUtil.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/BlankTransactionServiceTrackerTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/BundleContextBackedModuleFactoriesResolverTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/ExtensibleBundleTrackerTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/ModuleFactoryBundleTrackerTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelperTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/ObjectNameUtilTest.java [deleted file]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/OsgiRegistrationUtilTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/AbstractTestingFixedThreadPoolModuleFactory.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/test/SimpleConfigurationTest.java
opendaylight/config/config-manager/src/test/resources/module-factories/module-factory-fail [new file with mode: 0644]
opendaylight/config/config-manager/src/test/resources/module-factories/module-factory-ok [new file with mode: 0644]
opendaylight/config/netconf-config-dispatcher/pom.xml
opendaylight/config/netconf-config-dispatcher/src/test/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModuleTest.java [new file with mode: 0644]
opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/ImmediateEventExecutorModuleTest.java [new file with mode: 0644]
opendaylight/config/netty-timer-config/src/test/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleTest.java [moved from opendaylight/config/netty-timer-config/src/test/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleTest.java with 99% similarity]
opendaylight/distribution/opendaylight-karaf-empty/pom.xml [new file with mode: 0644]
opendaylight/distribution/opendaylight-karaf-resources/pom.xml [new file with mode: 0644]
opendaylight/distribution/opendaylight-karaf-resources/src/main/resources/bin/instance [moved from opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/instance with 100% similarity]
opendaylight/distribution/opendaylight-karaf-resources/src/main/resources/bin/instance.bat [moved from opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/instance.bat with 100% similarity]
opendaylight/distribution/opendaylight-karaf-resources/src/main/resources/bin/karaf [moved from opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/karaf with 100% similarity]
opendaylight/distribution/opendaylight-karaf-resources/src/main/resources/bin/karaf.bat [moved from opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/karaf.bat with 100% similarity]
opendaylight/distribution/opendaylight-karaf-resources/src/main/resources/configuration/context.xml [moved from opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/context.xml with 100% similarity]
opendaylight/distribution/opendaylight-karaf-resources/src/main/resources/configuration/logback.xml [moved from opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/logback.xml with 100% similarity]
opendaylight/distribution/opendaylight-karaf-resources/src/main/resources/configuration/tomcat-logging.properties [moved from opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/tomcat-logging.properties with 100% similarity]
opendaylight/distribution/opendaylight-karaf-resources/src/main/resources/configuration/tomcat-server.xml [moved from opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/tomcat-server.xml with 100% similarity]
opendaylight/distribution/opendaylight-karaf-resources/src/main/resources/etc/custom.properties [moved from opendaylight/distribution/opendaylight-karaf/src/main/resources/etc/custom.properties with 100% similarity]
opendaylight/distribution/opendaylight-karaf-resources/src/main/resources/version.properties [moved from opendaylight/distribution/opendaylight-karaf/src/main/resources/version.properties with 100% similarity]
opendaylight/distribution/opendaylight-karaf/pom.xml
opendaylight/distribution/opendaylight-karaf/src/main/resources/etc/jre.properties [deleted file]
opendaylight/distribution/opendaylight-karaf/src/main/resources/etc/startup.properties [deleted file]
opendaylight/distribution/opendaylight-karaf/src/main/resources/etc/system.properties [deleted file]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractChangeListener.java
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 [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowChangeListener.java
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowProvider.java
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupChangeListener.java
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupProvider.java
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransactionValidator.java [deleted file]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterChangeListener.java
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterProvider.java
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransactionValidator.java [deleted file]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/reconil/FlowNodeReconcilListener.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/reconil/FlowNodeReconcilProvider.java [new file with mode: 0644]
opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.java
opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/NodeChangeCommiter.java
opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-node-inventory.yang
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/AbstractBrokerAwareActivator.java
opendaylight/md-sal/sal-binding-broker/pom.xml
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/BindingAsyncDataBrokerImplModule.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/DataBrokerImplModule.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/DataBrokerImplModuleFactory.java [moved from opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransactionValidator.java with 57% similarity]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/ForwardedCompatibleDataBrokerImplModule.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.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/md/sal/binding/impl/ForwardedBackwardsCompatibleDataBroker.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBindingDataBroker.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/SingletonHolder.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RootDataBrokerImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/forward/DomForwardedDataBrokerImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/yang/opendaylight-binding-broker-impl.yang
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/BindingNormalizedCodecTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/DataBrokerTestCustomizer.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/compat/MultipleAugmentationPutsTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java
opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java
opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/DataServiceTest.java
opendaylight/md-sal/sal-binding-it/src/test/resources/controller.xml
opendaylight/md-sal/sal-clustering-commons/pom.xml
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/xml/codec/InstanceIdentifierForXmlCodec.java [moved from opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/InstanceIdentifierForXmlCodec.java with 99% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/xml/codec/RandomPrefix.java [moved from opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/RandomPrefix.java with 96% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/xml/codec/XmlDocumentUtils.java [moved from opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/XmlDocumentUtils.java with 99% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/xml/codec/XmlStreamUtils.java [moved from opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/XmlStreamUtils.java with 99% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/xml/codec/XmlUtils.java [moved from opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/XmlUtils.java with 99% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/xml/codec/XmlUtilsTest.java [moved from opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/utils/XmlUtilsTest.java with 98% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/org/opendaylight/controller/xml/codec/rpcTest.yang [moved from opendaylight/md-sal/sal-remoterpc-connector/src/test/resources/org/opendaylight/controller/remote/rpc/utils/rpcTest.yang with 100% similarity]
opendaylight/md-sal/sal-distributed-datastore/pom.xml
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/AbstractUntypedActor.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStore.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreFactory.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohort.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/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/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/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 [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomInmemoryDataBrokerModule.java
opendaylight/md-sal/sal-dom-broker/src/main/yang/opendaylight-dom-broker-impl.yang
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/InMemoryDOMDataStore.java
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStoreConfigProperties.java [new file with mode: 0644]
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/yang/opendaylight-inmemory-datastore-provider.yang
opendaylight/md-sal/sal-remoterpc-connector/pom.xml
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/ActorConstants.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcImplementation.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcProvider.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RoutedRpcListener.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RpcBroker.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RpcListener.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RpcManager.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/AddRoutedRpc.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/AddRpc.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRoutedRpc.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRoutedRpcReply.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRpc.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRpcReply.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/InvokeRoutedRpc.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/InvokeRpc.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RemoveRoutedRpc.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RemoveRpc.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RoutingTableData.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/ClusterWrapper.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/ClusterWrapperImpl.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RoutingTableOld.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistryOld.java [deleted file]
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/java/org/opendaylight/controller/remote/rpc/utils/LatestEntryRoutingLogic.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/RoutingLogic.java [new file with mode: 0644]
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/ActorSystemFactoryTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/RemoteRpcProviderTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/RouteRpcListenerTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/RpcBrokerTest.java
opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/RpcListenerTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/RoutingTableOldTest.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistryOldTest.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/gossip/BucketStoreTest.java
opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/gossip/GossiperTest.java
opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/utils/LatestEntryRoutingLogicTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/src/test/resources/application.conf
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/RestconfDocumentedException.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfError.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestPutOperationTest.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/RestconfErrorTest.java
opendaylight/md-sal/samples/toaster-provider/src/main/java/org/opendaylight/controller/config/yang/config/toaster_provider/impl/ToasterProviderModule.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/FlowStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeConnectorStatsTracker.java
opendaylight/md-sal/topology-manager/src/main/java/org/opendaylight/md/controller/topology/manager/FlowCapableTopologyProvider.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITSecureTest.java
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProvider.java
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProviderImpl.java [new file with mode: 0644]
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/osgi/NetconfSSHActivator.java
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/pom.xml [new file with mode: 0644]
opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/AcceptingAuthProvider.java [new file with mode: 0644]
opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/Main.java [new file with mode: 0644]
opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/ModuleBuilderCapability.java [new file with mode: 0644]
opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java [new file with mode: 0644]
opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedGet.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/SendErrorExceptionUtil.java
opendaylight/netconf/pom.xml
pom.xml

index 9144cda4cc6b40ede292b02156e21f99d136e13b..b304ffce87f5f06b1501a33f424225322353f64c 100644 (file)
@@ -28,4 +28,6 @@ maven-eclipse.xml
 .DS_STORE
 .metadata
 opendaylight/md-sal/sal-distributed-datastore/journal
+!opendaylight/distribution/opendaylight-karaf-resources/src/main/resources/bin
+
 
index 2f4b4b1e2198bb4e85cd1c66f19fb6e009cf4626..5fbc463df32f798c757a293da391fc0bc77f76bb 100644 (file)
@@ -9,7 +9,7 @@
   </parent>
   <artifactId>features-config-netty</artifactId>
 
-  <packaging>pom</packaging>
+  <packaging>jar</packaging>
 
   <properties>
     <features.file>features.xml</features.file>
@@ -21,7 +21,6 @@
       <artifactId>features-config-persister</artifactId>
       <classifier>features</classifier>
       <type>xml</type>
-      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-netty-config</artifactId>
     </dependency>
+    <!-- test to validate features.xml -->
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>features-test</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>
   <scm>
index 6dc894134546fabde2a2d7ef2bf71d0673fab5b0..3346c754d628f8fbb03add426db0026bc4af0615 100644 (file)
@@ -9,7 +9,7 @@
   </parent>
   <artifactId>features-config-persister</artifactId>
 
-  <packaging>pom</packaging>
+  <packaging>jar</packaging>
 
   <properties>
     <features.file>features.xml</features.file>
       <version>${yangtools.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
-      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>features-netconf</artifactId>
       <classifier>features</classifier>
       <type>xml</type>
-      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>features-config</artifactId>
       <classifier>features</classifier>
       <type>xml</type>
-      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <groupId>org.eclipse.persistence</groupId>
       <artifactId>org.eclipse.persistence.moxy</artifactId>
     </dependency>
+    <!-- test to validate features.xml -->
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>features-test</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>
   <scm>
index c69e11bed2c91e2a08d936dbffad02c601b12d7f..8c061c27361946cd3bfc62edde9252d2dd069b9b 100644 (file)
@@ -9,7 +9,7 @@
   </parent>
   <artifactId>features-config</artifactId>
 
-  <packaging>pom</packaging>
+  <packaging>jar</packaging>
 
   <properties>
     <features.file>features.xml</features.file>
@@ -22,7 +22,6 @@
       <version>${yangtools.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
-      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-manager</artifactId>
     </dependency>
+    <!-- test the features.xml -->
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>features-test</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>
   <scm>
index 6c0d32427da9508ccd39463e89e716e603bd2101..5027588acb2e9fce758cffffff77388400c21c68 100644 (file)
@@ -6,7 +6,7 @@
   <repository>mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features</repository>
 
   <feature name='odl-config-all' version='${project.version}'>
-    <feature version='${project.version}'>odl-mdsal-common</feature>
+      <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>
       <feature version='${project.version}'>odl-config-core</feature>
index 09bb6c91e6a0bde381f3902c299e59d4d4c7fa11..ac189737d937cd0fb36186847327acff27a74c18 100644 (file)
@@ -9,7 +9,7 @@
   </parent>
   <artifactId>features-flow</artifactId>
 
-  <packaging>pom</packaging>
+  <packaging>jar</packaging>
 
   <properties>
     <features.file>features.xml</features.file>
@@ -22,7 +22,6 @@
       <version>${mdsal.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
-      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <groupId>org.opendaylight.controller.md</groupId>
       <artifactId>forwardingrules-manager</artifactId>
     </dependency>
+    <!-- test to validate features.xml -->
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>features-test</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>
   <scm>
index 4f1ba98e5c5d4f60cc4d0a5a2fcbe7c06706d429..e7b825c48b1173b783291e3e2a1797c4cea64ebc 100644 (file)
@@ -9,7 +9,7 @@
   </parent>
   <artifactId>features-mdsal</artifactId>
 
-  <packaging>pom</packaging>
+  <packaging>jar</packaging>
 
   <properties>
     <features.file>features.xml</features.file>
       <artifactId>features-yangtools</artifactId>
       <classifier>features</classifier>
       <type>xml</type>
-      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>features-config</artifactId>
       <classifier>features</classifier>
       <type>xml</type>
-      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>features-config-persister</artifactId>
       <classifier>features</classifier>
       <type>xml</type>
-      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>features-config-netty</artifactId>
       <classifier>features</classifier>
       <type>xml</type>
-      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <groupId>org.opendaylight.controller.samples</groupId>
       <artifactId>toaster-config</artifactId>
     </dependency>
+    <!-- test to validate features.xml -->
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>features-test</artifactId>
+      <version>0.6.2-SNAPSHOT</version>
+    </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>
   <scm>
index 97836be4552f88e4ad960981ebea186e664a090f..dcd24d62169ee16d8e21d24d0469af5a9ba4bbbb 100644 (file)
@@ -9,7 +9,7 @@
   </parent>
   <artifactId>features-protocol-framework</artifactId>
   <version>${protocol-framework.version}</version>
-  <packaging>pom</packaging>
+  <packaging>jar</packaging>
 
   <properties>
     <features.file>features.xml</features.file>
       <artifactId>features-config</artifactId>
       <classifier>features</classifier>
       <type>xml</type>
-      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>protocol-framework</artifactId>
     </dependency>
+    <!-- test to validate features.xml -->
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>features-test</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>
   <scm>
index c74e7ae4108297abcb2799f0a7f81c4b23d892b6..1064afd82d53fcdcdf6714421b5702535a2d6180 100644 (file)
         <artifactId>toaster-config</artifactId>
         <version>${mdsal.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>features-test</artifactId>
+        <version>${yangtools.version}</version>
+        <scope>test</scope>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.yangtools</groupId>
         <artifactId>features-yangtools</artifactId>
index d60e6086176daebd69f58a795ccadd4f24eca4de..abb9f1ae9bf4d448c78bc795a74f0076b68de745 100644 (file)
@@ -35,7 +35,6 @@ public class ObjectNameUtil {
     public static final String SERVICE_QNAME_KEY = "serviceQName";
     public static final String INSTANCE_NAME_KEY = "instanceName";
     public static final String TYPE_KEY = ConfigRegistryConstants.TYPE_KEY;
-    public static final String TYPE_CONFIG_REGISTRY = ConfigRegistryConstants.TYPE_CONFIG_REGISTRY;
     public static final String TYPE_CONFIG_TRANSACTION = "ConfigTransaction";
     public static final String TYPE_MODULE = "Module";
     public static final String TYPE_SERVICE_REFERENCE = "ServiceReference";
@@ -43,6 +42,7 @@ public class ObjectNameUtil {
     public static final String TRANSACTION_NAME_KEY = "TransactionName";
     public static final String REF_NAME_KEY = "RefName";
     private static final String REPLACED_QUOTATION_MARK = "\\?";
+    public static final String ON_WILDCARD = "*";
 
     public static ObjectName createON(String on) {
         try {
@@ -304,12 +304,9 @@ public class ObjectNameUtil {
 
     public static ObjectName createModulePattern(String moduleName,
                                                  String instanceName) {
-        if (moduleName == null) {
-            moduleName = "*";
-        }
-        if (instanceName == null) {
-            instanceName = "*";
-        }
+        moduleName = moduleName == null ? ON_WILDCARD : moduleName;
+        instanceName = instanceName == null ? ON_WILDCARD : instanceName;
+
         // do not return object names containing transaction name
         ObjectName namePattern = ObjectNameUtil
                 .createON(ObjectNameUtil.ON_DOMAIN + ":"
@@ -323,6 +320,10 @@ public class ObjectNameUtil {
 
     public static ObjectName createModulePattern(String ifcName,
                                                  String instanceName, String transactionName) {
+        ifcName = ifcName == null ? ON_WILDCARD : ifcName;
+        instanceName = instanceName == null ? ON_WILDCARD : instanceName;
+        transactionName = transactionName == null ? ON_WILDCARD : transactionName;
+
         return ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN
                 + ":type=Module," + ObjectNameUtil.MODULE_FACTORY_NAME_KEY
                 + "=" + ifcName + "," + ObjectNameUtil.INSTANCE_NAME_KEY + "="
@@ -332,6 +333,9 @@ public class ObjectNameUtil {
 
     public static ObjectName createRuntimeBeanPattern(String moduleName,
                                                       String instanceName) {
+        moduleName = moduleName == null ? ON_WILDCARD : moduleName;
+        instanceName = instanceName == null ? ON_WILDCARD : instanceName;
+
         return ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN + ":"
                 + ObjectNameUtil.TYPE_KEY + "="
                 + ObjectNameUtil.TYPE_RUNTIME_BEAN + ","
diff --git a/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/JmxAttributeValidationExceptionTest.java b/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/JmxAttributeValidationExceptionTest.java
new file mode 100644 (file)
index 0000000..7a057bb
--- /dev/null
@@ -0,0 +1,51 @@
+package org.opendaylight.controller.config.api;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.common.collect.Lists;
+import org.junit.Before;
+import org.junit.Test;
+
+public class JmxAttributeValidationExceptionTest {
+
+    private JmxAttribute jmxAttribute = new JmxAttribute("attr1");
+    private JmxAttribute jmxAttribute2 = new JmxAttribute("attr2");
+
+    @Before
+    public void setUp() throws Exception {
+
+    }
+
+    @Test
+    public void testGetAttributeNames() throws Exception {
+
+    }
+
+    @Test
+    public void testCheckNotNull() throws Exception {
+        try {
+            JmxAttributeValidationException.checkNotNull(false, "message", jmxAttribute);
+        } catch (JmxAttributeValidationException e) {
+            assertJmxEx(e, jmxAttribute.getAttributeName() + " " + "message", jmxAttribute);
+        }
+    }
+
+    @Test
+    public void testWrap() throws Exception {
+
+    }
+
+    @Test
+    public void testCheckCondition() throws Exception {
+        try {
+            JmxAttributeValidationException.checkCondition(false, "message", jmxAttribute);
+        } catch (JmxAttributeValidationException e) {
+            assertJmxEx(e, jmxAttribute.getAttributeName() + " " + "message", jmxAttribute);
+        }
+    }
+
+    private void assertJmxEx(JmxAttributeValidationException e, String message, JmxAttribute... attrNames) {
+        assertEquals(message, e.getMessage());
+        assertEquals(Lists.newArrayList(attrNames), e.getAttributeNames());
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/ValidationExceptionTest.java b/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/ValidationExceptionTest.java
new file mode 100644 (file)
index 0000000..1809e45
--- /dev/null
@@ -0,0 +1,54 @@
+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.assertThat;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import com.google.common.collect.Lists;
+import java.util.Map;
+import org.junit.Test;
+
+public class ValidationExceptionTest {
+
+    private String instance = "instance";
+    private final ModuleIdentifier mi = new ModuleIdentifier("module", instance);
+    private String instance2 = "instance2";
+    private final ModuleIdentifier mi2 = new ModuleIdentifier("module", instance2);
+    private final String message = "ex message";
+    private final Exception e = new IllegalStateException(message);
+
+    @Test
+    public void testCreateFromCollectedValidationExceptions() throws Exception {
+        ValidationException single = ValidationException.createForSingleException(mi, e);
+        ValidationException single2 = ValidationException.createForSingleException(mi2, e);
+
+        ValidationException collected = ValidationException.createFromCollectedValidationExceptions(Lists.newArrayList(single, single2));
+
+        Map<String, Map<String, ValidationException.ExceptionMessageWithStackTrace>> failedMap = collected.getFailedValidations();
+        assertEquals(1, failedMap.size());
+        assertTrue(failedMap.containsKey("module"));
+
+        Map<String, ValidationException.ExceptionMessageWithStackTrace> failedModule = failedMap.get("module");
+        assertEquals(2, failedModule.size());
+        assertTrue(failedModule.containsKey(instance));
+        assertEquals(message, failedModule.get(instance).getMessage());
+        assertEquals(message, failedModule.get(instance2).getMessage());
+        assertEquals(failedModule.get(instance), failedModule.get(instance2));
+    }
+
+    @Test
+    public void testCreateFromCollectedValidationExceptionsWithDuplicate() throws Exception {
+        ValidationException single = ValidationException.createForSingleException(mi, e);
+        ValidationException single2 = ValidationException.createForSingleException(mi, e);
+        try {
+            ValidationException.createFromCollectedValidationExceptions(Lists.newArrayList(single, single2));
+        } catch (IllegalArgumentException ex) {
+            // Duplicate exception
+            assertThat(ex.getMessage(), containsString("Cannot merge"));
+            return;
+        }
+        fail("Duplicate exception should have failed");
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtilTest.java b/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtilTest.java
new file mode 100644 (file)
index 0000000..d3d8469
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * 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.config.api.jmx;
+
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.Maps;
+import java.util.Map;
+import javax.management.ObjectName;
+import junit.framework.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+
+public class ObjectNameUtilTest {
+
+    private String moduleName;
+    private String instanceName;
+
+    @Before
+    public void setUp() throws Exception {
+        moduleName = "module";
+        instanceName = "instance";
+    }
+
+    @Test
+    public void testServiceReferenceName() throws Exception {
+        String serviceQName = "(namespace?revision=r)qname";
+        String refName = "refName";
+        String transaction = "transaction";
+
+        ObjectName serviceReferenceON = ObjectNameUtil.createTransactionServiceON(transaction, serviceQName, refName);
+        ObjectNameUtil.checkType(serviceReferenceON, ObjectNameUtil.TYPE_SERVICE_REFERENCE);
+
+        assertFalse(serviceReferenceON.isPattern());
+        assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
+        assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
+        assertEquals(transaction, ObjectNameUtil.getTransactionName(serviceReferenceON));
+        assertEquals(ObjectNameUtil.createReadOnlyServiceON(serviceQName, refName), ObjectNameUtil.withoutTransactionName(serviceReferenceON));
+
+        serviceReferenceON = ObjectNameUtil.createReadOnlyServiceON(serviceQName, refName);
+        assertFalse(serviceReferenceON.isPattern());
+        assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
+        assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
+        assertEquals(null, ObjectNameUtil.getTransactionName(serviceReferenceON));
+    }
+
+    @Test
+    public void testModuleName() throws Exception {
+        String txName = "transaction";
+
+        ObjectName on = ObjectNameUtil.createTransactionModuleON(txName, moduleName, instanceName);
+
+        ObjectNameUtil.checkDomain(on);
+        ObjectNameUtil.checkType(on, ObjectNameUtil.TYPE_MODULE);
+
+        assertFalse(on.isPattern());
+        assertEquals(moduleName, ObjectNameUtil.getFactoryName(on));
+        assertEquals(instanceName, ObjectNameUtil.getInstanceName(on));
+        assertEquals(txName, ObjectNameUtil.getTransactionName(on));
+        assertEquals(4, ObjectNameUtil.getAdditionalProperties(on).size());
+
+        ObjectName withoutTx = ObjectNameUtil.withoutTransactionName(on);
+        assertEquals(ObjectNameUtil.createReadOnlyModuleON(moduleName, instanceName), withoutTx);
+        assertEquals(moduleName, ObjectNameUtil.getFactoryName(withoutTx));
+        assertEquals(instanceName, ObjectNameUtil.getInstanceName(withoutTx));
+        assertEquals(null, ObjectNameUtil.getTransactionName(withoutTx));
+        assertEquals(on, ObjectNameUtil.withTransactionName(withoutTx, txName));
+
+        ObjectName pattern = ObjectNameUtil.createModulePattern(moduleName, null);
+        assertPattern(withoutTx, pattern);
+        pattern = ObjectNameUtil.createModulePattern(moduleName, null, txName);
+        assertPattern(on, pattern);
+    }
+
+    private void assertPattern(ObjectName test, ObjectName pattern) {
+        assertTrue(pattern.isPattern());
+        assertTrue(pattern.apply(test));
+    }
+
+    @Test
+    public void testRuntimeBeanName() throws Exception {
+
+        Map<String, String> properties = Maps.newHashMap();
+        properties.put("p1", "value");
+        properties.put("p2", "value2");
+
+        ObjectName on = ObjectNameUtil.createRuntimeBeanName(moduleName, instanceName, properties);
+
+        ObjectNameUtil.checkDomain(on);
+        ObjectNameUtil.checkTypeOneOf(on, ObjectNameUtil.TYPE_RUNTIME_BEAN);
+
+        assertFalse(on.isPattern());
+        assertEquals(moduleName, ObjectNameUtil.getFactoryName(on));
+        assertEquals(instanceName, ObjectNameUtil.getInstanceName(on));
+        assertEquals(2, ObjectNameUtil.getAdditionalPropertiesOfRuntimeBeanName(on).size());
+        assertTrue(ObjectNameUtil.getAdditionalPropertiesOfRuntimeBeanName(on).containsKey("p1"));
+        assertEquals("value", ObjectNameUtil.getAdditionalPropertiesOfRuntimeBeanName(on).get("p1"));
+        assertTrue(ObjectNameUtil.getAdditionalProperties(on).containsKey("p2"));
+        assertEquals("value2", ObjectNameUtil.getAdditionalPropertiesOfRuntimeBeanName(on).get("p2"));
+
+        ObjectName pattern = ObjectNameUtil.createRuntimeBeanPattern(null, instanceName);
+        assertPattern(on, pattern);
+    }
+
+    @Test
+    public void testModuleIdentifier() throws Exception {
+        ModuleIdentifier mi = new ModuleIdentifier(moduleName, instanceName);
+        ObjectName on = ObjectNameUtil.createReadOnlyModuleON(mi);
+        assertEquals(moduleName, ObjectNameUtil.getFactoryName(on));
+        assertEquals(instanceName, ObjectNameUtil.getInstanceName(on));
+
+        assertEquals(mi, ObjectNameUtil.fromON(on, ObjectNameUtil.TYPE_MODULE));
+    }
+
+    @Test
+    public void testChecks() throws Exception {
+        final ObjectName on = ObjectNameUtil.createON("customDomain", ObjectNameUtil.TYPE_KEY, ObjectNameUtil.TYPE_MODULE);
+
+        assertFailure(new Runnable() {
+            @Override
+            public void run() {
+                ObjectNameUtil.checkTypeOneOf(on, ObjectNameUtil.TYPE_RUNTIME_BEAN, ObjectNameUtil.TYPE_CONFIG_TRANSACTION);
+            }
+        }, IllegalArgumentException.class);
+
+        assertFailure(new Runnable() {
+            @Override
+            public void run() {
+                ObjectNameUtil.checkType(on, ObjectNameUtil.TYPE_RUNTIME_BEAN);
+            }
+        }, IllegalArgumentException.class);
+
+        assertFailure(new Runnable() {
+            @Override
+            public void run() {
+                ObjectNameUtil.checkDomain(on);
+            }
+        }, IllegalArgumentException.class);
+    }
+
+    private void assertFailure(Runnable test, Class<? extends Exception> ex) {
+        try {
+            test.run();
+        } catch(Exception e) {
+            Assert.assertTrue("Failed with wrong exception: " + Throwables.getStackTraceAsString(e),
+                    e.getClass().isAssignableFrom(ex));
+            return;
+        }
+
+        fail(test + " should have failed on " + ex);
+    }
+}
index 720b7197ea6100b0890ee0fd4a89d5f5de9157bd..375ef5948712f3bcc5dc803802645b1d6fa56103 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.controller.config.manager.impl.osgi;
 
+import com.google.common.annotations.VisibleForTesting;
+import javax.management.ObjectName;
 import org.opendaylight.controller.config.api.ConflictingVersionException;
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.api.jmx.CommitStatus;
@@ -17,8 +19,6 @@ import org.osgi.util.tracker.ServiceTrackerCustomizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.management.ObjectName;
-
 /**
  * Every time factory is added or removed, blank transaction is triggered to handle
  * {@link org.opendaylight.controller.config.spi.ModuleFactory#getDefaultModules(org.opendaylight.controller.config.api.DependencyResolverFactory, org.osgi.framework.BundleContext)}
@@ -27,10 +27,29 @@ import javax.management.ObjectName;
 public class BlankTransactionServiceTracker implements ServiceTrackerCustomizer<ModuleFactory, Object> {
     private static final Logger logger = LoggerFactory.getLogger(BlankTransactionServiceTracker.class);
 
-    private final ConfigRegistryImpl configRegistry;
+    public static final int DEFAULT_MAX_ATTEMPTS = 10;
 
-    public BlankTransactionServiceTracker(ConfigRegistryImpl configRegistry) {
-        this.configRegistry = configRegistry;
+    private final BlankTransaction blankTransaction;
+    private int maxAttempts;
+
+    public BlankTransactionServiceTracker(final ConfigRegistryImpl configRegistry) {
+        this(new BlankTransaction() {
+            @Override
+            public CommitStatus hit() throws ValidationException, ConflictingVersionException {
+                ObjectName tx = configRegistry.beginConfig(true);
+                return configRegistry.commitConfig(tx);
+            }
+        });
+    }
+
+    public BlankTransactionServiceTracker(final BlankTransaction blankTransaction) {
+        this(blankTransaction, DEFAULT_MAX_ATTEMPTS);
+    }
+
+    @VisibleForTesting
+    BlankTransactionServiceTracker(final BlankTransaction blankTx, final int maxAttempts) {
+        this.blankTransaction = blankTx;
+        this.maxAttempts = maxAttempts;
     }
 
     @Override
@@ -42,13 +61,10 @@ public class BlankTransactionServiceTracker implements ServiceTrackerCustomizer<
     synchronized void blankTransaction() {
         // race condition check: config-persister might push new configuration while server is starting up.
         ConflictingVersionException lastException = null;
-        int maxAttempts = 10;
         for (int i = 0; i < maxAttempts; i++) {
             try {
                 // create transaction
-                boolean blankTransaction = true;
-                ObjectName tx = configRegistry.beginConfig(blankTransaction);
-                CommitStatus commitStatus = configRegistry.commitConfig(tx);
+                CommitStatus commitStatus = blankTransaction.hit();
                 logger.debug("Committed blank transaction with status {}", commitStatus);
                 return;
             } catch (ConflictingVersionException e) {
@@ -77,4 +93,9 @@ public class BlankTransactionServiceTracker implements ServiceTrackerCustomizer<
     public void removedService(ServiceReference<ModuleFactory> moduleFactoryServiceReference, Object o) {
         blankTransaction();
     }
+
+    @VisibleForTesting
+    static interface BlankTransaction {
+        CommitStatus hit() throws ValidationException, ConflictingVersionException;
+    }
 }
index 05ca43c3e2d88e01ea9458fc15bc621a0cd9daa4..3015ed229e28f1c04015d9d488d641c9ebceb161 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.controller.config.manager.impl.osgi;
 
 import static java.lang.String.format;
 
+import com.google.common.annotations.VisibleForTesting;
 import java.io.InputStream;
 import java.net.URL;
 import java.util.List;
@@ -70,9 +71,10 @@ public class ModuleFactoryBundleTracker implements BundleTrackerCustomizer<Objec
         blankTransactionServiceTracker.blankTransaction();
     }
 
-    // TODO:test
-    private static ServiceRegistration<?> registerFactory(String factoryClassName, Bundle bundle) {
+    @VisibleForTesting
+    protected static ServiceRegistration<?> registerFactory(String factoryClassName, Bundle bundle) {
         String errorMessage;
+        Exception ex = null;
         try {
             Class<?> clazz = bundle.loadClass(factoryClassName);
             if (ModuleFactory.class.isAssignableFrom(clazz)) {
@@ -86,10 +88,12 @@ public class ModuleFactoryBundleTracker implements BundleTrackerCustomizer<Objec
                     errorMessage = logMessage(
                             "Could not instantiate {} in bundle {}, reason {}",
                             factoryClassName, bundle, e);
+                    ex = e;
                 } catch (IllegalAccessException e) {
                     errorMessage = logMessage(
-                            "Illegal access during instatiation of class {} in bundle {}, reason {}",
+                            "Illegal access during instantiation of class {} in bundle {}, reason {}",
                             factoryClassName, bundle, e);
+                    ex = e;
                 }
             } else {
                 errorMessage = logMessage(
@@ -98,10 +102,12 @@ public class ModuleFactoryBundleTracker implements BundleTrackerCustomizer<Objec
             }
         } catch (ClassNotFoundException e) {
             errorMessage = logMessage(
-                    "Could not find class {} in bunde {}, reason {}",
+                    "Could not find class {} in bundle {}, reason {}",
                     factoryClassName, bundle, e);
+            ex = e;
         }
-        throw new IllegalStateException(errorMessage);
+
+        throw ex == null ? new IllegalStateException(errorMessage) : new IllegalStateException(errorMessage, ex);
     }
 
     public static String logMessage(String slfMessage, Object... params) {
index a6e9b1ba965b8532eb2e688742ca6ec66c5d5e10..510fdf9373f46a7dc0c5f1aa61aabd15d31fbb25 100644 (file)
@@ -109,7 +109,6 @@ public class InterfacesHelper {
      */
     public static Set<Class<?>> getOsgiRegistrationTypes(
             Class<? extends Module> configBeanClass) {
-        // TODO test with service interface hierarchy
         Set<Class<?>> serviceInterfaces = getServiceInterfaces(configBeanClass);
         Set<Class<?>> result = new HashSet<>();
         for (Class<?> clazz : serviceInterfaces) {
index e84337756e4ad6a74200ce1cd60293848b59d3ab..f1072a76ae907d934d13984478c119092c9f0dbd 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.controller.config.manager.impl.util;
 
 import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.opendaylight.yangtools.yang.binding.annotations.ModuleQName;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.osgi.framework.BundleContext;
 
 import java.util.HashSet;
@@ -31,9 +32,7 @@ public class ModuleQNameUtil {
                 inspected = inspected.getSuperclass();
             }
             if (annotation != null) {
-                // FIXME
-                String qName = "(" + annotation.namespace() + "?revision=" + annotation.revision() + ")" + annotation.name();
-                result.add(qName);
+                result.add(QName.create(annotation.namespace(), annotation.revision(), annotation.name()).toString());
             }
         }
         return result;
index 8873596642e43a8c460a8ee18fb7ef5fef8e9733..2df28f0a154b8b7a6e37f1930b5e06d46efda675 100644 (file)
@@ -8,6 +8,11 @@
 
 package org.opendaylight.controller.config.manager.impl.util;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.util.tracker.BundleTracker;
@@ -15,12 +20,6 @@ import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ListIterator;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
 public class OsgiRegistrationUtil {
     private static final Logger logger = LoggerFactory.getLogger(OsgiRegistrationUtil.class);
 
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/BlankTransactionServiceTrackerTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/BlankTransactionServiceTrackerTest.java
new file mode 100644 (file)
index 0000000..471c98a
--- /dev/null
@@ -0,0 +1,83 @@
+package org.opendaylight.controller.config.manager.impl.osgi;
+
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertSame;
+import static junit.framework.Assert.fail;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.Collections;
+import javax.management.ObjectName;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.ServiceReference;
+
+public class BlankTransactionServiceTrackerTest {
+
+    @Mock
+    private BlankTransactionServiceTracker.BlankTransaction blankTx;
+    private BlankTransactionServiceTracker tracker;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        doReturn(new CommitStatus(Collections.<ObjectName>emptyList(), Collections.<ObjectName>emptyList(), Collections.<ObjectName>emptyList())).when(blankTx).hit();
+        tracker = new BlankTransactionServiceTracker(blankTx);
+    }
+
+    @Test
+    public void testBlankTransaction() throws Exception {
+        tracker.addingService(getMockServiceReference());
+        tracker.modifiedService(getMockServiceReference(), null);
+        tracker.removedService(getMockServiceReference(), null);
+        verify(blankTx, times(3)).hit();
+    }
+
+    @Test
+    public void testValidationException() throws Exception {
+        IllegalArgumentException argumentException = new IllegalArgumentException();
+        ValidationException validationException = ValidationException.createForSingleException(new ModuleIdentifier("m", "i"), argumentException);
+        doThrow(validationException).when(blankTx).hit();
+        try {
+            tracker.addingService(getMockServiceReference());
+        } catch (Exception e) {
+            verify(blankTx, times(1)).hit();
+            assertNotNull(e.getCause());
+            assertSame(validationException, e.getCause());
+            return;
+        }
+
+        fail("Exception should have occurred for validation exception");
+    }
+
+    @Test
+    public void testConflictingException() throws Exception {
+        int maxAttempts = 2;
+        tracker = new BlankTransactionServiceTracker(blankTx, maxAttempts);
+
+        final ConflictingVersionException ex = new ConflictingVersionException();
+        doThrow(ex).when(blankTx).hit();
+        try {
+            tracker.addingService(getMockServiceReference());
+        } catch (Exception e) {
+            verify(blankTx, times(maxAttempts)).hit();
+            return;
+        }
+
+        fail("Exception should have occurred for conflicting exception");
+    }
+
+    private ServiceReference<ModuleFactory> getMockServiceReference() {
+        return mock(ServiceReference.class);
+    }
+}
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/BundleContextBackedModuleFactoriesResolverTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/BundleContextBackedModuleFactoriesResolverTest.java
new file mode 100644 (file)
index 0000000..dc3dedd
--- /dev/null
@@ -0,0 +1,104 @@
+package org.opendaylight.controller.config.manager.impl.osgi;
+
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import com.google.common.collect.Lists;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+public class BundleContextBackedModuleFactoriesResolverTest {
+
+    @Mock
+    private BundleContext bundleContext;
+    private BundleContextBackedModuleFactoriesResolver resolver;
+    private ServiceReference s1;
+    private ServiceReference s2;
+    private ModuleFactory f1;
+    private ModuleFactory f2;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        s1 = getServiceRef();
+        s2 = getServiceRef();
+        doReturn(Lists.newArrayList(s1, s2)).when(bundleContext).getServiceReferences(ModuleFactory.class, null);
+        f1 = getMockFactory("f1");
+        doReturn(f1).when(bundleContext).getService(s1);
+        f2 = getMockFactory("f2");
+        doReturn(f2).when(bundleContext).getService(s2);
+        resolver = new BundleContextBackedModuleFactoriesResolver(bundleContext);
+    }
+
+    private ModuleFactory getMockFactory(String name) {
+        ModuleFactory mock = mock(ModuleFactory.class);
+        doReturn(name).when(mock).toString();
+        doReturn(name).when(mock).getImplementationName();
+        return mock;
+    }
+
+    private ServiceReference getServiceRef() {
+        ServiceReference mock = mock(ServiceReference.class);
+        doReturn("serviceRef").when(mock).toString();
+        final Bundle bundle = mock(Bundle.class);
+        doReturn(bundleContext).when(bundle).getBundleContext();
+        doReturn(bundle).when(mock).getBundle();
+        return mock;
+    }
+
+    @Test
+    public void testGetAllFactories() throws Exception {
+        Map<String, Map.Entry<ModuleFactory, BundleContext>> allFactories = resolver.getAllFactories();
+        assertEquals(2, allFactories.size());
+        assertTrue(allFactories.containsKey(f1.getImplementationName()));
+        assertEquals(f1, allFactories.get(f1.getImplementationName()).getKey());
+        assertEquals(bundleContext, allFactories.get(f1.getImplementationName()).getValue());
+        assertTrue(allFactories.containsKey(f2.getImplementationName()));
+        assertEquals(f2, allFactories.get(f2.getImplementationName()).getKey());
+        assertEquals(bundleContext, allFactories.get(f2.getImplementationName()).getValue());
+    }
+
+    @Test
+    public void testDuplicateFactories() throws Exception {
+        doReturn(f1).when(bundleContext).getService(s2);
+        try {
+            resolver.getAllFactories();
+        } catch (Exception e) {
+            assertThat(e.getMessage(), containsString(f1.getImplementationName()));
+            assertThat(e.getMessage(), containsString("unique"));
+            return;
+        }
+
+        fail("Should fail with duplicate factory name");
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testNullFactory() throws Exception {
+        doReturn(null).when(bundleContext).getService(s2);
+        resolver.getAllFactories();
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testNullFactoryName() throws Exception {
+        doReturn(null).when(f1).getImplementationName();
+        resolver.getAllFactories();
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testNullBundleName() throws Exception {
+        doReturn(null).when(s1).getBundle();
+        resolver.getAllFactories();
+    }
+}
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/ExtensibleBundleTrackerTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/ExtensibleBundleTrackerTest.java
new file mode 100644 (file)
index 0000000..9a3ba64
--- /dev/null
@@ -0,0 +1,76 @@
+package org.opendaylight.controller.config.manager.impl.osgi;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import com.google.common.util.concurrent.Futures;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+
+public class ExtensibleBundleTrackerTest {
+
+    @Mock
+    private BundleContext bundleContext;
+    @Mock
+    private Bundle bundle;
+    @Mock
+    private BundleEvent bundleEvent;
+
+    @Mock
+    private BundleTrackerCustomizer<Object> primaryTracker;
+    @Mock
+    private BundleTrackerCustomizer<?> additionalTracker;
+
+    private ExtensibleBundleTracker<Object> extensibleBundleTracker;
+    private Object primaryValue = new Object();
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        doReturn("bundle").when(bundle).toString();
+        doReturn("bundleEvent").when(bundleEvent).toString();
+
+        doReturn(primaryValue).when(primaryTracker).addingBundle(bundle, bundleEvent);
+        doNothing().when(primaryTracker).modifiedBundle(bundle, bundleEvent, primaryValue);
+        doNothing().when(primaryTracker).removedBundle(bundle, bundleEvent, primaryValue);
+
+        doReturn(new Object()).when(additionalTracker).addingBundle(bundle, bundleEvent);
+        doNothing().when(additionalTracker).modifiedBundle(bundle, bundleEvent, null);
+        doNothing().when(additionalTracker).removedBundle(bundle, bundleEvent, null);
+        extensibleBundleTracker = new ExtensibleBundleTracker<>(bundleContext, primaryTracker, additionalTracker);
+    }
+
+    @Test
+    public void testAddingBundle() throws Exception {
+        assertEquals(primaryValue, extensibleBundleTracker.addingBundle(bundle, bundleEvent).get());
+        InOrder inOrder = Mockito.inOrder(primaryTracker, additionalTracker);
+        inOrder.verify(primaryTracker).addingBundle(bundle, bundleEvent);
+        inOrder.verify(additionalTracker).addingBundle(bundle, bundleEvent);
+    }
+
+    @Test
+    public void testRemovedBundle() throws Exception {
+        extensibleBundleTracker.removedBundle(bundle, bundleEvent, Futures.immediateFuture(primaryValue));
+        InOrder inOrder = Mockito.inOrder(primaryTracker, additionalTracker);
+        inOrder.verify(primaryTracker).removedBundle(bundle, bundleEvent, primaryValue);
+        inOrder.verify(additionalTracker).removedBundle(bundle, bundleEvent, null);
+    }
+
+    @Test
+    public void testRemovedBundleWithEx() throws Exception {
+        IllegalStateException throwable = new IllegalStateException();
+        extensibleBundleTracker.removedBundle(bundle, bundleEvent, Futures.immediateFailedFuture(throwable));
+        verifyZeroInteractions(primaryTracker);
+        verifyZeroInteractions(additionalTracker);
+    }
+}
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/ModuleFactoryBundleTrackerTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/ModuleFactoryBundleTrackerTest.java
new file mode 100644 (file)
index 0000000..5b83412
--- /dev/null
@@ -0,0 +1,193 @@
+package org.opendaylight.controller.config.manager.impl.osgi;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyObject;
+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 static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import java.util.Dictionary;
+import java.util.Set;
+
+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.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.DependencyResolverFactory;
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
+import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.controller.config.spi.Module;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.ServiceRegistration;
+
+public class ModuleFactoryBundleTrackerTest {
+
+    @Mock
+    private Bundle bundle;
+    @Mock
+    private BundleContext context;
+    @Mock
+    private ServiceRegistration<?> reg;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        doAnswer(new Answer() {
+            @Override
+            public Object answer(final InvocationOnMock invocation) throws Throwable {
+                return getClass().getClassLoader().loadClass((String) invocation.getArguments()[0]);
+            }
+        }).when(bundle).loadClass(anyString());
+        doReturn("mockBundle").when(bundle).toString();
+        doReturn(context).when(bundle).getBundleContext();
+        doReturn(reg).when(context).registerService(anyString(), anyObject(), any(Dictionary.class));
+    }
+
+    @Test
+    public void testRegisterFactory() throws Exception {
+        ModuleFactoryBundleTracker.registerFactory(TestingFactory.class.getName(), bundle);
+        verify(context).registerService(ModuleFactory.class.getName(), TestingFactory.currentInstance, null);
+    }
+
+    @Test
+    public void testRegisterFactoryInstantiateEx() throws Exception {
+        try {
+            ModuleFactoryBundleTracker.registerFactory(WrongConstructorTestingFactory.class.getName(), bundle);
+        } catch (Exception e) {
+            verifyZeroInteractions(context);
+            assertNotNull(e.getCause());
+            assertEquals(InstantiationException.class, e.getCause().getClass());
+            return;
+        }
+
+        fail("Cannot register without proper constructor");
+    }
+
+    @Test
+    public void testRegisterFactoryInstantiateExAccess() throws Exception {
+        try {
+            ModuleFactoryBundleTracker.registerFactory(NoAccessConstructorTestingFactory.class.getName(), bundle);
+        } catch (Exception e) {
+            verifyZeroInteractions(context);
+            assertNotNull(e.getCause());
+            assertEquals(IllegalAccessException.class, e.getCause().getClass());
+            return;
+        }
+
+        fail("Cannot register without proper constructor");
+    }
+
+    @Test
+    public void testRegisterFactoryNotExtending() throws Exception {
+        try {
+            ModuleFactoryBundleTracker.registerFactory(NotExtendingTestingFactory.class.getName(), bundle);
+        } catch (Exception e) {
+            verifyZeroInteractions(context);
+            return;
+        }
+
+        fail("Cannot register without extend");
+    }
+
+    @Test
+    public void testRegisterFactoryNotExisting() throws Exception {
+        try {
+            ModuleFactoryBundleTracker.registerFactory("Unknown class", bundle);
+        } catch (Exception e) {
+            verifyZeroInteractions(context);
+            assertNotNull(e.getCause());
+            assertEquals(ClassNotFoundException.class, e.getCause().getClass());
+            return;
+        }
+
+        fail("Cannot register without extend");
+    }
+
+    @Mock
+    private BlankTransactionServiceTracker blankTxTracker;
+
+    @Test
+    public void testAddingBundle() throws Exception {
+        final ModuleFactoryBundleTracker tracker = new ModuleFactoryBundleTracker(blankTxTracker);
+        doReturn(getClass().getResource("/module-factories/module-factory-ok")).when(bundle).getEntry(anyString());
+        tracker.addingBundle(bundle, mock(BundleEvent.class));
+        verify(context).registerService(ModuleFactory.class.getName(), TestingFactory.currentInstance, null);
+    }
+
+    @Test
+    public void testAddingBundleError() throws Exception {
+        final ModuleFactoryBundleTracker tracker = new ModuleFactoryBundleTracker(blankTxTracker);
+        doReturn(getClass().getResource("/module-factories/module-factory-fail")).when(bundle).getEntry(anyString());
+        try {
+            tracker.addingBundle(bundle, mock(BundleEvent.class));
+        } catch (Exception e) {
+            verifyZeroInteractions(context);
+            return;
+        }
+
+        fail("Cannot register");
+    }
+
+    static class WrongConstructorTestingFactory extends TestingFactory {
+        WrongConstructorTestingFactory(String randomParam) {
+        }
+    }
+
+    static class NotExtendingTestingFactory {}
+
+    static class NoAccessConstructorTestingFactory extends TestingFactory {
+        private NoAccessConstructorTestingFactory() {
+        }
+    }
+
+    static class TestingFactory implements ModuleFactory {
+
+        static TestingFactory currentInstance;
+
+        TestingFactory() {
+            currentInstance = this;
+        }
+
+        @Override
+        public String getImplementationName() {
+            return "Testing";
+        }
+
+        @Override
+        public Module createModule(final String instanceName, final DependencyResolver dependencyResolver, final BundleContext bundleContext) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Module createModule(final String instanceName, final DependencyResolver dependencyResolver, final DynamicMBeanWithInstance old, final BundleContext bundleContext) throws Exception {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isModuleImplementingServiceInterface(final Class<? extends AbstractServiceInterface> serviceInterface) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Set<Class<? extends AbstractServiceInterface>> getImplementedServiceIntefaces() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Set<? extends Module> getDefaultModules(final DependencyResolverFactory dependencyResolverFactory, final BundleContext bundleContext) {
+            throw new UnsupportedOperationException();
+        }
+    }
+}
index 22ea528030931b5350cd79c0facc30d1c4ed73a5..220bef03bc95eab1efbbe54122e7b42cb657927e 100644 (file)
@@ -9,20 +9,19 @@ package org.opendaylight.controller.config.manager.impl.util;
 
 import static org.junit.Assert.assertEquals;
 
+import com.google.common.collect.Sets;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
-
 import javax.management.MXBean;
-
 import org.junit.Test;
 import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
 import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingScheduledThreadPoolServiceInterface;
 import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingThreadPoolServiceInterface;
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.yangtools.concepts.Identifiable;
 
-import com.google.common.collect.Sets;
-
 public class InterfacesHelperTest {
 
     interface SuperA {
@@ -46,10 +45,19 @@ public class InterfacesHelperTest {
 
     }
 
+    @ServiceInterfaceAnnotation(value = "a", osgiRegistrationType = SuperA.class, namespace = "n", revision = "r", localName = "l")
+    interface Service extends AbstractServiceInterface{}
+    @ServiceInterfaceAnnotation(value = "b", osgiRegistrationType = SuperC.class, namespace = "n", revision = "r", localName = "l")
+    interface SubService extends Service{}
+
     abstract class SubClass extends SuperClass implements SubA, Module {
 
     }
 
+    abstract class SubClassWithService implements SubService, Module {
+
+    }
+
     @Test
     public void testGetAllInterfaces() {
         Set<Class<?>> expected = Sets.<Class<?>> newHashSet(SuperA.class, SuperBMXBean.class, SuperC.class,
@@ -58,6 +66,19 @@ public class InterfacesHelperTest {
                 InterfacesHelper.getAllInterfaces(SubClass.class));
     }
 
+    @Test
+    public void testGetServiceInterfaces() throws Exception {
+        assertEquals(Collections.<Class<?>>emptySet(), InterfacesHelper.getServiceInterfaces(SubClass.class));
+        assertEquals(Sets.<Class<?>>newHashSet(Service.class, SubService.class), InterfacesHelper.getServiceInterfaces(SubClassWithService.class));
+    }
+
+    @Test
+    public void testGetOsgiRegistrationTypes() throws Exception {
+        assertEquals(Collections.<Class<?>>emptySet(), InterfacesHelper.getOsgiRegistrationTypes(SubClass.class));
+        assertEquals(Sets.<Class<?>>newHashSet(SuperA.class, SuperC.class),
+                InterfacesHelper.getOsgiRegistrationTypes(SubClassWithService.class));
+    }
+
     @Test
     public void testGetMXInterfaces() {
         Set<Class<?>> expected = Sets.<Class<?>> newHashSet(SuperBMXBean.class, SubA.class);
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/ObjectNameUtilTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/ObjectNameUtilTest.java
deleted file mode 100644 (file)
index fe32289..0000000
+++ /dev/null
@@ -1,65 +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.config.manager.impl.util;
-
-import com.google.common.base.Throwables;
-import com.google.common.collect.Sets;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
-import org.opendaylight.controller.config.manager.impl.AbstractLockedPlatformMBeanServerTest;
-
-import javax.management.ObjectName;
-import java.util.Set;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-
-public class ObjectNameUtilTest extends AbstractLockedPlatformMBeanServerTest {
-    private Set<ObjectName> unregisterONs;
-
-    @Before
-    public void initUnregisterList() {
-        unregisterONs = Sets.newHashSet();
-    }
-
-    @After
-    public void unregisterONs() {
-        Exception lastException = null;
-        for (ObjectName on : unregisterONs) {
-            try {
-                platformMBeanServer.unregisterMBean(on);
-            } catch (Exception e) {
-                lastException = e;
-            }
-        }
-        if (lastException != null) {
-            throw Throwables.propagate(lastException);
-        }
-    }
-
-    @Test
-    public void testQuotation() throws Exception {
-        String serviceQName = "(namespace?revision=r)qname";
-        String refName = "refName";
-        String transaction = "transaction";
-        ObjectName serviceReferenceON = ObjectNameUtil.createTransactionServiceON(transaction, serviceQName, refName);
-        assertFalse(serviceReferenceON.isPattern());
-        assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
-        assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
-        assertEquals(transaction, ObjectNameUtil.getTransactionName(serviceReferenceON));
-
-        serviceReferenceON = ObjectNameUtil.createReadOnlyServiceON(serviceQName, refName);
-        assertFalse(serviceReferenceON.isPattern());
-        assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
-        assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
-        assertEquals(null, ObjectNameUtil.getTransactionName(serviceReferenceON));
-
-    }
-}
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/OsgiRegistrationUtilTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/OsgiRegistrationUtilTest.java
new file mode 100644 (file)
index 0000000..fb59e3d
--- /dev/null
@@ -0,0 +1,61 @@
+package org.opendaylight.controller.config.manager.impl.util;
+
+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.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mockito;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class OsgiRegistrationUtilTest {
+
+    @Test
+    public void testRegisterService() throws Exception {
+        final BundleContext bundleContext = mock(BundleContext.class);
+        ServiceRegistration<?> registration = mockServiceRegistration();
+        doReturn(registration).when(bundleContext).registerService(String.class, "string", null);
+        ServiceRegistration<?> registration2 = mockServiceRegistration();
+        doReturn(registration2).when(bundleContext).registerService(Object.class, "string", null);
+
+        AutoCloseable aggregatedRegister = OsgiRegistrationUtil.registerService(bundleContext, "string", String.class, Object.class);
+        aggregatedRegister.close();
+
+        InOrder inOrder = Mockito.inOrder(registration, registration2);
+        inOrder.verify(registration2).unregister();
+        inOrder.verify(registration).unregister();
+    }
+
+    @Test
+    public void testWrap() throws Exception {
+        final ServiceRegistration<?> serviceReg = mockServiceRegistration();
+        OsgiRegistrationUtil.wrap(serviceReg).close();
+        verify(serviceReg).unregister();
+
+        final BundleTracker tracker = mock(BundleTracker.class);
+        doNothing().when(tracker).close();
+        OsgiRegistrationUtil.wrap(tracker).close();
+        verify(tracker).close();
+
+        final ServiceTracker<?, ?> sTracker = mock(ServiceTracker.class);
+        doNothing().when(sTracker).close();
+        OsgiRegistrationUtil.wrap(sTracker).close();
+        verify(sTracker).close();
+    }
+
+    private ServiceRegistration<?> mockServiceRegistration() {
+        ServiceRegistration mock = mock(ServiceRegistration.class);
+        doNothing().when(mock).unregister();
+        return mock;
+    }
+
+    @Test
+    public void testAggregate() throws Exception {
+
+    }
+}
\ No newline at end of file
index 0286400d7b844524ba72dd8cadc7f2de44f7d317..a7024ca39e258011ae11afb15537ddd99764c294 100644 (file)
@@ -9,6 +9,6 @@ package org.opendaylight.controller.config.manager.testingservices.threadpool;
 
 import org.opendaylight.yangtools.yang.binding.annotations.ModuleQName;
 
-@ModuleQName(namespace = "namespace", revision = "revision", name = "name")
+@ModuleQName(namespace = "namespace", revision = "2012-12-12", name = "name")
 public abstract class AbstractTestingFixedThreadPoolModuleFactory {
 }
index 97d1c63ed2770da0ceb4fb504a4795a775b12c89..4ba3dc89399d11f157fdc833b5a72277e8e33ea1 100644 (file)
@@ -380,7 +380,8 @@ public class SimpleConfigurationTest extends AbstractConfigTest {
     @Test
     public void testQNames() {
         Set<String> availableModuleFactoryQNames = configRegistryClient.getAvailableModuleFactoryQNames();
-        String expected = "(namespace?revision=revision)name";
+        String expected = "(namespace?revision=2012-12-12)name";
+
         assertEquals(Sets.newHashSet(expected), availableModuleFactoryQNames);
     }
 
diff --git a/opendaylight/config/config-manager/src/test/resources/module-factories/module-factory-fail b/opendaylight/config/config-manager/src/test/resources/module-factories/module-factory-fail
new file mode 100644 (file)
index 0000000..fbd8108
--- /dev/null
@@ -0,0 +1 @@
+org.opendaylight.controller.config.manager.impl.osgi.ModuleFactoryBundleTrackerTest$NotExtendingTestingFactory
\ No newline at end of file
diff --git a/opendaylight/config/config-manager/src/test/resources/module-factories/module-factory-ok b/opendaylight/config/config-manager/src/test/resources/module-factories/module-factory-ok
new file mode 100644 (file)
index 0000000..031b622
--- /dev/null
@@ -0,0 +1 @@
+org.opendaylight.controller.config.manager.impl.osgi.ModuleFactoryBundleTrackerTest$TestingFactory
\ No newline at end of file
index b9d218ead1ea0fe39efd15c051037ebc2807e8be..1e5fcce6093bec286d4fce3e5e40ea3efc4b8834 100644 (file)
       <groupId>${project.groupId}</groupId>
       <artifactId>netconf-client</artifactId>
     </dependency>
+
+      <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>config-manager</artifactId>
+          <type>test-jar</type>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>config-manager</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>config-util</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>netty-threadgroup-config</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>netty-timer-config</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>mockito-configuration</artifactId>
+          <scope>test</scope>
+      </dependency>
   </dependencies>
 
   <build>
diff --git a/opendaylight/config/netconf-config-dispatcher/src/test/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModuleTest.java b/opendaylight/config/netconf-config-dispatcher/src/test/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModuleTest.java
new file mode 100644 (file)
index 0000000..85477a0
--- /dev/null
@@ -0,0 +1,102 @@
+package org.opendaylight.controller.config.yang.config.netconf.client.dispatcher;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import org.opendaylight.controller.config.yang.netty.threadgroup.NettyThreadgroupModuleFactory;
+import org.opendaylight.controller.config.yang.netty.threadgroup.NettyThreadgroupModuleMXBean;
+import org.opendaylight.controller.config.yang.netty.timer.HashedWheelTimerModuleFactory;
+
+public class NetconfClientDispatcherModuleTest extends AbstractConfigTest{
+
+    private NetconfClientDispatcherModuleFactory factory;
+    private final String instanceName = "dispatch";
+
+    @Before
+    public void setUp() {
+        factory = new NetconfClientDispatcherModuleFactory();
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory,
+                new NettyThreadgroupModuleFactory(),
+                new HashedWheelTimerModuleFactory()));
+    }
+
+    @Test
+    public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException, ConflictingVersionException {
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+        createInstance(transaction, instanceName, "timer", "thGroup");
+        createInstance(transaction, instanceName + 2, "timer2", "thGroup2");
+        transaction.validateConfig();
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(2, factory.getImplementationName());
+        assertStatus(status, 2 + 4, 0, 0);
+    }
+
+    @Test
+    public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException, ValidationException {
+
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        createInstance(transaction, instanceName, "timer", "thGroup");
+
+        transaction.commit();
+
+        transaction = configRegistryClient.createTransaction();
+        assertBeanCount(1, factory.getImplementationName());
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(1, factory.getImplementationName());
+        assertStatus(status, 0, 0, 3);
+    }
+
+    @Test
+    public void testReconfigure() throws InstanceAlreadyExistsException, ConflictingVersionException,
+            ValidationException, InstanceNotFoundException {
+
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        createInstance(transaction, instanceName, "timer", "thGroup");
+
+        transaction.commit();
+
+        transaction = configRegistryClient.createTransaction();
+        assertBeanCount(1, factory.getImplementationName());
+        NetconfClientDispatcherModuleMXBean mxBean = transaction.newMBeanProxy(
+                transaction.lookupConfigBean(NetconfClientDispatcherModuleFactory.NAME, instanceName),
+                NetconfClientDispatcherModuleMXBean.class);
+        mxBean.setBossThreadGroup(getThreadGroup(transaction, "group2"));
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(1, factory.getImplementationName());
+        assertStatus(status, 1, 1, 2);
+    }
+
+    private ObjectName createInstance(ConfigTransactionJMXClient transaction, String instanceName, String timerName, String threadGroupName)
+            throws InstanceAlreadyExistsException {
+        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);
+        NetconfClientDispatcherModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated, NetconfClientDispatcherModuleMXBean.class);
+        ObjectName thGroup = getThreadGroup(transaction, threadGroupName);
+        mxBean.setBossThreadGroup(thGroup);
+        mxBean.setWorkerThreadGroup(thGroup);
+        mxBean.setTimer(getTimer(transaction, timerName));
+        return nameCreated;
+    }
+
+    private ObjectName getTimer(ConfigTransactionJMXClient transaction, String name) throws InstanceAlreadyExistsException {
+        return transaction.createModule(HashedWheelTimerModuleFactory.NAME, name);
+    }
+
+    private ObjectName getThreadGroup(ConfigTransactionJMXClient transaction, String name) throws InstanceAlreadyExistsException {
+        ObjectName nameCreated = transaction.createModule(NettyThreadgroupModuleFactory.NAME, name);
+        NettyThreadgroupModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, NettyThreadgroupModuleMXBean.class);
+        mxBean.setThreadCount(1);
+        return nameCreated;
+    }
+}
diff --git a/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/ImmediateEventExecutorModuleTest.java b/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/ImmediateEventExecutorModuleTest.java
new file mode 100644 (file)
index 0000000..4cc9cc3
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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.config.yang.netty.eventexecutor;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+
+public class ImmediateEventExecutorModuleTest extends AbstractConfigTest {
+
+    private GlobalEventExecutorModuleFactory factory;
+    private final String instanceName = ImmediateEventExecutorModuleFactory.SINGLETON_NAME;
+
+    @Before
+    public void setUp() {
+        factory = new GlobalEventExecutorModuleFactory();
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory));
+    }
+
+    @Test
+    public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException,
+            ConflictingVersionException {
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+        createInstance(transaction, instanceName);
+
+        transaction.validateConfig();
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(1, factory.getImplementationName());
+        assertStatus(status, 1, 0, 0);
+    }
+
+    @Test
+    public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException,
+            ValidationException {
+
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        createInstance(transaction, instanceName);
+
+        transaction.commit();
+
+        transaction = configRegistryClient.createTransaction();
+        assertBeanCount(1, factory.getImplementationName());
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(1, factory.getImplementationName());
+        assertStatus(status, 0, 0, 1);
+    }
+
+    private ObjectName createInstance(ConfigTransactionJMXClient transaction, String instanceName)
+            throws InstanceAlreadyExistsException {
+        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);
+        transaction.newMBeanProxy(nameCreated, ImmediateEventExecutorModuleMXBean.class);
+        return nameCreated;
+    }
+
+}
@@ -34,7 +34,7 @@ public class HashedWheelTimerModuleTest extends AbstractConfigTest {
     public void setUp() {
         factory = new HashedWheelTimerModuleFactory();
         threadFactory = new NamingThreadFactoryModuleFactory();
-        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory, threadFactory));
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, factory, threadFactory));
     }
 
     public void testValidationExceptionTickDuration() throws InstanceAlreadyExistsException {
diff --git a/opendaylight/distribution/opendaylight-karaf-empty/pom.xml b/opendaylight/distribution/opendaylight-karaf-empty/pom.xml
new file mode 100644 (file)
index 0000000..d3dfe19
--- /dev/null
@@ -0,0 +1,235 @@
+<?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>opendaylight-karaf-empty</artifactId>
+  <packaging>pom</packaging>
+  <prerequisites>
+    <maven>3.0</maven>
+  </prerequisites>
+
+  <dependencies>
+    <dependency>
+      <!-- scope is compile so all features (there is only one) are installed
+            into startup.properties and the feature repo itself is not installed -->
+      <groupId>org.apache.karaf.features</groupId>
+      <artifactId>framework</artifactId>
+      <version>${karaf.version}</version>
+      <type>kar</type>
+    </dependency>
+    <!-- scope is runtime so the feature repo is listed in the features
+      service config file, and features may be installed using the
+      karaf-maven-plugin configuration -->
+    <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>
+      <scope>compile</scope>
+    </dependency>
+
+    <!-- Resources needed -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>opendaylight-karaf-resources</artifactId>
+      <version>${project.version}</version>
+    </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>
+        <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-checkstyle-plugin</artifactId>
+        <version>${checkstyle.version}</version>
+        <configuration>
+          <excludes>**\/target\/,**\/bin\/,**\/target-ide\/,**\/configuration\/initial\/</excludes>
+        </configuration>
+      </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>
+            <!-- here the phase you need -->
+            <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"/>
+                        </fileset>
+                    </chmod>
+                  </tasks>
+                </configuration>
+            </execution>
+        </executions>
+      </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/distribution/opendaylight-karaf-resources/pom.xml b/opendaylight/distribution/opendaylight-karaf-resources/pom.xml
new file mode 100644 (file)
index 0000000..00495a3
--- /dev/null
@@ -0,0 +1,21 @@
+<?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>commons.opendaylight</artifactId>
+    <version>1.4.2-SNAPSHOT</version>
+    <relativePath>../../commons/opendaylight</relativePath>
+  </parent>
+  <artifactId>opendaylight-karaf-resources</artifactId>
+  <description>Resources for opendaylight-karaf</description>
+  <packaging>jar</packaging>
+</project>
index b3c3f20ba80bb5cc829c5a208669a239ec8a1981..5cbe412b2b0af28da537a95af2ace0766df8e120 100644 (file)
       <version>${karaf.version}</version>
       <type>kar</type>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>base-features</artifactId>
-      <version>${project.version}</version>
-      <type>kar</type>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>karaf.branding</artifactId>
       <scope>compile</scope>
     </dependency>
-    <!-- scope is runtime so the feature repo is listed in the features
-      service config file, and features may be installed using the
-      karaf-maven-plugin configuration -->
-    <dependency>
-      <groupId>org.apache.karaf.features</groupId>
-      <artifactId>standard</artifactId>
-      <version>${karaf.version}</version>
-      <classifier>features</classifier>
-      <type>xml</type>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>base-features</artifactId>
-      <version>${project.parent.version}</version>
-      <classifier>features</classifier>
-      <type>xml</type>
-      <scope>runtime</scope>
-    </dependency>
-    <!-- scope is compile so all features (there is only one) are installed
-            into startup.properties and the feature repo itself is not installed -->
+
+    <!-- Resources needed -->
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
-      <artifactId>extras-features</artifactId>
+      <artifactId>opendaylight-karaf-resources</artifactId>
       <version>${project.version}</version>
-      <type>kar</type>
-      <scope>runtime</scope>
-    </dependency>
-    <!-- AD-SAL Related Features -->
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>features-adsal</artifactId>
-      <classifier>features</classifier>
-      <type>xml</type>
-      <scope>runtime</scope>
     </dependency>
+
+    <!-- scope is not runtime so the feature repo is pulled into the local
+    repo on build and thus you actually run.  Failure to do so can lead
+    to very confusing errors for devs -->
     <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>features-nsf</artifactId>
-      <version>${project.version}</version>
+      <groupId>org.apache.karaf.features</groupId>
+      <artifactId>standard</artifactId>
+      <version>${karaf.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
-      <scope>runtime</scope>
     </dependency>
 
+    <!--
+          controller provided features:
+          Note: Nothing should go here that is not locked
+          down with testing... ie, no broken feature repos
+    -->
+
     <!-- MD-SAL Related Features -->
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>features-mdsal</artifactId>
       <classifier>features</classifier>
       <type>xml</type>
-      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>features-flow</artifactId>
       <classifier>features</classifier>
       <type>xml</type>
-      <scope>runtime</scope>
     </dependency>
   </dependencies>
 
               </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"/>
+                        </fileset>
+                    </chmod>
+                  </tasks>
+                </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>
-                            <copy todir="${project.build.directory}/assembly/bin" overwrite="true">
-                                <fileset dir="${basedir}/src/main/resources/karaf/" includes="karaf,karaf.bat,instance,instance.bat"/>
-                            </copy>
-                        </tasks>
-                    </configuration>
-                </execution>
-            </executions>
-        </plugin>
     </plugins>
   </build>
   <scm>
diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/etc/jre.properties b/opendaylight/distribution/opendaylight-karaf/src/main/resources/etc/jre.properties
deleted file mode 100644 (file)
index a98956e..0000000
+++ /dev/null
@@ -1,506 +0,0 @@
-################################################################################
-#
-#    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.
-#
-################################################################################
-
-#
-# Java platform package export properties.
-#
-
-# Standard package set.  Note that:
-#   - javax.transaction* is exported with a mandatory attribute
-jre-1.6= \
- javax.accessibility, \
- javax.activation;version="1.1", \
- javax.activity, \
- javax.crypto, \
- javax.crypto.interfaces, \
- javax.crypto.spec, \
- javax.imageio, \
- javax.imageio.event, \
- javax.imageio.metadata, \
- javax.imageio.plugins.bmp, \
- javax.imageio.plugins.jpeg, \
- javax.imageio.spi, \
- javax.imageio.stream, \
- javax.jws, \
- javax.jws.soap, \
- javax.lang.model, \
- javax.lang.model.element, \
- javax.lang.model.type, \
- javax.lang.model.util, \
- javax.management, \
- javax.management.loading, \
- javax.management.modelmbean, \
- javax.management.monitor, \
- javax.management.openmbean, \
- javax.management.relation, \
- javax.management.remote, \
- javax.management.remote.rmi, \
- javax.management.timer, \
- javax.naming, \
- javax.naming.directory, \
- javax.naming.event, \
- javax.naming.ldap, \
- javax.naming.spi, \
- javax.net, \
- javax.net.ssl, \
- javax.print, \
- javax.print.attribute, \
- javax.print.attribute.standard, \
- javax.print.event, \
- javax.rmi, \
- javax.rmi.CORBA, \
- javax.rmi.ssl, \
- javax.script, \
- javax.security.auth, \
- javax.security.auth.callback, \
- javax.security.auth.kerberos, \
- javax.security.auth.login, \
- javax.security.auth.spi, \
- javax.security.auth.x500, \
- javax.security.cert, \
- javax.security.sasl, \
- javax.sound.midi, \
- javax.sound.midi.spi, \
- javax.sound.sampled, \
- javax.sound.sampled.spi, \
- javax.sql, \
- javax.sql.rowset, \
- javax.sql.rowset.serial, \
- javax.sql.rowset.spi, \
- javax.swing, \
- javax.swing.border, \
- javax.swing.colorchooser, \
- javax.swing.event, \
- javax.swing.filechooser, \
- javax.swing.plaf, \
- javax.swing.plaf.basic, \
- javax.swing.plaf.metal, \
- javax.swing.plaf.multi, \
- javax.swing.plaf.synth, \
- javax.swing.table, \
- javax.swing.text, \
- javax.swing.text.html, \
- javax.swing.text.html.parser, \
- javax.swing.text.rtf, \
- javax.swing.tree, \
- javax.swing.undo, \
- javax.tools, \
- javax.transaction; javax.transaction.xa; partial=true; mandatory:=partial, \
- javax.xml, \
- javax.xml.bind;version="2.2.1", \
- javax.xml.bind.annotation;version="2.2.1", \
- javax.xml.bind.annotation.adapters;version="2.2.1", \
- javax.xml.bind.attachment;version="2.2.1", \
- javax.xml.bind.helpers;version="2.2.1", \
- javax.xml.bind.util;version="2.2.1", \
- javax.xml.crypto, \
- javax.xml.crypto.dom, \
- javax.xml.crypto.dsig, \
- javax.xml.crypto.dsig.dom, \
- javax.xml.crypto.dsig.keyinfo, \
- javax.xml.crypto.dsig.spec, \
- javax.xml.datatype, \
- javax.xml.namespace, \
- javax.xml.parsers, \
- javax.xml.soap;version="1.3", \
- javax.xml.stream;version="1.2", \
- javax.xml.stream.events;version="1.2", \
- javax.xml.stream.util;version="1.2", \
- javax.xml.transform, \
- javax.xml.transform.dom, \
- javax.xml.transform.sax, \
- javax.xml.transform.stax, \
- javax.xml.transform.stream, \
- javax.xml.validation, \
- javax.xml.ws;version="2.2", \
- javax.xml.ws.handler;version="2.2", \
- javax.xml.ws.handler.soap;version="2.2", \
- javax.xml.ws.http;version="2.2", \
- javax.xml.ws.soap;version="2.2", \
- javax.xml.ws.spi;version="2.2", \
- javax.xml.ws.wsaddressing;version="2.2", \
- javax.xml.ws.spi.http;version="2.2", \
- javax.xml.xpath, \
- org.ietf.jgss, \
- org.omg.CORBA, \
- org.omg.CORBA_2_3, \
- org.omg.CORBA_2_3.portable, \
- org.omg.CORBA.DynAnyPackage, \
- org.omg.CORBA.ORBPackage, \
- org.omg.CORBA.portable, \
- org.omg.CORBA.TypeCodePackage, \
- org.omg.CosNaming, \
- org.omg.CosNaming.NamingContextExtPackage, \
- org.omg.CosNaming.NamingContextPackage, \
- org.omg.Dynamic, \
- org.omg.DynamicAny, \
- org.omg.DynamicAny.DynAnyFactoryPackage, \
- org.omg.DynamicAny.DynAnyPackage, \
- org.omg.IOP, \
- org.omg.IOP.CodecFactoryPackage, \
- org.omg.IOP.CodecPackage, \
- org.omg.Messaging, \
- org.omg.PortableInterceptor, \
- org.omg.PortableInterceptor.ORBInitInfoPackage, \
- org.omg.PortableServer, \
- org.omg.PortableServer.CurrentPackage, \
- org.omg.PortableServer.POAManagerPackage, \
- org.omg.PortableServer.POAPackage, \
- org.omg.PortableServer.portable, \
- org.omg.PortableServer.ServantLocatorPackage, \
- org.omg.SendingContext, \
- org.omg.stub.java.rmi, \
- org.omg.stub.javax.management.remote.rmi, \
- org.w3c.dom, \
- org.w3c.dom.bootstrap, \
- org.w3c.dom.css, \
- org.w3c.dom.events, \
- org.w3c.dom.html, \
- org.w3c.dom.ls, \
- org.w3c.dom.ranges, \
- org.w3c.dom.stylesheets, \
- org.w3c.dom.traversal, \
- org.w3c.dom.views, \
- org.w3c.dom.xpath, \
- org.xml.sax, \
- org.xml.sax.ext, \
- org.xml.sax.helpers, \
- javax.annotation.processing
-
-# Standard package set.  Note that:
-#   - javax.transaction* is exported with a mandatory attribute
-jre-1.7= \
- javax.accessibility, \
- javax.activation;version="1.1", \
- javax.activity, \
- javax.crypto, \
- javax.crypto.interfaces, \
- javax.crypto.spec, \
- javax.imageio, \
- javax.imageio.event, \
- javax.imageio.metadata, \
- javax.imageio.plugins.bmp, \
- javax.imageio.plugins.jpeg, \
- javax.imageio.spi, \
- javax.imageio.stream, \
- javax.jws, \
- javax.jws.soap, \
- javax.lang.model, \
- javax.lang.model.element, \
- javax.lang.model.type, \
- javax.lang.model.util, \
- javax.management, \
- javax.management.loading, \
- javax.management.modelmbean, \
- javax.management.monitor, \
- javax.management.openmbean, \
- javax.management.relation, \
- javax.management.remote, \
- javax.management.remote.rmi, \
- javax.management.timer, \
- javax.naming, \
- javax.naming.directory, \
- javax.naming.event, \
- javax.naming.ldap, \
- javax.naming.spi, \
- javax.net, \
- javax.net.ssl, \
- javax.print, \
- javax.print.attribute, \
- javax.print.attribute.standard, \
- javax.print.event, \
- javax.rmi, \
- javax.rmi.CORBA, \
- javax.rmi.ssl, \
- javax.script, \
- javax.security.auth, \
- javax.security.auth.callback, \
- javax.security.auth.kerberos, \
- javax.security.auth.login, \
- javax.security.auth.spi, \
- javax.security.auth.x500, \
- javax.security.cert, \
- javax.security.sasl, \
- javax.sound.midi, \
- javax.sound.midi.spi, \
- javax.sound.sampled, \
- javax.sound.sampled.spi, \
- javax.sql, \
- javax.sql.rowset, \
- javax.sql.rowset.serial, \
- javax.sql.rowset.spi, \
- javax.swing, \
- javax.swing.border, \
- javax.swing.colorchooser, \
- javax.swing.event, \
- javax.swing.filechooser, \
- javax.swing.plaf, \
- javax.swing.plaf.basic, \
- javax.swing.plaf.metal, \
- javax.swing.plaf.multi, \
- javax.swing.plaf.synth, \
- javax.swing.table, \
- javax.swing.text, \
- javax.swing.text.html, \
- javax.swing.text.html.parser, \
- javax.swing.text.rtf, \
- javax.swing.tree, \
- javax.swing.undo, \
- javax.tools, \
- javax.transaction; javax.transaction.xa; partial=true; mandatory:=partial, \
- javax.xml, \
- javax.xml.bind;version="2.2.1", \
- javax.xml.bind.annotation;version="2.2.1", \
- javax.xml.bind.annotation.adapters;version="2.2.1", \
- javax.xml.bind.attachment;version="2.2.1", \
- javax.xml.bind.helpers;version="2.2.1", \
- javax.xml.bind.util;version="2.2.1", \
- javax.xml.crypto, \
- javax.xml.crypto.dom, \
- javax.xml.crypto.dsig, \
- javax.xml.crypto.dsig.dom, \
- javax.xml.crypto.dsig.keyinfo, \
- javax.xml.crypto.dsig.spec, \
- javax.xml.datatype, \
- javax.xml.namespace, \
- javax.xml.parsers, \
- javax.xml.soap;version="1.3", \
- javax.xml.stream;version="1.2", \
- javax.xml.stream.events;version="1.2", \
- javax.xml.stream.util;version="1.2", \
- javax.xml.transform, \
- javax.xml.transform.dom, \
- javax.xml.transform.sax, \
- javax.xml.transform.stax, \
- javax.xml.transform.stream, \
- javax.xml.validation, \
- javax.xml.ws;version="2.2", \
- javax.xml.ws.handler;version="2.2", \
- javax.xml.ws.handler.soap;version="2.2", \
- javax.xml.ws.http;version="2.2", \
- javax.xml.ws.soap;version="2.2", \
- javax.xml.ws.spi;version="2.2", \
- javax.xml.ws.wsaddressing;version="2.2", \
- javax.xml.ws.spi.http;version="2.2", \
- javax.xml.xpath, \
- org.ietf.jgss, \
- org.omg.CORBA, \
- org.omg.CORBA_2_3, \
- org.omg.CORBA_2_3.portable, \
- org.omg.CORBA.DynAnyPackage, \
- org.omg.CORBA.ORBPackage, \
- org.omg.CORBA.portable, \
- org.omg.CORBA.TypeCodePackage, \
- org.omg.CosNaming, \
- org.omg.CosNaming.NamingContextExtPackage, \
- org.omg.CosNaming.NamingContextPackage, \
- org.omg.Dynamic, \
- org.omg.DynamicAny, \
- org.omg.DynamicAny.DynAnyFactoryPackage, \
- org.omg.DynamicAny.DynAnyPackage, \
- org.omg.IOP, \
- org.omg.IOP.CodecFactoryPackage, \
- org.omg.IOP.CodecPackage, \
- org.omg.Messaging, \
- org.omg.PortableInterceptor, \
- org.omg.PortableInterceptor.ORBInitInfoPackage, \
- org.omg.PortableServer, \
- org.omg.PortableServer.CurrentPackage, \
- org.omg.PortableServer.POAManagerPackage, \
- org.omg.PortableServer.POAPackage, \
- org.omg.PortableServer.portable, \
- org.omg.PortableServer.ServantLocatorPackage, \
- org.omg.SendingContext, \
- org.omg.stub.java.rmi, \
- org.omg.stub.javax.management.remote.rmi, \
- org.w3c.dom, \
- org.w3c.dom.bootstrap, \
- org.w3c.dom.css, \
- org.w3c.dom.events, \
- org.w3c.dom.html, \
- org.w3c.dom.ls, \
- org.w3c.dom.ranges, \
- org.w3c.dom.stylesheets, \
- org.w3c.dom.traversal, \
- org.w3c.dom.views, \
- org.w3c.dom.xpath, \
- org.xml.sax, \
- org.xml.sax.ext, \
- org.xml.sax.helpers, \
- javax.annotation.processing
-
-jre-1.8= \
- javax.accessibility, \
- javax.activation;version="1.1", \
- javax.activity, \
- javax.crypto, \
- javax.crypto.interfaces, \
- javax.crypto.spec, \
- javax.imageio, \
- javax.imageio.event, \
- javax.imageio.metadata, \
- javax.imageio.plugins.bmp, \
- javax.imageio.plugins.jpeg, \
- javax.imageio.spi, \
- javax.imageio.stream, \
- javax.jws, \
- javax.jws.soap, \
- javax.lang.model, \
- javax.lang.model.element, \
- javax.lang.model.type, \
- javax.lang.model.util, \
- javax.management, \
- javax.management.loading, \
- javax.management.modelmbean, \
- javax.management.monitor, \
- javax.management.openmbean, \
- javax.management.relation, \
- javax.management.remote, \
- javax.management.remote.rmi, \
- javax.management.timer, \
- javax.naming, \
- javax.naming.directory, \
- javax.naming.event, \
- javax.naming.ldap, \
- javax.naming.spi, \
- javax.net, \
- javax.net.ssl, \
- javax.print, \
- javax.print.attribute, \
- javax.print.attribute.standard, \
- javax.print.event, \
- javax.rmi, \
- javax.rmi.CORBA, \
- javax.rmi.ssl, \
- javax.script, \
- javax.security.auth, \
- javax.security.auth.callback, \
- javax.security.auth.kerberos, \
- javax.security.auth.login, \
- javax.security.auth.spi, \
- javax.security.auth.x500, \
- javax.security.cert, \
- javax.security.sasl, \
- javax.sound.midi, \
- javax.sound.midi.spi, \
- javax.sound.sampled, \
- javax.sound.sampled.spi, \
- javax.sql, \
- javax.sql.rowset, \
- javax.sql.rowset.serial, \
- javax.sql.rowset.spi, \
- javax.swing, \
- javax.swing.border, \
- javax.swing.colorchooser, \
- javax.swing.event, \
- javax.swing.filechooser, \
- javax.swing.plaf, \
- javax.swing.plaf.basic, \
- javax.swing.plaf.metal, \
- javax.swing.plaf.multi, \
- javax.swing.plaf.synth, \
- javax.swing.table, \
- javax.swing.text, \
- javax.swing.text.html, \
- javax.swing.text.html.parser, \
- javax.swing.text.rtf, \
- javax.swing.tree, \
- javax.swing.undo, \
- javax.tools, \
- javax.transaction; javax.transaction.xa; partial=true; mandatory:=partial, \
- javax.xml, \
- javax.xml.bind;version="2.2.1", \
- javax.xml.bind.annotation;version="2.2.1", \
- javax.xml.bind.annotation.adapters;version="2.2.1", \
- javax.xml.bind.attachment;version="2.2.1", \
- javax.xml.bind.helpers;version="2.2.1", \
- javax.xml.bind.util;version="2.2.1", \
- javax.xml.crypto, \
- javax.xml.crypto.dom, \
- javax.xml.crypto.dsig, \
- javax.xml.crypto.dsig.dom, \
- javax.xml.crypto.dsig.keyinfo, \
- javax.xml.crypto.dsig.spec, \
- javax.xml.datatype, \
- javax.xml.namespace, \
- javax.xml.parsers, \
- javax.xml.soap;version="1.3", \
- javax.xml.stream;version="1.2", \
- javax.xml.stream.events;version="1.2", \
- javax.xml.stream.util;version="1.2", \
- javax.xml.transform, \
- javax.xml.transform.dom, \
- javax.xml.transform.sax, \
- javax.xml.transform.stax, \
- javax.xml.transform.stream, \
- javax.xml.validation, \
- javax.xml.ws;version="2.2", \
- javax.xml.ws.handler;version="2.2", \
- javax.xml.ws.handler.soap;version="2.2", \
- javax.xml.ws.http;version="2.2", \
- javax.xml.ws.soap;version="2.2", \
- javax.xml.ws.spi;version="2.2", \
- javax.xml.ws.wsaddressing;version="2.2", \
- javax.xml.ws.spi.http;version="2.2", \
- javax.xml.xpath, \
- org.ietf.jgss, \
- org.omg.CORBA, \
- org.omg.CORBA_2_3, \
- org.omg.CORBA_2_3.portable, \
- org.omg.CORBA.DynAnyPackage, \
- org.omg.CORBA.ORBPackage, \
- org.omg.CORBA.portable, \
- org.omg.CORBA.TypeCodePackage, \
- org.omg.CosNaming, \
- org.omg.CosNaming.NamingContextExtPackage, \
- org.omg.CosNaming.NamingContextPackage, \
- org.omg.Dynamic, \
- org.omg.DynamicAny, \
- org.omg.DynamicAny.DynAnyFactoryPackage, \
- org.omg.DynamicAny.DynAnyPackage, \
- org.omg.IOP, \
- org.omg.IOP.CodecFactoryPackage, \
- org.omg.IOP.CodecPackage, \
- org.omg.Messaging, \
- org.omg.PortableInterceptor, \
- org.omg.PortableInterceptor.ORBInitInfoPackage, \
- org.omg.PortableServer, \
- org.omg.PortableServer.CurrentPackage, \
- org.omg.PortableServer.POAManagerPackage, \
- org.omg.PortableServer.POAPackage, \
- org.omg.PortableServer.portable, \
- org.omg.PortableServer.ServantLocatorPackage, \
- org.omg.SendingContext, \
- org.omg.stub.java.rmi, \
- org.omg.stub.javax.management.remote.rmi, \
- org.w3c.dom, \
- org.w3c.dom.bootstrap, \
- org.w3c.dom.css, \
- org.w3c.dom.events, \
- org.w3c.dom.html, \
- org.w3c.dom.ls, \
- org.w3c.dom.ranges, \
- org.w3c.dom.stylesheets, \
- org.w3c.dom.traversal, \
- org.w3c.dom.views, \
- org.w3c.dom.xpath, \
- org.xml.sax, \
- org.xml.sax.ext, \
- org.xml.sax.helpers, \
- javax.annotation.processing
diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/etc/startup.properties b/opendaylight/distribution/opendaylight-karaf/src/main/resources/etc/startup.properties
deleted file mode 100644 (file)
index ca8c83c..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-#Bundles to be started on startup, with startlevel
-
-# feature: framework version: 3.0.1
-mvn\:org.ops4j.base/ops4j-base-lang/1.4.0 = 5
-mvn\:biz.aQute.bnd/bndlib/2.2.0 = 5
-mvn\:org.ops4j.pax.swissbox/pax-swissbox-bnd/1.7.0 = 5
-mvn\:org.ops4j.pax.url/pax-url-maven-commons/1.6.0 = 5
-mvn\:org.ops4j.pax.url/pax-url-aether/1.6.0 = 5
-mvn\:org.ops4j.pax.url/pax-url-wrap/1.6.0 = 5
-mvn\:javax.annotation/javax.annotation-api/1.2 = 5
-mvn\:org.ops4j.pax.logging/pax-logging-api/1.7.2 = 8
-mvn\:org.ops4j.pax.logging/pax-logging-service/1.7.2 = 8
-mvn\:org.apache.karaf.service/org.apache.karaf.service.guard/3.0.1 = 10
-mvn\:org.apache.felix/org.apache.felix.configadmin/1.6.0 = 10
-mvn\:org.apache.felix/org.apache.felix.fileinstall/3.2.8 = 11
-mvn\:org.ow2.asm/asm-all/4.1 = 12
-mvn\:org.apache.aries/org.apache.aries.util/1.1.0 = 20
-mvn\:org.apache.aries.proxy/org.apache.aries.proxy.api/1.0.0 = 20
-mvn\:org.apache.aries.proxy/org.apache.aries.proxy.impl/1.0.2 = 20
-mvn\:org.apache.aries.blueprint/org.apache.aries.blueprint.api/1.0.0 = 20
-mvn\:org.apache.aries.blueprint/org.apache.aries.blueprint.cm/1.0.3 = 20
-mvn\:org.apache.aries.blueprint/org.apache.aries.blueprint.core.compatibility/1.0.0 = 20
-mvn\:org.apache.aries.blueprint/org.apache.aries.blueprint.core/1.4.0 = 20
-mvn\:org.apache.karaf.deployer/org.apache.karaf.deployer.spring/3.0.1 = 24
-mvn\:org.apache.karaf.deployer/org.apache.karaf.deployer.blueprint/3.0.1 = 24
-mvn\:org.apache.karaf.deployer/org.apache.karaf.deployer.wrap/3.0.1 = 24
-mvn\:org.apache.karaf.region/org.apache.karaf.region.core/3.0.1 = 25
-mvn\:org.apache.karaf.features/org.apache.karaf.features.core/3.0.1 = 25
-mvn\:org.apache.karaf.deployer/org.apache.karaf.deployer.features/3.0.1 = 26
-mvn\:jline/jline/2.11 = 30
-mvn\:org.jledit/core/0.2.1 = 30
-mvn\:org.fusesource.jansi/jansi/1.11 = 30
-mvn\:org.ops4j.base/ops4j-base-util-property/1.4.0 = 30
-mvn\:org.ops4j.base/ops4j-base-util-xml/1.4.0 = 30
-mvn\:org.ops4j.base/ops4j-base-util-collections/1.4.0 = 30
-mvn\:org.ops4j.pax.url/pax-url-commons/1.6.0 = 30
-mvn\:org.ops4j.pax.swissbox/pax-swissbox-property/1.7.0 = 30
-mvn\:org.ops4j.base/ops4j-base-net/1.4.0 = 30
-mvn\:org.ops4j.base/ops4j-base-monitors/1.4.0 = 30
-mvn\:org.apache.karaf.features/org.apache.karaf.features.command/3.0.1 = 30
-mvn\:org.apache.karaf.shell/org.apache.karaf.shell.console/3.0.1 = 30
-mvn\:org.apache.karaf.jaas/org.apache.karaf.jaas.modules/3.0.1 = 30
-mvn\:org.apache.karaf.jaas/org.apache.karaf.jaas.config/3.0.1 = 30
-mvn\:org.apache.karaf.jaas/org.apache.karaf.jaas.boot/3.0.1 = 30
-mvn\:org.apache.sshd/sshd-core/0.9.0 = 30
-mvn\:org.apache.karaf.bundle/org.apache.karaf.bundle.command/3.0.1 = 30
-mvn\:org.apache.karaf.shell/org.apache.karaf.shell.table/3.0.1 = 30
-mvn\:org.apache.karaf.bundle/org.apache.karaf.bundle.core/3.0.1 = 30
-mvn\:org.apache.karaf.shell/org.apache.karaf.shell.help/3.0.1 = 30
-mvn\:org.apache.karaf.system/org.apache.karaf.system.core/3.0.1 = 30
-mvn\:org.apache.karaf.system/org.apache.karaf.system.command/3.0.1 = 30
-mvn\:org.apache.karaf.shell/org.apache.karaf.shell.commands/3.0.1 = 30
-mvn\:org.apache.aries.quiesce/org.apache.aries.quiesce.api/1.0.0 = 30
diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/etc/system.properties b/opendaylight/distribution/opendaylight-karaf/src/main/resources/etc/system.properties
deleted file mode 100644 (file)
index a312d66..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-#
-# The properties defined in this file will be made available through system
-# properties at the very beginning of the Karaf's boot process.
-#
-
-# Use Equinox as default OSGi Framework Implementation
-karaf.framework=equinox
-
-# 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:
-osgi.hook.configurators.include=org.eclipse.virgo.kernel.equinox.extensions.hooks.ExtensionsHookConfigurator
-
-
-# Log level when the pax-logging service is not available
-# This level will only be used while the pax-logging service bundle
-# is not fully available.
-# To change log levels, please refer to the org.ops4j.pax.logging.cfg file
-# instead.
-org.ops4j.pax.logging.DefaultServiceLog.level = ERROR
-
-#
-# Name of this Karaf instance.
-#
-karaf.name = root
-
-#
-# Default repository where bundles will be loaded from before using
-# other Maven repositories.  For the full Maven configuration, see
-# the org.ops4j.pax.url.mvn.cfg file.
-#
-karaf.default.repository = system
-
-#
-# Location of a shell script that will be run when starting a shell
-# session.  This script can be used to create aliases and define
-# additional commands.
-#
-karaf.shell.init.script = ${karaf.etc}/shell.init.script
-
-#
-# Sets the maximum size of the shell command history. If not set,
-# defaults to 500 entries. Setting to 0 will disable history.
-#
-# karaf.shell.history.maxSize = 0
-
-#
-# Deletes the entire karaf.data directory at every start
-#
-karaf.clean.all = false
-
-#
-# Deletes the karaf.data/cache directory at every start
-#
-karaf.clean.cache = false
-
-#
-# Roles to use when logging into a local Karaf console.
-#
-# The syntax is the following:
-#   [classname:]principal
-# where classname is the class name of the principal object
-# (defaults to org.apache.karaf.jaas.modules.RolePrincipal)
-# and principal is the name of the principal of that class
-# (defaults to instance).
-#
-karaf.local.roles = admin,manager,viewer
-
-#
-# Set this empty property to avoid errors when validating xml documents.
-#
-xml.catalog.files =
-
-#
-# Suppress the bell in the console when hitting backspace too many times
-# for example
-#
-jline.nobell = true
-
-#
-# ServiceMix specs options
-#
-org.apache.servicemix.specs.debug = false
-org.apache.servicemix.specs.timeout = 0
-
-#
-# Settings for the OSGi 4.3 Weaving
-# By default, we will not weave any classes. Change this setting to include classes
-# that you application needs to have woven.
-#
-org.apache.aries.proxy.weaving.enabled = none
-# Classes not to weave - Aries default + Xerces which is known to have issues.
-org.apache.aries.proxy.weaving.disabled = org.objectweb.asm.*,org.slf4j.*,org.apache.log4j.*,javax.*,org.apache.xerces.*
-
-#
-# By default, only Karaf shell commands are secured, but additional services can be
-# secured by expanding this filter
-#
-karaf.secured.services = (&(osgi.command.scope=*)(osgi.command.function=*))
-
-#
-# Security properties
-#
-# To enable OSGi security, uncomment the properties below,
-# install the framework-security feature and restart.
-#
-#java.security.policy=${karaf.etc}/all.policy
-#org.osgi.framework.security=osgi
-#org.osgi.framework.trust.repositories=${karaf.etc}/trustStore.ks
index c8a7f01e132b519c5f522554faa7e2dd8bfd2ae7..130c096deb9545bdc4407eb146082d0dd44b738d 100644 (file)
@@ -9,67 +9,89 @@ package org.opendaylight.controller.frm;
 
 import java.util.HashSet;
 import java.util.Map;
-import java.util.Set;
 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.common.api.data.DataChangeEvent;
-import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+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(DataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
+    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.getCreatedConfigurationData().entrySet();
-        final Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updatedEntries =
-                new HashSet<Entry<InstanceIdentifier<? extends DataObject>, DataObject>>();
-
+                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.getUpdatedConfigurationData().entrySet();
+                changeEvent.getUpdatedData().entrySet();
         updatedEntries.addAll(updateConfigEntrySet);
         updatedEntries.removeAll(createdEntries);
-
+        /* All DataObjects for remove */
         final Set<InstanceIdentifier<? extends DataObject>> removeEntriesInstanceIdentifiers =
-                changeEvent.getRemovedConfigurationData();
-
+                changeEvent.getRemovedPaths();
+        /* Create DataObject processing (send to device) */
         for (final Entry<InstanceIdentifier<? extends DataObject>, DataObject> createdEntry : createdEntries) {
-            InstanceIdentifier<? extends DataObject> c_key = createdEntry.getKey();
-            DataObject c_value = createdEntry.getValue();
-            this.add(c_key, c_value);
+            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.getOriginalConfigurationData();
-
-            InstanceIdentifier<? extends Object> u_key = updatedEntrie.getKey();
-            final DataObject originalFlow = origConfigData.get(u_key);
-            final DataObject updatedFlow = updatedEntrie.getValue();
-            this.update(u_key, originalFlow, updatedFlow);
+                    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.getOriginalConfigurationData();
+                    changeEvent.getOriginalData();
 
             final DataObject removeValue = origConfigData.get(instanceId);
-            this.remove(instanceId, removeValue);
+            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;
     }
@@ -78,17 +100,74 @@ public abstract class AbstractChangeListener implements DataChangeListener {
         return "DOM-" + txNum.getAndIncrement();
     }
 
-    protected abstract void validate() throws IllegalStateException;
-
-    protected abstract void remove(
+    /**
+     * 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);
 
-    protected abstract void update(
-            final InstanceIdentifier<? extends DataObject> identifier,
+    /**
+     * 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);
 
-    protected abstract void add(
-            final InstanceIdentifier<? extends DataObject> identifier,
+    /**
+     * 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 2f986ea5bcbbf83c75d81adb9a6724855641fe60..c75c644c008dfe0aad4849a98a13a80f053a6e80 100644 (file)
@@ -10,52 +10,79 @@ 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.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
-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.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * Forwarding Rules Manager Activator
+ *
+ * Activator manages all Providers ({@link FlowProvider}, {@link GroupProvider},
+ * {@link MeterProvider} and the {@link FlowNodeReconcilProvider}).
+ * It registers all listeners (DataChangeEvent, ReconcilNotification)
+ * in the Session Initialization phase.
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ * *
+ */
 public class FRMActivator extends AbstractBindingAwareProvider {
 
     private final static Logger LOG = LoggerFactory.getLogger(FRMActivator.class);
 
-    private static FlowProvider flowProvider = new FlowProvider();
-    private static GroupProvider groupProvider = new GroupProvider();
-    private static MeterProvider meterProvider = new MeterProvider();
+    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();
+    }
 
     @Override
     public void onSessionInitiated(final ProviderContext session) {
-        DataProviderService flowSalService = session.<DataProviderService>getSALService(DataProviderService.class);
-        FRMActivator.flowProvider.setDataService(flowSalService);
-        SalFlowService rpcFlowSalService = session.<SalFlowService>getRpcService(SalFlowService.class);
-        FRMActivator.flowProvider.setSalFlowService(rpcFlowSalService);
-        FRMActivator.flowProvider.start();
-        DataProviderService groupSalService = session.<DataProviderService>getSALService(DataProviderService.class);
-        FRMActivator.groupProvider.setDataService(groupSalService);
-        SalGroupService rpcGroupSalService = session.<SalGroupService>getRpcService(SalGroupService.class);
-        FRMActivator.groupProvider.setSalGroupService(rpcGroupSalService);
-        FRMActivator.groupProvider.start();
-        DataProviderService meterSalService = session.<DataProviderService>getSALService(DataProviderService.class);
-        FRMActivator.meterProvider.setDataService(meterSalService);
-        SalMeterService rpcMeterSalService = session.<SalMeterService>getRpcService(SalMeterService.class);
-        FRMActivator.meterProvider.setSalMeterService(rpcMeterSalService);
-        FRMActivator.meterProvider.start();
+        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);
+        }
     }
 
     @Override
     protected void stopImpl(final BundleContext context) {
         try {
-            FRMActivator.flowProvider.close();
-            FRMActivator.groupProvider.close();
-            FRMActivator.meterProvider.close();
-        } catch (Throwable e) {
+            this.flowProvider.close();
+            this.groupProvider.close();
+            this.meterProvider.close();
+            this.flowNodeReconcilProvider.close();
+        } catch (Exception e) {
             LOG.error("Unexpected error by stopping FRMActivator", e);
-            throw new RuntimeException(e);
         }
     }
   }
\ 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
new file mode 100644 (file)
index 0000000..d7b54e8
--- /dev/null
@@ -0,0 +1,79 @@
+/**
+ * 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 !");
+    }
+}
index b60424513f2fb9f6c930e1648f937008bf9d203e..c10b0da2ba959d74800a918fc4b55c2fd7091c86 100644 (file)
@@ -7,22 +7,21 @@
  */
 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.service.rev130819.AddFlowInput;
+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.RemoveFlowInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
-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.UpdateFlowInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlow;
 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.UpdatedFlow;
 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.Flow;
+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;
@@ -31,90 +30,97 @@ 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 final static Logger LOG = LoggerFactory.getLogger(FlowChangeListener.class);
+    private static final Logger LOG = LoggerFactory.getLogger(FlowChangeListener.class);
 
-    private final SalFlowService salFlowService;
-
-    public SalFlowService getSalFlowService() {
-        return this.salFlowService;
-    }
+    private final FlowProvider provider;
 
-    public FlowChangeListener(final SalFlowService manager) {
-        this.salFlowService = manager;
+    public FlowChangeListener (final FlowProvider provider) {
+        this.provider = Preconditions.checkNotNull(provider, "FlowProvider can not be null !");
     }
 
     @Override
-    protected void validate() throws IllegalStateException {
-        FlowTransactionValidator.validate(this);
-    }
+    protected void remove(final InstanceIdentifier<? extends DataObject> identifier,
+                          final DataObject removeDataObj) {
 
-    @Override
-    protected void remove(InstanceIdentifier<? extends DataObject> identifier, DataObject removeDataObj) {
-        if ((removeDataObj instanceof Flow)) {
-
-            final Flow flow = ((Flow) removeDataObj);
-            final InstanceIdentifier<Table> tableInstanceId = identifier.<Table> firstIdentifierOf(Table.class);
-            final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
-            final RemoveFlowInputBuilder builder = new RemoveFlowInputBuilder(flow);
-
-            builder.setFlowRef(new FlowRef(identifier));
-            builder.setNode(new NodeRef(nodeInstanceId));
-            builder.setFlowTable(new FlowTableRef(tableInstanceId));
-
-            Uri uri = new Uri(this.getTransactionId());
-            builder.setTransactionUri(uri);
-            this.salFlowService.removeFlow((RemoveFlowInput) builder.build());
-            LOG.debug("Transaction {} - Removed Flow has removed flow: {}", new Object[]{uri, 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(InstanceIdentifier<? extends DataObject> identifier, DataObject original, DataObject update) {
-        if (original instanceof Flow && update instanceof Flow) {
+    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();
 
-            final Flow originalFlow = ((Flow) original);
-            final Flow updatedFlow = ((Flow) update);
-            final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node>firstIdentifierOf(Node.class);
-            final UpdateFlowInputBuilder builder = new UpdateFlowInputBuilder();
+        builder.setNode(new NodeRef(nodeIdent));
+        builder.setFlowRef(new FlowRef(identifier));
 
-            builder.setNode(new NodeRef(nodeInstanceId));
-            builder.setFlowRef(new FlowRef(identifier));
+        Uri uri = new Uri(this.getTransactionId());
+        builder.setTransactionUri(uri);
 
-            Uri uri = new Uri(this.getTransactionId());
-            builder.setTransactionUri(uri);
+        builder.setUpdatedFlow((new UpdatedFlowBuilder(updatedFlow)).build());
+        builder.setOriginalFlow((new OriginalFlowBuilder(originalFlow)).build());
 
-            builder.setUpdatedFlow((UpdatedFlow) (new UpdatedFlowBuilder(updatedFlow)).build());
-            builder.setOriginalFlow((OriginalFlow) (new OriginalFlowBuilder(originalFlow)).build());
+        this.provider.getSalFlowService().updateFlow(builder.build());
+        LOG.debug("Transaction {} - Update Flow has updated flow {} with {}", new Object[]{uri, original, update});
+    }
 
-            this.salFlowService.updateFlow((UpdateFlowInput) 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 void add(InstanceIdentifier<? extends DataObject> identifier, DataObject addDataObj) {
-        if ((addDataObj instanceof Flow)) {
-
-            final Flow flow = ((Flow) addDataObj);
-            final InstanceIdentifier<Table> tableInstanceId = identifier.<Table> firstIdentifierOf(Table.class);
-            final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
-            final AddFlowInputBuilder builder = new AddFlowInputBuilder(flow);
-
-            builder.setNode(new NodeRef(nodeInstanceId));
-            builder.setFlowRef(new FlowRef(identifier));
-            builder.setFlowTable(new FlowTableRef(tableInstanceId));
-
-            Uri uri = new Uri(this.getTransactionId());
-            builder.setTransactionUri(uri);
-            this.salFlowService.addFlow((AddFlowInput) builder.build());
-            LOG.debug("Transaction {} - Add Flow has added flow: {}", new Object[]{uri, addDataObj});
-        }
+    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));
     }
 }
index 33db529598dc9115c4dfcb52906f585bcb00313e..8c248fa264055b615d58bb986b8faaad5d5110b3 100644 (file)
@@ -7,9 +7,11 @@
  */
 package org.opendaylight.controller.frm.flow;
 
-import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+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;
@@ -17,54 +19,89 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalF
 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.InstanceIdentifier.InstanceIdentifierBuilder;
 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 final static Logger LOG = LoggerFactory.getLogger(FlowProvider.class);
+    private static final Logger LOG = LoggerFactory.getLogger(FlowProvider.class);
 
     private SalFlowService salFlowService;
-    private DataProviderService dataService;
+    private DataBroker dataService;
 
     /* DataChangeListener */
-    private FlowChangeListener flowDataChangeListener;
-    ListenerRegistration<DataChangeListener> flowDataChangeListenerRegistration;
+    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.");
 
-    public void start() {
         /* Build Path */
-        InstanceIdentifierBuilder<Nodes> nodesBuilder = InstanceIdentifier.<Nodes> builder(Nodes.class);
-        InstanceIdentifierBuilder<Node> nodeChild = nodesBuilder.<Node> child(Node.class);
-        InstanceIdentifierBuilder<FlowCapableNode> augmentFlowCapNode = nodeChild.<FlowCapableNode> augmentation(FlowCapableNode.class);
-        InstanceIdentifierBuilder<Table> tableChild = augmentFlowCapNode.<Table> child(Table.class);
-        InstanceIdentifierBuilder<Flow> flowChild = tableChild.<Flow> child(Flow.class);
-        final InstanceIdentifier<? extends DataObject> flowDataObjectPath = flowChild.toInstance();
+        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(this.salFlowService);
-        this.flowDataChangeListenerRegistration = this.dataService.registerDataChangeListener(flowDataObjectPath, flowDataChangeListener);
-        LOG.info("Flow Config Provider started.");
-    }
+        this.flowDataChangeListener = new FlowChangeListener(FlowProvider.this);
+        this.flowDataChangeListenerRegistration =
+                this.dataService.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+                        flowIdentifier, flowDataChangeListener, DataChangeScope.SUBTREE);
 
-    protected DataModificationTransaction startChange() {
-        return this.dataService.beginTransaction();
+        LOG.info("FRM Flow Config Provider started.");
     }
 
     @Override
-    public void close() throws Exception {
-        if(flowDataChangeListenerRegistration != null){
-            flowDataChangeListenerRegistration.close();
+    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 void setDataService(final DataProviderService dataService) {
-        this.dataService = dataService;
+    public DataChangeListener getFlowDataChangeListener() {
+        return flowDataChangeListener;
+    }
+
+    public SalFlowService getSalFlowService() {
+        return salFlowService;
     }
 
-    public void setSalFlowService(final SalFlowService salFlowService) {
-        this.salFlowService = salFlowService;
+    public DataBroker getDataService() {
+        return dataService;
     }
 }
index 54f12bfdcf64346191ab589969e579b0dfdf5db7..9b03eaad8ccfd1373467dbf85353ef8b558dd9c3 100644 (file)
@@ -8,17 +8,12 @@
 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.AddGroupInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder;
-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.UpdateGroupInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroup;
 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.UpdatedGroup;
 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;
@@ -29,85 +24,88 @@ 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 final static Logger LOG = LoggerFactory.getLogger(GroupChangeListener.class);
-
-    private final SalGroupService salGroupService;
+    private static final Logger LOG = LoggerFactory.getLogger(GroupChangeListener.class);
 
-    public SalGroupService getSalGroupService() {
-        return this.salGroupService;
-    }
+    private final GroupProvider provider;
 
-    public GroupChangeListener(final SalGroupService manager) {
-        this.salGroupService = manager;
+    public GroupChangeListener(final GroupProvider provider) {
+        this.provider = Preconditions.checkNotNull(provider, "GroupProvider can not be null !");
     }
 
     @Override
-    protected void validate() throws IllegalStateException {
-        GroupTransactionValidator.validate(this);
+    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 remove(InstanceIdentifier<? extends DataObject> identifier, DataObject removeDataObj) {
-        if ((removeDataObj instanceof Group)) {
+    protected void update(final InstanceIdentifier<? extends DataObject> identifier,
+                          final DataObject original, final DataObject update) {
 
-            final Group group = ((Group) removeDataObj);
-            final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
-            final RemoveGroupInputBuilder builder = new RemoveGroupInputBuilder(group);
+        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));
+        builder.setNode(new NodeRef(nodeInstanceId));
+        builder.setGroupRef(new GroupRef(identifier));
 
-            Uri uri = new Uri(this.getTransactionId());
-            builder.setTransactionUri(uri);
-            this.salGroupService.removeGroup((RemoveGroupInput) builder.build());
-            LOG.debug("Transaction {} - Remove Group has removed group: {}", new Object[]{uri, removeDataObj});
-        }
-    }
+        Uri uri = new Uri(this.getTransactionId());
+        builder.setTransactionUri(uri);
 
-    @Override
-    protected void update(InstanceIdentifier<? extends DataObject> identifier, DataObject original, DataObject update) {
-        if (original instanceof Group && update instanceof Group) {
+        builder.setUpdatedGroup((new UpdatedGroupBuilder(updatedGroup)).build());
+        builder.setOriginalGroup((new OriginalGroupBuilder(originalGroup)).build());
 
-            final Group originalGroup = ((Group) original);
-            final Group updatedGroup = ((Group) update);
-            final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
-            final UpdateGroupInputBuilder builder = new UpdateGroupInputBuilder();
+        this.provider.getSalGroupService().updateGroup(builder.build());
+        LOG.debug("Transaction {} - Update Group has updated group {} with group {}", new Object[]{uri, original, update});
+    }
 
-            builder.setNode(new NodeRef(nodeInstanceId));
-            builder.setGroupRef(new GroupRef(identifier));
+    @Override
+    protected void add(final InstanceIdentifier<? extends DataObject> identifier,
+                       final DataObject addDataObj) {
 
-            Uri uri = new Uri(this.getTransactionId());
-            builder.setTransactionUri(uri);
+        final Group group = ((Group) addDataObj);
+        final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
+        final AddGroupInputBuilder builder = new AddGroupInputBuilder(group);
 
-            builder.setUpdatedGroup((UpdatedGroup) (new UpdatedGroupBuilder(updatedGroup)).build());
-            builder.setOriginalGroup((OriginalGroup) (new OriginalGroupBuilder(originalGroup)).build());
+        builder.setNode(new NodeRef(nodeInstanceId));
+        builder.setGroupRef(new GroupRef(identifier));
 
-            this.salGroupService.updateGroup((UpdateGroupInput) builder.build());
-            LOG.debug("Transaction {} - Update Group has updated group {} with group {}", new Object[]{uri, original, update});
-        }
+        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 void add(InstanceIdentifier<? extends DataObject> identifier, DataObject addDataObj) {
-        if ((addDataObj instanceof Group)) {
-            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.salGroupService.addGroup((AddGroupInput) builder.build());
-            LOG.debug("Transaction {} - Add Group has added group: {}", new Object[]{uri, addDataObj});
-        }
+    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));
     }
 }
index 9f2806e929a25344726fa125ec1ec7b918b8197e..a999242bc08ed8c16fe2cde4074248435d815131 100644 (file)
@@ -7,61 +7,99 @@
  */
 package org.opendaylight.controller.frm.group;
 
-import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+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.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 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 final static Logger LOG = LoggerFactory.getLogger(GroupProvider.class);
+    private static final Logger LOG = LoggerFactory.getLogger(GroupProvider.class);
 
     private SalGroupService salGroupService;
-    private DataProviderService dataService;
+    private DataBroker dataService;
 
     /* DataChangeListener */
-    private GroupChangeListener groupDataChangeListener;
-    ListenerRegistration<DataChangeListener> groupDataChangeListenerRegistration;
+    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.");
 
-    public void start() {
         /* Build Path */
-        InstanceIdentifierBuilder<Nodes> nodesBuilder = InstanceIdentifier.<Nodes> builder(Nodes.class);
-        InstanceIdentifierBuilder<Node> nodeChild = nodesBuilder.<Node> child(Node.class);
-        InstanceIdentifierBuilder<FlowCapableNode> augmentFlowCapNode = nodeChild.<FlowCapableNode> augmentation(FlowCapableNode.class);
-        InstanceIdentifierBuilder<Group> groupChild = augmentFlowCapNode.<Group> child(Group.class);
-        final InstanceIdentifier<? extends DataObject> groupDataObjectPath = groupChild.toInstance();
+        InstanceIdentifier<Group> groupIdentifier = InstanceIdentifier.create(Nodes.class)
+                .child(Node.class).augmentation(FlowCapableNode.class).child(Group.class);
 
         /* DataChangeListener registration */
-        this.groupDataChangeListener = new GroupChangeListener(this.salGroupService);
-        this.groupDataChangeListenerRegistration = this.dataService.registerDataChangeListener(groupDataObjectPath, groupDataChangeListener);
-        LOG.info("Group Config Provider started.");
-    }
+        this.groupDataChangeListener = new GroupChangeListener(GroupProvider.this);
+        this.groupDataChangeListenerRegistration = this.dataService.registerDataChangeListener(
+                LogicalDatastoreType.CONFIGURATION, groupIdentifier, groupDataChangeListener, DataChangeScope.SUBTREE);
 
-    protected DataModificationTransaction startChange() {
-        return this.dataService.beginTransaction();
+        LOG.info("FRM Group Config Provider started.");
     }
 
-    public void close() throws Exception {
-        if(groupDataChangeListenerRegistration != null){
-            groupDataChangeListenerRegistration.close();
+    @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 void setDataService(final DataProviderService dataService) {
-        this.dataService = dataService;
+    public DataChangeListener getGroupDataChangeListener() {
+        return groupDataChangeListener;
+    }
+
+    public SalGroupService getSalGroupService() {
+        return salGroupService;
     }
 
-    public void setSalGroupService(final SalGroupService salGroupService) {
-        this.salGroupService = salGroupService;
+    public DataBroker getDataService() {
+        return dataService;
     }
 }
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransactionValidator.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransactionValidator.java
deleted file mode 100644 (file)
index 88eea0d..0000000
+++ /dev/null
@@ -1,15 +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;
-
-public class GroupTransactionValidator {
-
-    public static void validate(GroupChangeListener transaction) throws IllegalStateException {
-        // NOOP
-    }
-}
index 48d5257978cc28ff5c86a44449b55a45f15024cc..a2def8490f77b0fbdca938511ddd9ed11f062070 100644 (file)
@@ -8,19 +8,14 @@
 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.AddMeterInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInputBuilder;
-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.UpdateMeterInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeter;
 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.UpdatedMeter;
 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;
@@ -29,86 +24,89 @@ 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 final static Logger LOG = LoggerFactory.getLogger(MeterChangeListener.class);
-
-    private final SalMeterService salMeterService;
-
-    public SalMeterService getSalMeterService() {
-        return this.salMeterService;
-    }
+    private static final Logger LOG = LoggerFactory.getLogger(MeterChangeListener.class);
 
-    public MeterChangeListener(final SalMeterService manager) {
-        this.salMeterService = manager;
-    }
+    private final MeterProvider provider;
 
-    @Override
-    protected void validate() throws IllegalStateException {
-        MeterTransactionValidator.validate(this);
+    public MeterChangeListener (final MeterProvider provider) {
+        this.provider = Preconditions.checkNotNull(provider, "MeterProvider can not be null !");
     }
 
     @Override
-    protected void remove(InstanceIdentifier<? extends DataObject> identifier, DataObject removeDataObj) {
-        if ((removeDataObj instanceof Meter)) {
+    protected void remove(final InstanceIdentifier<? extends DataObject> identifier,
+                          final DataObject removeDataObj) {
 
-            final Meter meter = ((Meter) removeDataObj);
-            final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
-            final RemoveMeterInputBuilder builder = new RemoveMeterInputBuilder(meter);
+        final Meter meter = ((Meter) removeDataObj);
+        final InstanceIdentifier<Node> nodeIdent = identifier.firstIdentifierOf(Node.class);
+        final RemoveMeterInputBuilder builder = new RemoveMeterInputBuilder(meter);
 
-            builder.setNode(new NodeRef(nodeInstanceId));
-            builder.setMeterRef(new MeterRef(identifier));
+        builder.setNode(new NodeRef(nodeIdent));
+        builder.setMeterRef(new MeterRef(identifier));
 
-            Uri uri = new Uri(this.getTransactionId());
-            builder.setTransactionUri(uri);
-            this.salMeterService.removeMeter((RemoveMeterInput) builder.build());
-            LOG.debug("Transaction {} - Remove Meter has removed meter: {}", new Object[]{uri, removeDataObj});
-        }
+        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(InstanceIdentifier<? extends DataObject> identifier, DataObject original, DataObject update) {
-        if (original instanceof Meter && update instanceof Meter) {
+    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.<Node> firstIdentifierOf(Node.class);
-            final UpdateMeterInputBuilder builder = new UpdateMeterInputBuilder();
+        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));
+        builder.setNode(new NodeRef(nodeInstanceId));
+        builder.setMeterRef(new MeterRef(identifier));
 
-            Uri uri = new Uri(this.getTransactionId());
-            builder.setTransactionUri(uri);
+        Uri uri = new Uri(this.getTransactionId());
+        builder.setTransactionUri(uri);
 
-            builder.setUpdatedMeter((UpdatedMeter) (new UpdatedMeterBuilder(updatedMeter)).build());
-            builder.setOriginalMeter((OriginalMeter) (new OriginalMeterBuilder(originalMeter)).build());
+        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});
 
-            this.salMeterService.updateMeter((UpdateMeterInput) builder.build());
-            LOG.debug("Transaction {} - Update Meter has updated meter {} with {}", new Object[]{uri, original, update});
-        }
     }
 
     @Override
-    protected void add(InstanceIdentifier<? extends DataObject> identifier, DataObject addDataObj) {
-        if ((addDataObj instanceof Meter)) {
+    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);
 
-            final Meter meter = ((Meter) addDataObj);
-            final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
-            final AddMeterInputBuilder builder = new AddMeterInputBuilder(meter);
+        builder.setNode(new NodeRef(nodeInstanceId));
+        builder.setMeterRef(new MeterRef(identifier));
 
-            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) {
 
-            Uri uri = new Uri(this.getTransactionId());
-            builder.setTransactionUri(uri);
-            this.salMeterService.addMeter((AddMeterInput) builder.build());
-            LOG.debug("Transaction {} - Add Meter has added meter: {}", new Object[]{uri, addDataObj});
-        }
+        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));
     }
-}
\ No newline at end of file
+}
index 8596c3fec6e7f8f04dc2fcc4917240d35b85f8eb..44de7af4957a5dca73c2ce8ae893d06877b247e5 100644 (file)
@@ -7,61 +7,99 @@
  */
 package org.opendaylight.controller.frm.meter;
 
-import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+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.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 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 final static Logger LOG = LoggerFactory.getLogger(MeterProvider.class);
+    private static final Logger LOG = LoggerFactory.getLogger(MeterProvider.class);
 
-    private DataProviderService dataService;
     private SalMeterService salMeterService;
+    private DataBroker dataService;
 
     /* DataChangeListener */
-    private MeterChangeListener meterDataChangeListener;
-    ListenerRegistration<DataChangeListener> meterDataChangeListenerRegistration;
+    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.");
 
-    public void start() {
         /* Build Path */
-        InstanceIdentifierBuilder<Nodes> nodesBuilder = InstanceIdentifier.<Nodes> builder(Nodes.class);
-        InstanceIdentifierBuilder<Node> nodeChild = nodesBuilder.<Node> child(Node.class);
-        InstanceIdentifierBuilder<FlowCapableNode> augmentFlowCapNode = nodeChild.<FlowCapableNode> augmentation(FlowCapableNode.class);
-        InstanceIdentifierBuilder<Meter> meterChild = augmentFlowCapNode.<Meter> child(Meter.class);
-        final InstanceIdentifier<? extends DataObject> meterDataObjectPath = meterChild.toInstance();
+        InstanceIdentifier<Meter> meterIdentifier = InstanceIdentifier.create(Nodes.class)
+                .child(Node.class).augmentation(FlowCapableNode.class).child(Meter.class);
 
         /* DataChangeListener registration */
-        this.meterDataChangeListener = new MeterChangeListener(this.salMeterService);
-        this.meterDataChangeListenerRegistration = this.dataService.registerDataChangeListener(meterDataObjectPath, meterDataChangeListener);
-        LOG.info("Meter Config Provider started.");
-    }
+        this.meterDataChangeListener = new MeterChangeListener(MeterProvider.this);
+        this.meterDataChangeListenerRegistration =
+                this.dataService.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+                        meterIdentifier, meterDataChangeListener, DataChangeScope.SUBTREE);
 
-    protected DataModificationTransaction startChange() {
-        return this.dataService.beginTransaction();
+        LOG.info("FRM Meter Config Provider started.");
     }
 
-    public void close() throws Exception {
-        if(meterDataChangeListenerRegistration != null){
-            meterDataChangeListenerRegistration.close();
+    @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 void setDataService(final DataProviderService dataService) {
-        this.dataService = dataService;
+    public DataChangeListener getMeterDataChangeListener() {
+        return meterDataChangeListener;
+    }
+
+    public DataBroker getDataService() {
+        return dataService;
     }
 
-    public void setSalMeterService(final SalMeterService salMeterService) {
-        this.salMeterService = salMeterService;
+    public SalMeterService getSalMeterService() {
+        return salMeterService;
     }
-}
\ No newline at end of file
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransactionValidator.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransactionValidator.java
deleted file mode 100644 (file)
index c8fba23..0000000
+++ /dev/null
@@ -1,15 +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;
-
-public class MeterTransactionValidator {
-
-    public static void validate(MeterChangeListener transaction) throws IllegalStateException {
-        // NOOP
-    }
-}
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
new file mode 100644 (file)
index 0000000..eb5ae4a
--- /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.reconil;
+
+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;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * 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(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 */
+            for (Group group : flowCapNode.get().getGroup()) {
+                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 */
+            for (Meter meter : flowCapNode.get().getMeter()) {
+                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 */
+            for (Table flowTable : flowCapNode.get().getTable()) {
+                final InstanceIdentifier<Table> tableIdent = flowNodeIdent.child(Table.class, flowTable.getKey());
+                for (Flow flow : flowTable.getFlow()) {
+                    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, 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
new file mode 100644 (file)
index 0000000..ad970d6
--- /dev/null
@@ -0,0 +1,115 @@
+/**
+ * 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;
+    }
+}
index ff3984a548eeb3a7d6ed2f93da04b2f1c801802b..29ac12393ac54aa33d2de6b01af01c1213db1c4c 100644 (file)
@@ -103,9 +103,10 @@ class FlowCapableInventoryProvider implements AutoCloseable, Runnable {
                 LOG.debug("Processed {} operations, submitting transaction {}", ops, tx.getIdentifier());
 
                 final CheckedFuture<Void, TransactionCommitFailedException> result = tx.submit();
-                Futures.addCallback(result, new FutureCallback<Object>() {
+                Futures.addCallback(result, new FutureCallback<Void>() {
                     @Override
-                    public void onSuccess(Object o) {
+                    public void onSuccess(Void aVoid) {
+                        //NOOP
                     }
 
                     @Override
index 1b031990ab9f6808aed11c265e0672614559f4c2..57ec89307678ae5e28641671182650e8de9254b6 100644 (file)
@@ -7,13 +7,20 @@
  */
 package org.opendaylight.controller.md.inventory.manager;
 
+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 org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 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.FlowCapableNodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated;
+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.inventory.rev130819.NodeConnectorRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
@@ -27,6 +34,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.No
 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.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 import org.slf4j.Logger;
@@ -100,21 +108,60 @@ class NodeChangeCommiter implements OpendaylightInventoryListener {
         LOG.debug("Node updated notification received.");
         manager.enqueue(new InventoryOperation() {
             @Override
-            public void applyOperation(final ReadWriteTransaction tx) {
+            public void applyOperation(ReadWriteTransaction tx) {
                 final NodeRef ref = node.getNodeRef();
+                @SuppressWarnings("unchecked")
+                InstanceIdentifierBuilder<Node> builder = ((InstanceIdentifier<Node>) ref.getValue()).builder();
+                InstanceIdentifierBuilder<FlowCapableNode> augmentation = builder.augmentation(FlowCapableNode.class);
+                final InstanceIdentifier<FlowCapableNode> path = augmentation.build();
+                CheckedFuture readFuture = tx.read(LogicalDatastoreType.OPERATIONAL, path);
+                Futures.addCallback(readFuture, new FutureCallback<Optional<? extends DataObject>>() {
+                    @Override
+                    public void onSuccess(Optional<? extends DataObject> optional) {
+                        enqueueWriteNodeDataTx(node, flowNode, path);
+                        if (!optional.isPresent()) {
+                            enqueuePutTable0Tx(ref);
+                        }
+                    }
+
+                    @Override
+                    public void onFailure(Throwable throwable) {
+                        LOG.debug(String.format("Can't retrieve node data for node %s. Writing node data with table0.", node));
+                        enqueueWriteNodeDataTx(node, flowNode, path);
+                        enqueuePutTable0Tx(ref);
+                    }
+                });
+            }
+        });
+    }
+
+    private void enqueueWriteNodeDataTx(final NodeUpdated node, final FlowCapableNodeUpdated flowNode, final InstanceIdentifier<FlowCapableNode> path) {
+        manager.enqueue(new InventoryOperation() {
+            @Override
+            public void applyOperation(final ReadWriteTransaction tx) {
                 final NodeBuilder nodeBuilder = new NodeBuilder(node);
                 nodeBuilder.setKey(new NodeKey(node.getId()));
 
                 final FlowCapableNode augment = InventoryMapping.toInventoryAugment(flowNode);
                 nodeBuilder.addAugmentation(FlowCapableNode.class, augment);
-
-                @SuppressWarnings("unchecked")
-                InstanceIdentifierBuilder<Node> builder = ((InstanceIdentifier<Node>) ref.getValue()).builder();
-                InstanceIdentifierBuilder<FlowCapableNode> augmentation = builder.augmentation(FlowCapableNode.class);
-                final InstanceIdentifier<FlowCapableNode> path = augmentation.build();
                 LOG.debug("updating node :{} ", path);
                 tx.put(LogicalDatastoreType.OPERATIONAL, path, augment);
             }
         });
     }
+
+    private void enqueuePutTable0Tx(final NodeRef ref) {
+        manager.enqueue(new InventoryOperation() {
+            @Override
+            public void applyOperation(ReadWriteTransaction tx) {
+                final TableKey tKey = new TableKey((short) 0);
+                final InstanceIdentifier<Table> tableIdentifier =
+                        ((InstanceIdentifier<Node>) ref.getValue()).augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tKey));
+                TableBuilder tableBuilder = new TableBuilder();
+                Table table0 = tableBuilder.setId((short) 0).build();
+                LOG.debug("writing table :{} ", tableIdentifier);
+                tx.put(LogicalDatastoreType.OPERATIONAL, tableIdentifier, table0, true);
+            }
+        });
+    }
 }
index 65362a179094b98104c8345a0ec7dd28fced2296..605cb9004a65235dd6cf66b0ff065514f54ad183 100644 (file)
@@ -229,4 +229,16 @@ module flow-node-inventory {
         uses flow-node-connector;
     }
 
+    augment "/inv:nodes/inv:node/table" {
+        ext:augment-identifier "flow-cookie-mapping";
+        list flow-cookie-map {
+            key "cookie";
+            leaf cookie {
+                type flow:flow-cookie;
+            }
+            leaf-list flow-ids {
+                type flow-id;
+            }
+        }
+    }
 }
index b62e4529f341f76a53d522f49dd4f935e781887d..bd78c584ee95ec9a6f9fff0f3dce728c154f0222 100644 (file)
@@ -39,14 +39,20 @@ public abstract class AbstractBrokerAwareActivator implements BundleActivator {
 
         @Override
         public void modifiedService(ServiceReference<BindingAwareBroker> reference, BindingAwareBroker service) {
-            // TODO Auto-generated method stub
-
+            removedService(reference, service);
+            addingService(reference);
         }
 
         @Override
         public void removedService(ServiceReference<BindingAwareBroker> reference, BindingAwareBroker service) {
-            // TODO Auto-generated method stub
+            broker = context.getService(reference);
+            mdActivationPool.execute(new Runnable() {
 
+                @Override
+                public void run() {
+                    onBrokerRemoved(broker, context);
+                }
+            });
         }
 
     };
@@ -117,6 +123,6 @@ public abstract class AbstractBrokerAwareActivator implements BundleActivator {
     protected abstract void onBrokerAvailable(BindingAwareBroker broker, BundleContext context);
 
     protected void onBrokerRemoved(BindingAwareBroker broker, BundleContext context) {
-
+        stopImpl(context);
     }
 }
index 539f9d45c8b8c30ebfcde9da22229bd4c2a547ab..74cceb1cbd55fc786b78e3f111b2a82a60bd8751 100644 (file)
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>binding-generator-impl</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.yangtools</groupId>
-      <artifactId>binding-data-codec</artifactId>
-      <version>0.6.2-SNAPSHOT</version>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-data-impl</artifactId>
index 93d99c832fcc2bbffe5a7c5f851fe2fec2ef7558..018e26878c9873490d6c3ed88822edb78efe0280 100644 (file)
@@ -2,13 +2,14 @@ package org.opendaylight.controller.config.yang.md.sal.binding.impl;
 
 import java.util.Collection;
 import java.util.Collections;
-import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+
 import org.opendaylight.controller.md.sal.binding.impl.ForwardedBindingDataBroker;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
 import org.opendaylight.controller.sal.core.api.Provider;
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
 
 public class BindingAsyncDataBrokerImplModule extends
         org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractBindingAsyncDataBrokerImplModule implements
@@ -35,7 +36,7 @@ public class BindingAsyncDataBrokerImplModule extends
     @Override
     public java.lang.AutoCloseable createInstance() {
         Broker domBroker = getDomAsyncBrokerDependency();
-        BindingToNormalizedNodeCodec mappingService = getBindingMappingServiceDependency();
+        BindingIndependentMappingService mappingService = getBindingMappingServiceDependency();
 
         // FIXME: Switch this to DOM Broker registration which would not require
         // BundleContext when API are updated.
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/DataBrokerImplModule.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/DataBrokerImplModule.java
new file mode 100644 (file)
index 0000000..4a4e800
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.config.yang.md.sal.binding.impl;
+
+import java.util.concurrent.ExecutorService;
+
+import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
+import org.opendaylight.controller.sal.binding.impl.RootDataBrokerImpl;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingDomConnectorDeployer;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;
+import org.opendaylight.controller.sal.binding.impl.forward.DomForwardedDataBrokerImpl;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+
+/**
+*
+*/
+public final class DataBrokerImplModule extends
+        org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractDataBrokerImplModule {
+
+    public DataBrokerImplModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public DataBrokerImplModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            final DataBrokerImplModule oldModule, final java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void validate() {
+        super.validate();
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        RootDataBrokerImpl dataBindingBroker;
+
+
+        ExecutorService listeningExecutor = SingletonHolder.getDefaultCommitExecutor();
+        BindingIndependentMappingService potentialMapping = getMappingServiceDependency();
+        if (getDomBrokerDependency() != null && potentialMapping != null) {
+
+            dataBindingBroker = createDomConnectedBroker(listeningExecutor,potentialMapping);
+        } else {
+            dataBindingBroker = createStandAloneBroker(listeningExecutor);
+        }
+        dataBindingBroker.registerRuntimeBean(getRootRuntimeBeanRegistratorWrapper());
+        dataBindingBroker.setNotificationExecutor(SingletonHolder.getDefaultChangeEventExecutor());
+        return dataBindingBroker;
+    }
+
+
+    private RootDataBrokerImpl createStandAloneBroker(final ExecutorService listeningExecutor) {
+        RootDataBrokerImpl broker = new RootDataBrokerImpl();
+        broker.setExecutor(listeningExecutor);
+        return broker;
+    }
+
+    private RootDataBrokerImpl createDomConnectedBroker(final ExecutorService listeningExecutor, final BindingIndependentMappingService mappingService) {
+        DomForwardedDataBrokerImpl forwardedBroker = new DomForwardedDataBrokerImpl();
+        forwardedBroker.setExecutor(listeningExecutor);
+        BindingIndependentConnector connector = BindingDomConnectorDeployer.createConnector(mappingService);
+        getDomBrokerDependency().registerProvider(forwardedBroker, null);
+        ProviderSession domContext = forwardedBroker.getDomProviderContext();
+        forwardedBroker.setConnector(connector);
+        forwardedBroker.setDomProviderContext(domContext);
+        forwardedBroker.startForwarding();
+        return forwardedBroker;
+    }
+
+}
@@ -1,15 +1,17 @@
-/**
+/*
  * 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;
+package org.opendaylight.controller.config.yang.md.sal.binding.impl;
+
 
-public class FlowTransactionValidator {
+/**
+*
+*/
+public class DataBrokerImplModuleFactory extends
+        org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractDataBrokerImplModuleFactory {
 
-    public static void validate(FlowChangeListener transaction) throws IllegalStateException {
-        // NOOP
-    }
 }
index 2bc673adfff4219a9b6b84b07fc478fd8fd7164b..0ea30f7e66a817f63c63cc81e20f3890170ea7b5 100644 (file)
@@ -7,10 +7,9 @@
  */
 package org.opendaylight.controller.config.yang.md.sal.binding.impl;
 
-import com.google.common.util.concurrent.ListeningExecutorService;
 import java.util.Collection;
 import java.util.Collections;
-import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+
 import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
 import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
@@ -19,6 +18,9 @@ import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
 import org.opendaylight.controller.sal.core.api.Provider;
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+
+import com.google.common.util.concurrent.ListeningExecutorService;
 
 /**
 *
@@ -49,7 +51,7 @@ public final class ForwardedCompatibleDataBrokerImplModule extends
     @Override
     public java.lang.AutoCloseable createInstance() {
         ListeningExecutorService listeningExecutor = SingletonHolder.getDefaultCommitExecutor();
-        BindingToNormalizedNodeCodec mappingService = getBindingMappingServiceDependency();
+        BindingIndependentMappingService mappingService = getBindingMappingServiceDependency();
 
         Broker domBroker = getDomAsyncBrokerDependency();
         ProviderSession session = domBroker.registerProvider(this, null);
@@ -58,7 +60,7 @@ public final class ForwardedCompatibleDataBrokerImplModule extends
         ForwardedBackwardsCompatibleDataBroker dataBroker = new ForwardedBackwardsCompatibleDataBroker(domDataBroker,
                 mappingService, schemaService,listeningExecutor);
 
-        dataBroker.setConnector(BindingDomConnectorDeployer.createConnector(mappingService.getLegacy()));
+        dataBroker.setConnector(BindingDomConnectorDeployer.createConnector(getBindingMappingServiceDependency()));
         dataBroker.setDomProviderContext(session);
         return dataBroker;
     }
index a15b1d746c5f5709374387f996056f6f979e2025..b0c2d742e214046be839cca263dbc0652005aa9b 100644 (file)
@@ -7,18 +7,12 @@
  */
 package org.opendaylight.controller.config.yang.md.sal.binding.impl;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
 import java.util.Hashtable;
 import java.util.Map.Entry;
 import java.util.Set;
-import javassist.ClassPool;
-import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+
 import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
-import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
-import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
 import org.opendaylight.yangtools.concepts.Delegator;
-import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
 import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
@@ -35,6 +29,9 @@ import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
 /**
 *
 */
@@ -45,14 +42,14 @@ public final class RuntimeMappingModule extends
 
     private BundleContext bundleContext;
 
-    public RuntimeMappingModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
-            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+    public RuntimeMappingModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
         super(identifier, dependencyResolver);
     }
 
-    public RuntimeMappingModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
-            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
-            final RuntimeMappingModule oldModule, final java.lang.AutoCloseable oldInstance) {
+    public RuntimeMappingModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            RuntimeMappingModule oldModule, java.lang.AutoCloseable oldInstance) {
         super(identifier, dependencyResolver, oldModule, oldInstance);
     }
 
@@ -64,48 +61,41 @@ public final class RuntimeMappingModule extends
     }
 
     @Override
-    public boolean canReuseInstance(final AbstractRuntimeMappingModule oldModule) {
+    public boolean canReuseInstance(AbstractRuntimeMappingModule oldModule) {
         return true;
     }
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-        final GeneratedClassLoadingStrategy classLoading = getGlobalClassLoadingStrategy();
-        final BindingIndependentMappingService legacyMapping = getGlobalLegacyMappingService(classLoading);
-        BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(new StreamWriterGenerator(SingletonHolder.JAVASSIST));
-        BindingToNormalizedNodeCodec instance = new BindingToNormalizedNodeCodec(classLoading, legacyMapping, codecRegistry);
-        bundleContext.registerService(SchemaContextListener.class, instance, new Hashtable<String,String>());
-        return instance;
-    }
 
-    private BindingIndependentMappingService getGlobalLegacyMappingService(final GeneratedClassLoadingStrategy classLoading) {
-        BindingIndependentMappingService potential = tryToReuseGlobalMappingServiceInstance();
-        if(potential == null) {
-            potential =  new RuntimeGeneratedMappingServiceImpl(ClassPool.getDefault(),classLoading);
-            bundleContext.registerService(SchemaContextListener.class, (SchemaContextListener) potential, new Hashtable<String,String>());
+        RuntimeGeneratedMappingServiceProxy potential = tryToReuseGlobalInstance();
+        if(potential != null) {
+            return potential;
         }
-        return potential;
-    }
 
-    private GeneratedClassLoadingStrategy getGlobalClassLoadingStrategy() {
-        ServiceReference<GeneratedClassLoadingStrategy> ref = bundleContext.getServiceReference(GeneratedClassLoadingStrategy.class);
-        return bundleContext.getService(ref);
+        final RuntimeGeneratedMappingServiceImpl service = new RuntimeGeneratedMappingServiceImpl(SingletonHolder.CLASS_POOL);
+        bundleContext.registerService(SchemaContextListener.class, service, new Hashtable<String,String>());
+        return service;
     }
 
-    private BindingIndependentMappingService tryToReuseGlobalMappingServiceInstance() {
+    private RuntimeGeneratedMappingServiceProxy tryToReuseGlobalInstance() {
         ServiceReference<BindingIndependentMappingService> serviceRef = getBundleContext().getServiceReference(BindingIndependentMappingService.class);
         if(serviceRef == null) {
             return null;
         }
-        return bundleContext.getService(serviceRef);
 
+        BindingIndependentMappingService delegate = bundleContext.getService(serviceRef);
+        if (delegate == null) {
+            return null;
+        }
+        return new RuntimeGeneratedMappingServiceProxy(getBundleContext(),serviceRef,delegate);
     }
 
     private BundleContext getBundleContext() {
         return bundleContext;
     }
 
-    public void setBundleContext(final BundleContext bundleContext) {
+    public void setBundleContext(BundleContext bundleContext) {
         this.bundleContext = bundleContext;
     }
 
@@ -118,9 +108,9 @@ public final class RuntimeMappingModule extends
         private ServiceReference<BindingIndependentMappingService> reference;
         private BundleContext bundleContext;
 
-        public RuntimeGeneratedMappingServiceProxy(final BundleContext bundleContext,
-                final ServiceReference<BindingIndependentMappingService> serviceRef,
-                final BindingIndependentMappingService delegate) {
+        public RuntimeGeneratedMappingServiceProxy(BundleContext bundleContext,
+                ServiceReference<BindingIndependentMappingService> serviceRef,
+                BindingIndependentMappingService delegate) {
             this.bundleContext = Preconditions.checkNotNull(bundleContext);
             this.reference = Preconditions.checkNotNull(serviceRef);
             this.delegate = Preconditions.checkNotNull(delegate);
@@ -132,47 +122,47 @@ public final class RuntimeMappingModule extends
         }
 
         @Override
-        public CompositeNode toDataDom(final DataObject data) {
+        public CompositeNode toDataDom(DataObject data) {
             return delegate.toDataDom(data);
         }
 
         @Override
         public Entry<YangInstanceIdentifier, CompositeNode> toDataDom(
-                final Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> entry) {
+                Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> entry) {
             return delegate.toDataDom(entry);
         }
 
         @Override
         public YangInstanceIdentifier toDataDom(
-                final org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> path) {
+                org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> path) {
             return delegate.toDataDom(path);
         }
 
         @Override
         public DataObject dataObjectFromDataDom(
-                final org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> path,
-                final CompositeNode result) throws DeserializationException {
+                org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> path,
+                CompositeNode result) throws DeserializationException {
             return delegate.dataObjectFromDataDom(path, result);
         }
 
         @Override
-        public org.opendaylight.yangtools.yang.binding.InstanceIdentifier<?> fromDataDom(final YangInstanceIdentifier entry)
+        public org.opendaylight.yangtools.yang.binding.InstanceIdentifier<?> fromDataDom(YangInstanceIdentifier entry)
                 throws DeserializationException {
             return delegate.fromDataDom(entry);
         }
 
         @Override
-        public Set<QName> getRpcQNamesFor(final Class<? extends RpcService> service) {
+        public Set<QName> getRpcQNamesFor(Class<? extends RpcService> service) {
             return delegate.getRpcQNamesFor(service);
         }
 
         @Override
-        public Optional<Class<? extends RpcService>> getRpcServiceClassFor(final String namespace, final String revision) {
+        public Optional<Class<? extends RpcService>> getRpcServiceClassFor(String namespace, String revision) {
             return delegate.getRpcServiceClassFor(namespace,revision);
         }
 
         @Override
-        public DataContainer dataObjectFromDataDom(final Class<? extends DataContainer> inputClass, final CompositeNode domInput) {
+        public DataContainer dataObjectFromDataDom(Class<? extends DataContainer> inputClass, CompositeNode domInput) {
             return delegate.dataObjectFromDataDom(inputClass, domInput);
         }
 
index f843b23f9b2cc9d15a55c2d9a4373cde3baffecc..e632e6336aaf959808a28f9ecc209432c504b4eb 100644 (file)
@@ -9,6 +9,7 @@ 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;
@@ -18,6 +19,7 @@ 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;
@@ -35,28 +37,33 @@ 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.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
 import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBroker>, DomForwardedBroker,
-        SchemaContextListener, AutoCloseable {
+public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBroker>, DomForwardedBroker, SchemaContextListener, AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(AbstractForwardedDataBroker.class);
     // The Broker to whom we do all forwarding
     private final DOMDataBroker domDataBroker;
 
+    // Mapper to convert from Binding Independent objects to Binding Aware
+    // objects
+    private final BindingIndependentMappingService mappingService;
+
     private final BindingToNormalizedNodeCodec codec;
     private BindingIndependentConnector connector;
     private ProviderSession context;
     private final ListenerRegistration<SchemaContextListener> schemaListenerRegistration;
 
-    protected AbstractForwardedDataBroker(final DOMDataBroker domDataBroker, final BindingToNormalizedNodeCodec codec,
-            final SchemaService schemaService) {
+    protected AbstractForwardedDataBroker(final DOMDataBroker domDataBroker,
+            final BindingIndependentMappingService mappingService,final SchemaService schemaService) {
         this.domDataBroker = domDataBroker;
-        this.codec = codec;
+        this.mappingService = mappingService;
+        this.codec = new BindingToNormalizedNodeCodec(mappingService);
         this.schemaListenerRegistration = schemaService.registerSchemaContextListener(this);
     }
 
@@ -64,6 +71,10 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         return codec;
     }
 
+    protected BindingIndependentMappingService getMappingService() {
+        return mappingService;
+    }
+
     @Override
     public DOMDataBroker getDelegate() {
         return domDataBroker;
@@ -71,11 +82,12 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
 
     @Override
     public void onGlobalContextUpdated(final SchemaContext ctx) {
-        // NOOP
+        codec.onGlobalContextUpdated(ctx);
     }
 
     public ListenerRegistration<DataChangeListener> registerDataChangeListener(final LogicalDatastoreType store,
-            final InstanceIdentifier<?> path, final DataChangeListener listener, final DataChangeScope triggeringScope) {
+            final InstanceIdentifier<?> path, final DataChangeListener listener,
+            final DataChangeScope triggeringScope) {
         DOMDataChangeListener domDataChangeListener = new TranslatingDataChangeInvoker(store, path, listener,
                 triggeringScope);
         YangInstanceIdentifier domPath = codec.toNormalized(path);
@@ -84,16 +96,23 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         return new ListenerRegistrationImpl(listener, domRegistration);
     }
 
-    protected Map<InstanceIdentifier<?>, DataObject> toBinding(final InstanceIdentifier<?> path,
+    protected Map<InstanceIdentifier<?>, DataObject> toBinding(
+            InstanceIdentifier<?> path,
             final Map<YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized) {
         Map<InstanceIdentifier<?>, DataObject> newMap = new HashMap<>();
 
         for (Map.Entry<YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> entry : sortedEntries(normalized)) {
             try {
-                Optional<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> potential = getCodec().toBinding(entry);
+                Optional<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> potential = getCodec().toBinding(
+                        entry);
                 if (potential.isPresent()) {
                     Entry<InstanceIdentifier<? extends DataObject>, DataObject> binding = potential.get();
                     newMap.put(binding.getKey(), binding.getValue());
+                } else if (entry.getKey().getLastPathArgument() instanceof YangInstanceIdentifier.AugmentationIdentifier) {
+                    DataObject bindingDataObject = getCodec().toBinding(path, entry.getValue());
+                    if (bindingDataObject != null) {
+                        newMap.put(path, bindingDataObject);
+                    }
                 }
             } catch (DeserializationException e) {
                 LOG.warn("Failed to transform {}, omitting it", entry, e);
@@ -104,7 +123,8 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
 
     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) {
+        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();
 
@@ -124,7 +144,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         }
     };
 
-    private static <T> Iterable<Entry<YangInstanceIdentifier, T>> sortedEntries(final Map<YangInstanceIdentifier, T> map) {
+    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);
@@ -134,7 +154,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         }
     }
 
-    protected Set<InstanceIdentifier<?>> toBinding(final InstanceIdentifier<?> path,
+    protected Set<InstanceIdentifier<?>> toBinding(InstanceIdentifier<?> path,
             final Set<YangInstanceIdentifier> normalized) {
         Set<InstanceIdentifier<?>> hashSet = new HashSet<>();
         for (YangInstanceIdentifier normalizedPath : normalized) {
@@ -157,7 +177,12 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         if (path.isWildcarded()) {
             return Optional.absent();
         }
-        return (Optional) getCodec().deserializeFunction(path).apply(Optional.<NormalizedNode<?, ?>> of(data));
+
+        try {
+            return Optional.fromNullable(getCodec().toBinding(path, data));
+        } catch (DeserializationException e) {
+            return Optional.absent();
+        }
     }
 
     private class TranslatingDataChangeInvoker implements DOMDataChangeListener {
@@ -175,7 +200,8 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         }
 
         @Override
-        public void onDataChanged(final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
+        public void onDataChanged(
+                final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
             bindingDataChangeListener.onDataChanged(new TranslatedDataChangeEvent(change, path));
         }
     }
@@ -235,7 +261,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         @Override
         public DataObject getOriginalSubtree() {
             if (originalDataCache == null) {
-                if (domEvent.getOriginalSubtree() != null) {
+                if(domEvent.getOriginalSubtree() != null) {
                     originalDataCache = toBindingData(path, domEvent.getOriginalSubtree());
                 } else {
                     originalDataCache = Optional.absent();
@@ -247,7 +273,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         @Override
         public DataObject getUpdatedSubtree() {
             if (updatedDataCache == null) {
-                if (domEvent.getUpdatedSubtree() != null) {
+                if(domEvent.getUpdatedSubtree() != null) {
                     updatedDataCache = toBindingData(path, domEvent.getUpdatedSubtree());
                 } else {
                     updatedDataCache = Optional.absent();
index 1e2d2b17f0b1846ab9272f6683f2a0f00cd1c070..66caaea7083af18f1ffaedc3113f4e35d167b4ff 100644 (file)
  */
 package org.opendaylight.controller.md.sal.binding.impl;
 
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
+import java.lang.reflect.Method;
 import java.util.AbstractMap.SimpleEntry;
+import java.util.Collection;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.annotation.Nullable;
+
 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;
-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.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+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.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+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.PathArgument;
+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.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
 import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class BindingToNormalizedNodeCodec implements SchemaContextListener,AutoCloseable {
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+public class BindingToNormalizedNodeCodec implements SchemaContextListener {
 
     private static final Logger LOG = LoggerFactory.getLogger(BindingToNormalizedNodeCodec.class);
 
     private final BindingIndependentMappingService bindingToLegacy;
-    private final BindingNormalizedNodeCodecRegistry codecRegistry;
     private DataNormalizer legacyToNormalized;
-    private final GeneratedClassLoadingStrategy classLoadingStrategy;
 
-    public BindingToNormalizedNodeCodec(final GeneratedClassLoadingStrategy classLoadingStrategy, final BindingIndependentMappingService mappingService, final BindingNormalizedNodeCodecRegistry codecRegistry) {
+    public BindingToNormalizedNodeCodec(final BindingIndependentMappingService mappingService) {
         super();
         this.bindingToLegacy = mappingService;
-        this.classLoadingStrategy = classLoadingStrategy;
-        this.codecRegistry = codecRegistry;
-
     }
 
     public org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier toNormalized(
             final InstanceIdentifier<? extends DataObject> binding) {
-        return codecRegistry.toYangInstanceIdentifier(binding);
+
+        // Used instance-identifier codec do not support serialization of last
+        // path
+        // argument if it is Augmentation (behaviour expected by old datastore)
+        // in this case, we explicitly check if last argument is augmentation
+        // to process it separately
+        if (isAugmentationIdentifier(binding)) {
+            return toNormalizedAugmented(binding);
+        }
+        return toNormalizedImpl(binding);
     }
 
-    @SuppressWarnings({ "unchecked", "rawtypes" })
     public Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
             final InstanceIdentifier<? extends DataObject> bindingPath, final DataObject bindingObject) {
-        return codecRegistry.toNormalizedNode((InstanceIdentifier) bindingPath, bindingObject);
+        return toNormalizedNode(toBindingEntry(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) {
-        return toNormalizedNode(binding.getKey(),binding.getValue());
+        Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> legacyEntry = bindingToLegacy
+                .toDataDom(binding);
+        Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedEntry = legacyToNormalized
+                .toNormalized(legacyEntry);
+        LOG.trace("Serialization of {}, Legacy Representation: {}, Normalized Representation: {}", binding,
+                legacyEntry, normalizedEntry);
+        if (isAugmentation(binding.getKey().getTargetType())) {
+
+            for (DataContainerChild<? extends PathArgument, ?> child : ((DataContainerNode<?>) normalizedEntry
+                    .getValue()).getValue()) {
+                if (child instanceof AugmentationNode) {
+                    ImmutableList<PathArgument> childArgs = ImmutableList.<PathArgument> builder()
+                            .addAll(normalizedEntry.getKey().getPathArguments()).add(child.getIdentifier()).build();
+                    org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier childPath = org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier
+                            .create(childArgs);
+                    return toDOMEntry(childPath, child);
+                }
+            }
+
+        }
+        return normalizedEntry;
+
     }
 
     /**
@@ -75,13 +125,109 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener,AutoC
     public Optional<InstanceIdentifier<? extends DataObject>> toBinding(
             final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
                     throws DeserializationException {
+
+        PathArgument lastArgument = Iterables.getLast(normalized.getPathArguments());
+        // Used instance-identifier codec do not support serialization of last
+        // path
+        // argument if it is AugmentationIdentifier (behaviour expected by old
+        // datastore)
+        // in this case, we explicitly check if last argument is augmentation
+        // to process it separately
+        if (lastArgument instanceof AugmentationIdentifier) {
+            return toBindingAugmented(normalized);
+        }
+        return toBindingImpl(normalized);
+    }
+
+    private Optional<InstanceIdentifier<? extends DataObject>> toBindingAugmented(
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
+                    throws DeserializationException {
+        Optional<InstanceIdentifier<? extends DataObject>> potential = toBindingImpl(normalized);
+        // Shorthand check, if codec already supports deserialization
+        // of AugmentationIdentifier we will return
+        if (potential.isPresent() && isAugmentationIdentifier(potential.get())) {
+            return potential;
+        }
+
+        int normalizedCount = getAugmentationCount(normalized);
+        AugmentationIdentifier lastArgument = (AugmentationIdentifier) Iterables.getLast(normalized.getPathArguments());
+
+        // Here we employ small trick - Binding-aware Codec injects an pointer
+        // to augmentation class
+        // if child is referenced - so we will reference child and then shorten
+        // path.
+        LOG.trace("Looking for candidates to match {}", normalized);
+        for (QName child : lastArgument.getPossibleChildNames()) {
+            org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier childPath = normalized.node(child);
+            try {
+                if (isNotRepresentable(childPath)) {
+                    LOG.trace("Path {} is not BI-representable, skipping it", childPath);
+                    continue;
+                }
+            } catch (DataNormalizationException e) {
+                LOG.warn("Failed to denormalize path {}, skipping it", childPath, e);
+                continue;
+            }
+
+            Optional<InstanceIdentifier<? extends DataObject>> baId = toBindingImpl(childPath);
+            if (!baId.isPresent()) {
+                LOG.debug("No binding-aware identifier found for path {}, skipping it", childPath);
+                continue;
+            }
+
+            InstanceIdentifier<? extends DataObject> potentialPath = shortenToLastAugment(baId.get());
+            int potentialAugmentCount = getAugmentationCount(potentialPath);
+            if (potentialAugmentCount == normalizedCount) {
+                LOG.trace("Found matching path {}", potentialPath);
+                return Optional.<InstanceIdentifier<? extends DataObject>> of(potentialPath);
+            }
+
+            LOG.trace("Skipping mis-matched potential path {}", potentialPath);
+        }
+
+        LOG.trace("Failed to find augmentation matching {}", normalized);
+        return Optional.absent();
+    }
+
+    private Optional<InstanceIdentifier<? extends DataObject>> toBindingImpl(
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
+                    throws DeserializationException {
+        org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier legacyPath;
+
         try {
-            return  Optional.<InstanceIdentifier<? extends DataObject>>of(codecRegistry.fromYangInstanceIdentifier(normalized));
-        } catch (IllegalArgumentException e) {
-            return Optional.absent();
+            if (isNotRepresentable(normalized)) {
+                return Optional.absent();
+            }
+            legacyPath = legacyToNormalized.toLegacy(normalized);
+        } catch (DataNormalizationException e) {
+            throw new IllegalStateException("Could not denormalize path.", e);
+        }
+        LOG.trace("InstanceIdentifier Path Deserialization: Legacy representation {}, Normalized representation: {}",
+                legacyPath, normalized);
+        return Optional.<InstanceIdentifier<? extends DataObject>> of(bindingToLegacy.fromDataDom(legacyPath));
+    }
+
+    private boolean isNotRepresentable(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
+            throws DataNormalizationException {
+        DataNormalizationOperation<?> op = findNormalizationOperation(normalized);
+        if (op.isMixin() && op.getIdentifier() instanceof NodeIdentifier) {
+            return true;
+        }
+        if (op.isLeaf()) {
+            return true;
         }
+        return false;
     }
 
+    private DataNormalizationOperation<?> findNormalizationOperation(
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
+                    throws DataNormalizationException {
+        DataNormalizationOperation<?> current = legacyToNormalized.getRootOperation();
+        for (PathArgument arg : normalized.getPathArguments()) {
+            current = current.getChild(arg);
+        }
+        return current;
+    }
 
     private static final Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> toBindingEntry(
             final org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> key,
@@ -90,19 +236,45 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener,AutoC
                 key, value);
     }
 
+    private static final Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>> toDOMEntry(
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier key, final NormalizedNode<?, ?> value) {
+        return new SimpleEntry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>>(key,
+                value);
+    }
+
+    public DataObject toBinding(final InstanceIdentifier<?> path, final NormalizedNode<?, ?> normalizedNode)
+            throws DeserializationException {
+        CompositeNode legacy = null;
+        if (isAugmentationIdentifier(path) && normalizedNode instanceof AugmentationNode) {
+            QName augIdentifier = BindingReflections.findQName(path.getTargetType());
+            ContainerNode virtualNode = Builders.containerBuilder() //
+                    .withNodeIdentifier(new NodeIdentifier(augIdentifier)) //
+                    .withChild((DataContainerChild<?, ?>) normalizedNode) //
+                    .build();
+            legacy = (CompositeNode) DataNormalizer.toLegacy(virtualNode);
+        } else {
+            legacy = (CompositeNode) DataNormalizer.toLegacy(normalizedNode);
+        }
+
+        return bindingToLegacy.dataObjectFromDataDom(path, legacy);
+    }
+
     public DataNormalizer getDataNormalizer() {
         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)
                     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);
-        } catch (IllegalArgumentException e) {
+        Optional<InstanceIdentifier<? extends DataObject>> potentialPath = toBinding(normalized.getKey());
+        if (potentialPath.isPresent()) {
+            InstanceIdentifier<? extends DataObject> bindingPath = potentialPath.get();
+            DataObject bindingData = toBinding(bindingPath, normalized.getValue());
+            if (bindingData == null) {
+                LOG.warn("Failed to deserialize {} to Binding format. Binding path is: {}", normalized, bindingPath);
+            }
+            return Optional.of(toBindingEntry(bindingPath, bindingData));
+        } else {
             return Optional.absent();
         }
     }
@@ -110,11 +282,269 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener,AutoC
     @Override
     public void onGlobalContextUpdated(final SchemaContext arg0) {
         legacyToNormalized = new DataNormalizer(arg0);
-        codecRegistry.onBindingRuntimeContextUpdated(BindingRuntimeContext.create(classLoadingStrategy, arg0));
     }
 
+    private org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier toNormalizedAugmented(
+            final InstanceIdentifier<?> augPath) {
+        org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier processed = toNormalizedImpl(augPath);
+        // If used instance identifier codec added supports for deserialization
+        // of last AugmentationIdentifier we will just reuse it
+        if (isAugmentationIdentifier(processed)) {
+            return processed;
+        }
+        Optional<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier> additionalSerialized;
+        additionalSerialized = toNormalizedAugmentedUsingChildContainers(augPath, processed);
+
+        if (additionalSerialized.isPresent()) {
+            return additionalSerialized.get();
+        }
+        additionalSerialized = toNormalizedAugmentedUsingChildLeafs(augPath, processed);
+        if (additionalSerialized.isPresent()) {
+            return additionalSerialized.get();
+        }
+        throw new IllegalStateException("Unabled to construct augmentation identfier for " + augPath);
+    }
+
+    /**
+     * Tries to find correct augmentation identifier using children leafs
+     *
+     * This method uses normalized Instance Identifier of parent node to fetch
+     * schema and {@link BindingReflections#getModuleInfo(Class)} to learn about
+     * augmentation namespace, specificly, in which module it was defined.
+     *
+     * Then it uses it to filter all available augmentations for parent by
+     * module. After that it walks augmentations in particular module and
+     * pick-up first which at least one leaf name matches supplied augmentation.
+     * We could do this safely since YANG explicitly states that no any existing
+     * augmentations must differ in leaf fully qualified names.
+     *
+     *
+     * @param augPath
+     *            Binding Aware Path which ends with augment
+     * @param parentPath
+     *            Processed path
+     * @return
+     */
+    private Optional<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier> toNormalizedAugmentedUsingChildLeafs(
+            final InstanceIdentifier<?> augPath,
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier parentPath) {
+        try {
+            DataNormalizationOperation<?> parentOp = legacyToNormalized.getOperation(parentPath);
+            if(!parentOp.getDataSchemaNode().isPresent()) {
+                return Optional.absent();
+            }
+            DataSchemaNode parentSchema = parentOp.getDataSchemaNode().get();
+            if (parentSchema instanceof AugmentationTarget) {
+                Set<AugmentationSchema> augmentations = ((AugmentationTarget) parentSchema).getAvailableAugmentations();
+                LOG.info("Augmentations for {}, {}", augPath, augmentations);
+                Optional<AugmentationSchema> schema = findAugmentation(augPath.getTargetType(), augmentations);
+                if (schema.isPresent()) {
+                    AugmentationIdentifier augmentationIdentifier = DataNormalizationOperation
+                            .augmentationIdentifierFrom(schema.get());
+                    return Optional.of(parentPath.node(augmentationIdentifier));
+                }
+            }
+        } catch (DataNormalizationException e) {
+            throw new IllegalArgumentException(e);
+        }
+        return Optional.absent();
+    }
+
+    /**
+     * Creates instance identifier for augmentation child, tries to serialize it
+     * Instance Identifier is then shortened to last augmentation.
+     *
+     * This is for situations, where underlying codec is implementing hydrogen
+     * style DOM APIs (which did not supported {@link AugmentationIdentifier}.)
+     *
+     * @param augPath
+     * @param parentPath
+     *            Path to parent node
+     * @return
+     */
+    @SuppressWarnings("rawtypes")
+    private Optional<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier> toNormalizedAugmentedUsingChildContainers(
+            final InstanceIdentifier<?> augPath,
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier parentPath) {
+        for (Class augChild : BindingReflections.getChildrenClasses(augPath.getTargetType())) {
+            @SuppressWarnings("unchecked")
+            InstanceIdentifier<?> childPath = augPath.child(augChild);
+            org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized = toNormalizedImpl(childPath);
+            org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier potentialDiscovered = shortenToLastAugmentation(
+                    normalized, parentPath);
+            if (potentialDiscovered != null) {
+                return Optional.of(potentialDiscovered);
+            }
+        }
+        return Optional.absent();
+    }
+
+    private Optional<AugmentationSchema> findAugmentation(final Class<?> targetType,
+            final Set<AugmentationSchema> augmentations) {
+        YangModuleInfo moduleInfo;
+        try {
+            moduleInfo = BindingReflections.getModuleInfo(targetType);
+        } catch (Exception e) {
+            throw new IllegalStateException(e);
+        }
+        Iterable<AugmentationSchema> filtered = filteredByModuleInfo(augmentations,
+                BindingReflections.getModuleQName(moduleInfo).getModule());
+        filtered.toString();
+        Set<String> targetTypeGetters = getYangModeledGetters(targetType);
+        for (AugmentationSchema schema : filtered) {
+            for (DataSchemaNode child : schema.getChildNodes()) {
+                String getterName = "get" + BindingMapping.getClassName(child.getQName());
+                if (targetTypeGetters.contains(getterName)) {
+                    return Optional.of(schema);
+                }
+            }
+        }
+        return Optional.absent();
+    }
+
+    private static Iterable<AugmentationSchema> filteredByModuleInfo(final Iterable<AugmentationSchema> augmentations,
+            final QNameModule module) {
+        return Iterables.filter(augmentations, new Predicate<AugmentationSchema>() {
+            @Override
+            public boolean apply(final AugmentationSchema schema) {
+                final Collection<DataSchemaNode> childNodes = schema.getChildNodes();
+                return !childNodes.isEmpty() && module.equals(Iterables.get(childNodes, 0).getQName().getModule());
+            }
+        });
+    }
+
+    public static final Set<String> getYangModeledGetters(final Class<?> targetType) {
+        HashSet<String> ret = new HashSet<String>();
+        for (Method method : targetType.getMethods()) {
+            if (isYangModeledGetter(method)) {
+                ret.add(method.getName());
+            }
+        }
+        return ret;
+    }
+
+    /**
+     *
+     * Returns true if supplied method represent getter for YANG modeled value
+     *
+     * @param method
+     *            Method to be tested
+     * @return true if method represent getter for YANG Modeled value.
+     */
+    private static final boolean isYangModeledGetter(final Method method) {
+        return !method.getName().equals("getClass") && !method.getName().equals("getImplementedInterface")
+                && method.getName().startsWith("get") && method.getParameterTypes().length == 0;
+    }
+
+    private org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier shortenToLastAugmentation(
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized,
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier parentPath) {
+        int parentSize = Iterables.size(parentPath.getPathArguments());
+        int position = 0;
+        int foundPosition = -1;
+        for (PathArgument arg : normalized.getPathArguments()) {
+            position++;
+            if (arg instanceof AugmentationIdentifier) {
+                foundPosition = position;
+            }
+        }
+        if (foundPosition > 0 && foundPosition > parentSize) {
+            Iterable<PathArgument> shortened = Iterables.limit(normalized.getPathArguments(), foundPosition);
+            return org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.create(shortened);
+        }
+        return null;
+    }
+
+    private InstanceIdentifier<? extends DataObject> shortenToLastAugment(
+            final InstanceIdentifier<? extends DataObject> binding) {
+        int position = 0;
+        int foundPosition = -1;
+        for (org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument arg : binding.getPathArguments()) {
+            position++;
+            if (isAugmentation(arg.getType())) {
+                foundPosition = position;
+            }
+        }
+        return InstanceIdentifier.create(Iterables.limit(binding.getPathArguments(), foundPosition));
+    }
+
+    private org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier toNormalizedImpl(
+            final InstanceIdentifier<? extends DataObject> binding) {
+        final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier legacyPath = bindingToLegacy
+                .toDataDom(binding);
+        final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized = legacyToNormalized
+                .toNormalized(legacyPath);
+        return normalized;
+    }
+
+    private static boolean isAugmentation(final Class<? extends DataObject> type) {
+        return Augmentation.class.isAssignableFrom(type);
+    }
+
+    private static boolean isAugmentationIdentifier(final InstanceIdentifier<?> potential) {
+        return Augmentation.class.isAssignableFrom(potential.getTargetType());
+    }
+
+    private boolean isAugmentationIdentifier(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier processed) {
+        return Iterables.getLast(processed.getPathArguments()) instanceof AugmentationIdentifier;
+    }
+
+    private static int getAugmentationCount(final InstanceIdentifier<?> potential) {
+        int count = 0;
+        for (org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument arg : potential.getPathArguments()) {
+            if (isAugmentation(arg.getType())) {
+                count++;
+            }
+
+        }
+        return count;
+    }
+
+    private static int getAugmentationCount(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier potential) {
+        int count = 0;
+        for (PathArgument arg : potential.getPathArguments()) {
+            if (arg instanceof AugmentationIdentifier) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
     public <T extends DataObject> Function<Optional<NormalizedNode<?, ?>>, Optional<T>>  deserializeFunction(final InstanceIdentifier<T> path) {
-        return codecRegistry.deserializeFunction(path);
+        return new DeserializeFunction(this, path);
+    }
+
+    private static class DeserializeFunction<T extends DataObject> implements Function<Optional<NormalizedNode<?, ?>>, Optional<T>> {
+
+        private final BindingToNormalizedNodeCodec codec;
+        private final InstanceIdentifier<?> path;
+
+        public DeserializeFunction(final BindingToNormalizedNodeCodec codec, final InstanceIdentifier<?> path) {
+            super();
+            this.codec = Preconditions.checkNotNull(codec, "Codec must not be null");
+            this.path = Preconditions.checkNotNull(path, "Path must not be null");
+        }
+
+        @SuppressWarnings("rawtypes")
+        @Nullable
+        @Override
+        public Optional apply(@Nullable final Optional<NormalizedNode<?, ?>> normalizedNode) {
+            if (normalizedNode.isPresent()) {
+                final DataObject dataObject;
+                try {
+                    dataObject = codec.toBinding(path, normalizedNode.get());
+                } catch (DeserializationException e) {
+                    LOG.warn("Failed to create dataobject from node {}", normalizedNode.get(), e);
+                    throw new IllegalStateException("Failed to create dataobject", e);
+                }
+
+                if (dataObject != null) {
+                    return Optional.of(dataObject);
+                }
+            }
+            return Optional.absent();
+        }
     }
 
     /**
@@ -136,13 +566,4 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener,AutoC
         }
         return currentOp.createDefault(path.getLastPathArgument());
     }
-
-    public BindingIndependentMappingService getLegacy() {
-        return bindingToLegacy;
-    }
-
-    @Override
-    public void close() throws Exception {
-        // NOOP Intentionally
-    }
 }
index 52e114b0ea969436bd4ea2928babf0df7e5f9b96..237d9678f95f3a743dfbe19a033ca02845b81375 100644 (file)
@@ -7,12 +7,6 @@
  */
 package org.opendaylight.controller.md.sal.binding.impl;
 
-import com.google.common.base.Function;
-import com.google.common.util.concurrent.AsyncFunction;
-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 java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -23,6 +17,7 @@ import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutionException;
+
 import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
@@ -49,9 +44,17 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.AsyncFunction;
+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;
+
 @SuppressWarnings("deprecation")
 public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDataBroker implements DataProviderService, AutoCloseable {
 
@@ -61,7 +64,7 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat
     private final ListeningExecutorService executorService;
 
     public ForwardedBackwardsCompatibleDataBroker(final DOMDataBroker domDataBroker,
-            final BindingToNormalizedNodeCodec mappingService, final SchemaService schemaService,final ListeningExecutorService executor) {
+            final BindingIndependentMappingService mappingService, final SchemaService schemaService,final ListeningExecutorService executor) {
         super(domDataBroker, mappingService,schemaService);
         executorService = executor;
         LOG.info("ForwardedBackwardsCompatibleBroker started.");
index ef66d80ed445b1e323dc5c2ad770236e42eb64a8..6359b60684ef45e18d2185d1231b14b165497724 100644 (file)
@@ -16,6 +16,7 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
 
 /**
  * The DataBrokerImpl simply defers to the DOMDataBroker for all its operations.
@@ -29,8 +30,8 @@ import org.opendaylight.controller.sal.core.api.model.SchemaService;
  */
 public class ForwardedBindingDataBroker extends AbstractForwardedDataBroker implements DataBroker {
 
-    public ForwardedBindingDataBroker(final DOMDataBroker domDataBroker, final BindingToNormalizedNodeCodec codec, final SchemaService schemaService) {
-        super(domDataBroker, codec,schemaService);
+    public ForwardedBindingDataBroker(final DOMDataBroker domDataBroker, final BindingIndependentMappingService mappingService, final SchemaService schemaService) {
+        super(domDataBroker, mappingService,schemaService);
     }
 
     @Override
index f037e679be72fbb037318708c98217325782dd66..1ec4aa2d30bc9da7307891a41050bfc33e55642a 100644 (file)
@@ -7,10 +7,6 @@
  */
 package org.opendaylight.controller.sal.binding.codegen.impl;
 
-import com.google.common.util.concurrent.ForwardingBlockingQueue;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -20,19 +16,24 @@ import java.util.concurrent.RejectedExecutionHandler;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
+
 import javassist.ClassPool;
+
 import org.apache.commons.lang3.StringUtils;
 import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator;
 import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory;
-import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.util.concurrent.ForwardingBlockingQueue;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
 public class SingletonHolder {
     private static final Logger logger = LoggerFactory.getLogger(SingletonHolder.class);
 
     public static final ClassPool CLASS_POOL = ClassPool.getDefault();
-    public static final JavassistUtils JAVASSIST = JavassistUtils.forClassPool(CLASS_POOL);
     public static final org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator RPC_GENERATOR_IMPL = new org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator(
             CLASS_POOL);
     public static final RuntimeCodeGenerator RPC_GENERATOR = RPC_GENERATOR_IMPL;
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RootDataBrokerImpl.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RootDataBrokerImpl.java
new file mode 100644 (file)
index 0000000..a1cae26
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.binding.impl;\r
+\r
+import org.opendaylight.controller.config.yang.md.sal.binding.impl.Data;\r
+import org.opendaylight.controller.config.yang.md.sal.binding.impl.DataBrokerImplRuntimeMXBean;\r
+import org.opendaylight.controller.config.yang.md.sal.binding.impl.DataBrokerImplRuntimeRegistration;\r
+import org.opendaylight.controller.config.yang.md.sal.binding.impl.DataBrokerImplRuntimeRegistrator;\r
+import org.opendaylight.controller.config.yang.md.sal.binding.impl.Transactions;\r
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;\r
+\r
+public class RootDataBrokerImpl extends DataBrokerImpl implements DataBrokerImplRuntimeMXBean {\r
+\r
+    private final Transactions transactions = new Transactions();\r
+    private final Data data = new Data();\r
+    private BindingIndependentConnector bindingIndependentConnector;\r
+    private DataBrokerImplRuntimeRegistration runtimeBeanRegistration;\r
+\r
+    public BindingIndependentConnector getBindingIndependentConnector() {\r
+        return bindingIndependentConnector;\r
+    }\r
+\r
+    public Transactions getTransactions() {\r
+        transactions.setCreated(getCreatedTransactionsCount().get());\r
+        transactions.setSubmitted(getSubmittedTransactionsCount().get());\r
+        transactions.setSuccessful(getFinishedTransactionsCount().get());\r
+        transactions.setFailed(getFailedTransactionsCount().get());\r
+        return transactions;\r
+    }\r
+\r
+    @Override\r
+    public Data getData() {\r
+        data.setTransactions(getTransactions());\r
+        return data;\r
+    }\r
+\r
+    public void setBindingIndependentConnector(BindingIndependentConnector runtimeMapping) {\r
+        this.bindingIndependentConnector = runtimeMapping;\r
+    }\r
+\r
+    public void registerRuntimeBean(DataBrokerImplRuntimeRegistrator rootRegistrator) {\r
+        runtimeBeanRegistration = rootRegistrator.register(this);\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/forward/DomForwardedDataBrokerImpl.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/forward/DomForwardedDataBrokerImpl.java
new file mode 100644 (file)
index 0000000..3d0e4de
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.binding.impl.forward;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.opendaylight.controller.sal.binding.impl.RootDataBrokerImpl;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingDomConnectorDeployer;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+
+public class DomForwardedDataBrokerImpl extends RootDataBrokerImpl implements Provider, DomForwardedBroker {
+
+    private BindingIndependentConnector connector;
+    private ProviderSession domProviderContext;
+
+    public void setConnector(BindingIndependentConnector connector) {
+        this.connector = connector;
+    }
+
+    @Override
+    public void onSessionInitiated(ProviderSession session) {
+        this.setDomProviderContext(session);
+    }
+
+    @Override
+    public Collection<ProviderFunctionality> getProviderFunctionality() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public BindingIndependentConnector getConnector() {
+        return connector;
+    }
+
+    @Override
+    public ProviderSession getDomProviderContext() {
+        return domProviderContext;
+    }
+
+    public void setDomProviderContext(ProviderSession domProviderContext) {
+        this.domProviderContext = domProviderContext;
+    }
+
+    @Override
+    public void startForwarding() {
+        BindingDomConnectorDeployer.startDataForwarding(getConnector(), this, getDomProviderContext());
+    }
+}
index aec27235910633fb34389208e02b550c81a85a43..cee4b1efb3a3107e27fa5325dd6d3f92cc937609 100644 (file)
@@ -18,9 +18,10 @@ module opendaylight-sal-binding-broker-impl {
 
     identity binding-dom-mapping-service {
         base config:service-type;
-        config:java-class "org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec";
+        config:java-class "org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService";
     }
 
+
     identity binding-broker-impl {
         base config:module-type;
         config:provided-service sal:binding-broker-osgi-registry;
@@ -28,6 +29,13 @@ module opendaylight-sal-binding-broker-impl {
         config:java-name-prefix BindingBrokerImpl;
     }
 
+    identity binding-data-broker {
+        base config:module-type;
+        config:provided-service sal:binding-data-broker;
+        config:provided-service sal:binding-data-consumer-broker;
+        config:java-name-prefix DataBrokerImpl;
+    }
+
     identity binding-data-compatible-broker {
         base config:module-type;
         config:provided-service sal:binding-data-broker;
@@ -123,6 +131,29 @@ module opendaylight-sal-binding-broker-impl {
         }
     }
 
+    augment "/config:modules/config:module/config:configuration" {
+        case binding-data-broker {
+            when "/config:modules/config:module/config:type = 'binding-data-broker'";
+            container dom-broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity dom:dom-broker-osgi-registry;
+                    }
+                }
+            }
+
+            container mapping-service {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity binding-dom-mapping-service;
+                    }
+                }
+            }
+        }
+    }
+
     augment "/config:modules/config:module/config:configuration" {
         case binding-data-compatible-broker {
             when "/config:modules/config:module/config:type = 'binding-data-compatible-broker'";
@@ -147,6 +178,14 @@ module opendaylight-sal-binding-broker-impl {
         }
     }
 
+    augment "/config:modules/config:module/config:state" {
+        case binding-data-broker {
+            when "/config:modules/config:module/config:type = 'binding-data-broker'";
+            container data {
+                uses common:data-state;
+            }
+        }
+    }
     augment "/config:modules/config:module/config:state" {
         case binding-rpc-broker {
             when "/config:modules/config:module/config:type = 'binding-rpc-broker'";
index 815fc452594e837965b1bd7d66a1814cf87bf299..fd0a169694c5836b52fe02bc1207805cd071ffef 100644 (file)
@@ -1,8 +1,8 @@
 package org.opendaylight.controller.md.sal.binding.impl.test;
 
 import static org.junit.Assert.assertTrue;
-
 import javassist.ClassPool;
+
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
 import org.opendaylight.controller.md.sal.binding.test.AbstractSchemaAwareTest;
@@ -11,11 +11,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controll
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey;
-import org.opendaylight.yangtools.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.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
@@ -38,9 +34,7 @@ public class BindingNormalizedCodecTest extends AbstractSchemaAwareTest {
     @Override
     protected void setupWithSchema(final SchemaContext context) {
         mappingService = new RuntimeGeneratedMappingServiceImpl(ClassPool.getDefault());
-        StreamWriterGenerator streamWriter = new StreamWriterGenerator(JavassistUtils.forClassPool(ClassPool.getDefault()));
-        BindingNormalizedNodeCodecRegistry registry = new BindingNormalizedNodeCodecRegistry(streamWriter);
-        codec = new BindingToNormalizedNodeCodec(GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy(), mappingService, registry);
+        codec = new BindingToNormalizedNodeCodec(mappingService);
         mappingService.onGlobalContextUpdated(context);
         codec.onGlobalContextUpdated(context);
     };
index 106fcea0e9f178470c26eab42fe1bf7c36eb4e08..60eec55ca55df3df580318e5608ea08f1a319801 100644 (file)
@@ -7,14 +7,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;
@@ -24,22 +19,20 @@ import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
 import org.opendaylight.controller.sal.binding.test.util.MockSchemaService;
 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.data.impl.codec.BindingIndependentMappingService;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
 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()
@@ -50,13 +43,7 @@ public class DataBrokerTestCustomizer {
 
     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);
+        mappingService = new RuntimeGeneratedMappingServiceImpl(ClassPool.getDefault());
     }
 
     public DOMStore createConfigurationDatastore() {
@@ -82,13 +69,14 @@ public class DataBrokerTestCustomizer {
     }
 
     public DataBroker createDataBroker() {
-        return new ForwardedBindingDataBroker(getDOMDataBroker(), bindingToNormalized, schemaService );
+        return new ForwardedBindingDataBroker(getDOMDataBroker(), getMappingService(), getSchemaService());
     }
 
     public ForwardedBackwardsCompatibleDataBroker createBackwardsCompatibleDataBroker() {
-        return new ForwardedBackwardsCompatibleDataBroker(getDOMDataBroker(), bindingToNormalized, getSchemaService(), MoreExecutors.sameThreadExecutor());
+        return new ForwardedBackwardsCompatibleDataBroker(getDOMDataBroker(), getMappingService(), getSchemaService(), MoreExecutors.sameThreadExecutor());
     }
 
+
     private SchemaService getSchemaService() {
         return schemaService;
     }
index 63e0e2290aadd37e697d6a36d6de3fb779c3ab7f..7b67d3b10f4d2eacd2659eefdd1a72af2ca51482 100644 (file)
@@ -16,6 +16,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
@@ -75,7 +76,7 @@ public class MultipleAugmentationPutsTest extends AbstractDataServiceTest implem
      *
      * @throws Exception
      */
-    @Test()
+    @Test( timeout = 15000)
     public void testAugmentSerialization() throws Exception {
 
         baDataService.registerDataChangeListener(NODES_INSTANCE_ID_BA, this);
@@ -121,7 +122,7 @@ public class MultipleAugmentationPutsTest extends AbstractDataServiceTest implem
         testNodeRemove();
     }
 
-    private <T extends Augmentation<Node>> Node createTestNode(final Class<T> augmentationClass, final T augmentation) {
+    private <T extends Augmentation<Node>> Node createTestNode(Class<T> augmentationClass, T augmentation) {
         NodeBuilder nodeBuilder = new NodeBuilder();
         nodeBuilder.setId(new NodeId(NODE_ID));
         nodeBuilder.setKey(NODE_KEY);
@@ -129,7 +130,7 @@ public class MultipleAugmentationPutsTest extends AbstractDataServiceTest implem
         return nodeBuilder.build();
     }
 
-    private DataModificationTransaction commitNodeAndVerifyTransaction(final Node original) throws Exception {
+    private DataModificationTransaction commitNodeAndVerifyTransaction(Node original) throws Exception {
         DataModificationTransaction transaction = baDataService.beginTransaction();
         transaction.putOperationalData(NODE_INSTANCE_ID_BA, original);
         RpcResult<TransactionStatus> result = transaction.commit().get();
@@ -147,7 +148,7 @@ public class MultipleAugmentationPutsTest extends AbstractDataServiceTest implem
         assertNull(node);
     }
 
-    private AugmentationVerifier<Node> verifyNode(final Nodes nodes, final Node original) {
+    private AugmentationVerifier<Node> verifyNode(Nodes nodes, Node original) {
         assertNotNull(nodes);
         assertNotNull(nodes.getNode());
         assertEquals(1, nodes.getNode().size());
@@ -157,7 +158,7 @@ public class MultipleAugmentationPutsTest extends AbstractDataServiceTest implem
         return new AugmentationVerifier<Node>(readedNode);
     }
 
-    private void assertBindingIndependentVersion(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier nodeId) {
+    private void assertBindingIndependentVersion(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier nodeId) {
         CompositeNode node = biDataService.readOperationalData(nodeId);
         assertNotNull(node);
     }
@@ -170,7 +171,7 @@ public class MultipleAugmentationPutsTest extends AbstractDataServiceTest implem
         return nodeMeterStatistics(10, false);
     }
 
-    private NodeMeterStatistics nodeMeterStatistics(final int count, final boolean setDuration) {
+    private NodeMeterStatistics nodeMeterStatistics(int count, boolean setDuration) {
         NodeMeterStatisticsBuilder nmsb = new NodeMeterStatisticsBuilder();
         MeterStatisticsBuilder meterStats = new MeterStatisticsBuilder();
 
@@ -206,7 +207,7 @@ public class MultipleAugmentationPutsTest extends AbstractDataServiceTest implem
     }
 
     @Override
-    public void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+    public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
         receivedChangeEvent = change;
     }
 
index d0a326adff83054ff99cbc9e0b1278dde8ed6ad4..fef5715f50deea8ac6038b8684dc832c779cf582 100644 (file)
@@ -9,19 +9,12 @@ package org.opendaylight.controller.sal.binding.test.util;
 
 import static com.google.common.base.Preconditions.checkState;
 
-import com.google.common.annotations.Beta;
-import com.google.common.collect.ClassToInstanceMap;
-import com.google.common.collect.ImmutableClassToInstanceMap;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.MutableClassToInstanceMap;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
 import java.util.Set;
 import java.util.concurrent.Future;
+
 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;
@@ -50,14 +43,9 @@ import org.opendaylight.controller.sal.core.spi.data.DOMStore;
 import org.opendaylight.controller.sal.dom.broker.BrokerImpl;
 import org.opendaylight.controller.sal.dom.broker.MountPointManagerImpl;
 import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker;
-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.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
 import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
 import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
-import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -68,6 +56,15 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ClassToInstanceMap;
+import com.google.common.collect.ImmutableClassToInstanceMap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.MutableClassToInstanceMap;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
 @Beta
 public class BindingTestContext implements AutoCloseable {
 
@@ -77,7 +74,6 @@ public class BindingTestContext implements AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(BindingTestContext.class);
 
     private RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
-    private BindingToNormalizedNodeCodec codec;
 
     private DomForwardedBindingBrokerImpl baBrokerImpl;
     private DataBrokerImpl baDataImpl;
@@ -133,7 +129,7 @@ public class BindingTestContext implements AutoCloseable {
     public void startNewDataBroker() {
         checkState(executor != null, "Executor needs to be set");
         checkState(newDOMDataBroker != null, "DOM Data Broker must be set");
-        dataBroker = new ForwardedBindingDataBroker(newDOMDataBroker, codec, mockSchemaService);
+        dataBroker = new ForwardedBindingDataBroker(newDOMDataBroker, mappingServiceImpl, mockSchemaService);
     }
 
     public void startNewDomDataBroker() {
@@ -254,12 +250,6 @@ public class BindingTestContext implements AutoCloseable {
         checkState(classPool != null, "ClassPool needs to be present");
         mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl(classPool);
         mockSchemaService.registerSchemaContextListener(mappingServiceImpl);
-
-        DataObjectSerializerGenerator generator = StreamWriterGenerator.create(JavassistUtils.forClassPool(classPool));
-        BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(generator);
-        GeneratedClassLoadingStrategy loading = GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy();
-        codec = new BindingToNormalizedNodeCodec(loading, mappingServiceImpl, codecRegistry);
-        mockSchemaService.registerSchemaContextListener(codec);
     }
 
     private void updateYangSchema(final ImmutableSet<YangModuleInfo> moduleInfos) {
@@ -290,7 +280,7 @@ public class BindingTestContext implements AutoCloseable {
     }
 
     public void startNewBindingDataBroker() {
-        ForwardedBackwardsCompatibleDataBroker forwarded = new ForwardedBackwardsCompatibleDataBroker(newDOMDataBroker, codec,mockSchemaService, executor);
+        ForwardedBackwardsCompatibleDataBroker forwarded = new ForwardedBackwardsCompatibleDataBroker(newDOMDataBroker, mappingServiceImpl,mockSchemaService, executor);
         baData = forwarded;
     }
 
index 344694381a222850fb23ccac0cc8415b3296f472..83a69969b7b8c8bd0be90111227bda05cd61fd58 100644 (file)
@@ -112,7 +112,6 @@ public class TestHelper {
                 mavenBundle(YANGTOOLS, "binding-generator-api").versionAsInProject(), mavenBundle(YANGTOOLS,
                         "binding-generator-spi").versionAsInProject(), //
                 mavenBundle(YANGTOOLS, "binding-generator-impl").versionAsInProject(),
-                mavenBundle(YANGTOOLS, "binding-data-codec").versionAsInProject(),
                 mavenBundle(YANGTOOLS + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), // //
 
                 mavenBundle(CONTROLLER, "sal-core-api").versionAsInProject().update(), //
index 33039ea2314329e0a132606bff58894e7cb84585..8a390b337e1849ae8cf2c15f7799073ace928ee2 100644 (file)
@@ -11,10 +11,9 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
-import com.google.inject.Inject;
 import java.util.concurrent.Future;
+
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
@@ -23,6 +22,7 @@ import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
@@ -31,6 +31,8 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 
+import com.google.inject.Inject;
+
 public class DataServiceTest extends AbstractTest {
 
     protected DataBrokerService consumerDataService;
@@ -43,20 +45,12 @@ public class DataServiceTest extends AbstractTest {
     public void setUp() throws Exception {
     }
 
-    /*
-     *
-     * Ignored this, because classes here are constructed from
-     * very different class loader as MD-SAL is run into,
-     * this is code is run from different classloader.
-     *
-     */
     @Test
-    @Ignore
     public void test() throws Exception {
         BindingAwareConsumer consumer1 = new BindingAwareConsumer() {
 
             @Override
-            public void onSessionInitialized(final ConsumerContext session) {
+            public void onSessionInitialized(ConsumerContext session) {
                 consumerDataService = session.getSALService(DataBrokerService.class);
             }
         };
@@ -68,12 +62,12 @@ public class DataServiceTest extends AbstractTest {
         DataModificationTransaction transaction = consumerDataService.beginTransaction();
         assertNotNull(transaction);
 
-        InstanceIdentifier<Node> node1 = createNodeRef("0");
-        DataObject  node = consumerDataService.readConfigurationData(node1);
+        NodeRef node1 = createNodeRef("0");
+        DataObject  node = consumerDataService.readConfigurationData(node1.getValue());
         assertNull(node);
         Node nodeData1 = createNode("0");
 
-        transaction.putConfigurationData(node1, nodeData1);
+        transaction.putConfigurationData(node1.getValue(), nodeData1);
         Future<RpcResult<TransactionStatus>> commitResult = transaction.commit();
         assertNotNull(commitResult);
 
@@ -83,7 +77,7 @@ public class DataServiceTest extends AbstractTest {
         assertNotNull(result.getResult());
         assertEquals(TransactionStatus.COMMITED, result.getResult());
 
-        Node readedData = (Node) consumerDataService.readConfigurationData(node1);
+        Node readedData = (Node) consumerDataService.readConfigurationData(node1.getValue());
         assertNotNull(readedData);
         assertEquals(nodeData1.getKey(), readedData.getKey());
 
@@ -91,7 +85,7 @@ public class DataServiceTest extends AbstractTest {
         DataModificationTransaction transaction2 = consumerDataService.beginTransaction();
         assertNotNull(transaction);
 
-        transaction2.removeConfigurationData(node1);
+        transaction2.removeConfigurationData(node1.getValue());
 
         Future<RpcResult<TransactionStatus>> commitResult2 = transaction2.commit();
         assertNotNull(commitResult2);
@@ -102,19 +96,21 @@ public class DataServiceTest extends AbstractTest {
         assertNotNull(result2.getResult());
         assertEquals(TransactionStatus.COMMITED, result2.getResult());
 
-        DataObject readedData2 = consumerDataService.readConfigurationData(node1);
+        DataObject readedData2 = consumerDataService.readConfigurationData(node1.getValue());
         assertNull(readedData2);
 
 
     }
 
 
-    private static InstanceIdentifier<Node> createNodeRef(final String string) {
+    private static NodeRef createNodeRef(String string) {
         NodeKey key = new NodeKey(new NodeId(string));
-        return  InstanceIdentifier.builder(Nodes.class).child(Node.class, key).build();
+        InstanceIdentifier<Node> path = InstanceIdentifier.builder(Nodes.class).child(Node.class, key).build();
+
+        return new NodeRef(path);
     }
 
-    private static Node createNode(final String string) {
+    private static Node createNode(String string) {
         NodeBuilder ret = new NodeBuilder();
         NodeId id = new NodeId(string);
         ret.setKey(new NodeKey(id));
index 5e37f36a2c1d6e16c85696315d5427e1a2f2d9de..63a921d6f309db37a0a438bbadbafdaadb528485 100644 (file)
                 <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
                     <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
                         <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:schema-service-singleton</type>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
+                                prefix:schema-service-singleton
+                            </type>
                             <name>yang-schema-service</name>
                         </module>
                         <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:runtime-generated-mapping</type>
-                            <name>runtime-mapping-singleton</name>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
+                                prefix:hash-map-data-store
+                            </type>
+                            <name>hash-map-data-store</name>
                         </module>
                         <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-notification-broker</type>
-                            <name>binding-notification-broker</name>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
+                                prefix:dom-broker-impl
+                            </type>
+                            <name>dom-broker</name>
+                            <data-store xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
+                                <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
+                                    dom:dom-data-store
+                                </type>
+                                <name>ref_hash-map-data-store</name>
+                            </data-store>
                         </module>
                         <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</type>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                                prefix:binding-broker-impl
+                            </type>
                             <name>binding-broker-impl</name>
-                            <notification-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
-                                <name>binding-notification-broker</name>
+                            <notification-service
+                                    xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+                                    binding:binding-notification-service
+                                </type>
+                                <name>ref_binding-notification-broker</name>
                             </notification-service>
                             <data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
-                                <name>binding-data-broker</name>
+                                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+                                    binding:binding-data-broker
+                                </type>
+                                <name>ref_binding-data-broker</name>
                             </data-broker>
                         </module>
-                        <!--
-                             Tree-based in-memory data store. This is the data store which is currently
-                             recommended for single-node deployments.
-                        -->
-                        <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-inmemory-data-broker</type>
-                            <name>inmemory-data-broker</name>
-                            <schema-service>
-                                <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
-                                <name>yang-schema-service</name>
-                            </schema-service>
-                        </module>
                         <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl</type>
-                            <name>inmemory-dom-broker</name>
-                            <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>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                                prefix:runtime-generated-mapping
+                            </type>
+                            <name>runtime-mapping-singleton</name>
                         </module>
                         <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-data-compatible-broker</type>
-                            <name>inmemory-binding-data-broker</name>
-                            <dom-async-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
-                                <name>dom-broker</name>
-                            </dom-async-broker>
-                            <binding-mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-dom-mapping-service</type>
-                                <name>runtime-mapping-singleton</name>
-                            </binding-mapping-service>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                                prefix:binding-notification-broker
+                            </type>
+                            <name>binding-notification-broker</name>
                         </module>
                         <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-forwarded-data-broker</type>
-                            <name>binding-async-data-broker</name>
-                            <binding-forwarded-data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                <dom-async-broker>
-                                    <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
-                                    <name>dom-broker</name>
-                                </dom-async-broker>
-                                <binding-mapping-service>
-                                    <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-dom-mapping-service</type>
-                                    <name>runtime-mapping-singleton</name>
-                                </binding-mapping-service>
-                            </binding-forwarded-data-broker>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                                prefix:binding-data-broker
+                            </type>
+                            <name>binding-data-broker</name>
+                            <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                                <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
+                                    dom:dom-broker-osgi-registry
+                                </type>
+                                <name>ref_dom-broker</name>
+                            </dom-broker>
+                            <mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                                    binding:binding-dom-mapping-service
+                                </type>
+                                <name>ref_runtime-mapping-singleton</name>
+                            </mapping-service>
                         </module>
                     </modules>
 
                     <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
                         <service>
-                            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+                            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
+                                dom:schema-service
+                            </type>
                             <instance>
-                                <name>yang-schema-service</name>
-                                <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
+                                <name>ref_yang-schema-service</name>
+                                <provider>
+                                    /config/modules/module[name='schema-service-singleton']/instance[name='yang-schema-service']
+                                </provider>
                             </instance>
                         </service>
                         <service>
-                            <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
+                            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+                                binding:binding-notification-service
+                            </type>
                             <instance>
-                                <name>runtime-mapping-singleton</name>
-                                <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
+                                <name>ref_binding-notification-broker</name>
+                                <provider>
+                                    /config/modules/module[name='binding-notification-broker']/instance[name='binding-notification-broker']
+                                </provider>
                             </instance>
                         </service>
                         <service>
-                            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
+                            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
+                                dom:dom-data-store
+                            </type>
                             <instance>
-                                <name>binding-notification-broker</name>
-                                <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
+                                <name>ref_hash-map-data-store</name>
+                                <provider>
+                                    /config/modules/module[name='hash-map-data-store']/instance[name='hash-map-data-store']
+                                </provider>
                             </instance>
                         </service>
+
                         <service>
-                            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+                            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+                                binding:binding-broker-osgi-registry
+                            </type>
                             <instance>
-                                <name>binding-osgi-broker</name>
-                                <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
+                                <name>ref_binding-broker-impl</name>
+                                <provider>
+                                    /config/modules/module[name='binding-broker-impl']/instance[name='binding-broker-impl']
+                                </provider>
                             </instance>
                         </service>
                         <service>
                                 <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
                             </instance>
                         </service>
-
-                        <service>
-                            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
-                            <instance>
-                                <name>dom-broker</name>
-                                <provider>/modules/module[type='dom-broker-impl'][name='inmemory-dom-broker']</provider>
-                            </instance>
-                        </service>
-
                         <service>
-                            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+                            <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                                binding-impl:binding-dom-mapping-service
+                            </type>
                             <instance>
-                                <name>binding-data-broker</name>
-                                <provider>/modules/module[type='binding-data-compatible-broker'][name='inmemory-binding-data-broker']</provider>
+                                <name>ref_runtime-mapping-singleton</name>
+                                <provider>
+                                    /config/modules/module[name='runtime-generated-mapping']/instance[name='runtime-mapping-singleton']
+                                </provider>
                             </instance>
                         </service>
-
                         <service>
-                            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
+                            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
+                                dom:dom-broker-osgi-registry
+                            </type>
                             <instance>
-                                <name>binding-data-broker</name>
-                                <provider>/modules/module[type='binding-forwarded-data-broker'][name='binding-async-data-broker']</provider>
+                                <name>ref_dom-broker</name>
+                                <provider>/config/modules/module[name='dom-broker-impl']/instance[name='dom-broker']
+                                </provider>
                             </instance>
                         </service>
-
                         <service>
-                            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
+                            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+                                binding:binding-data-broker
+                            </type>
                             <instance>
-                                <name>inmemory-data-broker</name>
-                                <provider>/modules/module[type='dom-inmemory-data-broker'][name='inmemory-data-broker']</provider>
+                                <name>ref_binding-data-broker</name>
+                                <provider>
+                                    /config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker']
+                                </provider>
                             </instance>
                         </service>
                     </services>
index a904d6a3ba361788883bebf5ad25ef48199f35d9..4419d19f527c9c096718496041dee08933275106 100644 (file)
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-parser-impl</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>netconf-util</artifactId>
+    </dependency>
 
     <dependency>
       <groupId>xmlunit</groupId>
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.remote.rpc.utils;
+package org.opendaylight.controller.xml.codec;
 
 import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.remote.rpc.utils;
+package org.opendaylight.controller.xml.codec;
 
 import org.opendaylight.yangtools.yang.common.QName;
 
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.remote.rpc.utils;
+package org.opendaylight.controller.xml.codec;
 
 import com.google.common.base.Function;
 import com.google.common.base.Objects;
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.remote.rpc.utils;
+package org.opendaylight.controller.xml.codec;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Preconditions;
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.remote.rpc.utils;
+package org.opendaylight.controller.xml.codec;
 
 import com.google.common.base.Optional;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
index b47222ffa26e65ceb4599f2c2319a9491d2599f6..9c5129d6a4eb932f764a158530e304808dbb375d 100644 (file)
             <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
             <Export-package></Export-package>
             <Private-Package></Private-Package>
-            <Import-Package>!*snappy;!org.jboss.*;*</Import-Package>
+            <Import-Package>!*snappy;!org.jboss.*;!com.jcraft.*;*</Import-Package>
             <Embed-Dependency>
                 sal-clustering-commons;
                 sal-akka-raft;
index ac01f42a7fb017a9e33b330c64e6b5178aa95ff2..b258c4466a7d1939aacaa5c3ac32159539bf2485 100644 (file)
@@ -18,7 +18,7 @@ public abstract class AbstractUntypedActor extends UntypedActor {
         Logging.getLogger(getContext().system(), this);
 
 
-    public AbstractUntypedActor(){
+    public AbstractUntypedActor() {
         LOG.debug("Actor created {}", getSelf());
         getContext().
             system().
@@ -29,16 +29,18 @@ public abstract class AbstractUntypedActor extends UntypedActor {
     @Override public void onReceive(Object message) throws Exception {
         LOG.debug("Received message {}", message.getClass().getSimpleName());
         handleReceive(message);
-        LOG.debug("Done handling message {}", message.getClass().getSimpleName());
+        LOG.debug("Done handling message {}",
+            message.getClass().getSimpleName());
     }
 
     protected abstract void handleReceive(Object message) throws Exception;
 
-    protected void ignoreMessage(Object message){
+    protected void ignoreMessage(Object message) {
         LOG.debug("Unhandled message {} ", message);
     }
 
-    protected void unknownMessage(Object message) throws Exception{
+    protected void unknownMessage(Object message) throws Exception {
+        LOG.debug("Received unhandled message {}", message);
         unhandled(message);
     }
 }
index 40e045f18e31bdfbcf2eb34c9fa0847a778f94f4..4fa26ffb2033407efb5b1fc1c86f96d04e4e3dd7 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.controller.cluster.datastore.shardstrategy.ShardStrategy
 import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreConfigProperties;
 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;
@@ -72,7 +73,8 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener, Au
                                     EXECUTOR_MAX_QUEUE_SIZE_PROP,
                                     DEFAULT_EXECUTOR_MAX_QUEUE_SIZE), "DistDataStore"));
 
-    public DistributedDataStore(ActorSystem actorSystem, String type, ClusterWrapper cluster, Configuration configuration) {
+    public DistributedDataStore(ActorSystem actorSystem, String type, ClusterWrapper cluster,
+            Configuration configuration, InMemoryDOMDataStoreConfigProperties 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");
@@ -84,7 +86,7 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener, Au
         LOG.info("Creating ShardManager : {}", shardManagerId);
 
         this.actorContext = new ActorContext(actorSystem, actorSystem
-            .actorOf(ShardManager.props(type, cluster, configuration),
+            .actorOf(ShardManager.props(type, cluster, configuration, dataStoreProperties),
                 shardManagerId ), cluster, configuration);
     }
 
index 6d87271f00d54fcdbf6ca70c27843248b0bbc1b9..a1a3e87510e78d151b769fd579c2602503ec656c 100644 (file)
@@ -9,19 +9,22 @@
 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){
+    public static DistributedDataStore createInstance(String name, SchemaService schemaService,
+            InMemoryDOMDataStoreConfigProperties dataStoreProperties) {
+
         ActorSystem actorSystem = ActorSystemFactory.getInstance();
         Configuration config = new ConfigurationImpl("module-shards.conf", "modules.conf");
         final DistributedDataStore dataStore =
-            new DistributedDataStore(actorSystem, name, new ClusterWrapperImpl(actorSystem),config );
-       ShardStrategyFactory.setConfiguration(config);
-        schemaService
-            .registerSchemaContextListener(dataStore);
+            new DistributedDataStore(actorSystem, name, new ClusterWrapperImpl(actorSystem),
+                    config, dataStoreProperties );
+        ShardStrategyFactory.setConfiguration(config);
+        schemaService.registerSchemaContextListener(dataStore);
         return dataStore;
-
     }
 }
index 63b26331a510835ae623a9feade7893938d81f84..75f540ade088e6bb45b10e9b92bc4af8789b0218 100644 (file)
@@ -17,6 +17,8 @@ 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;
@@ -41,6 +43,7 @@ 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;
@@ -92,7 +95,8 @@ public class Shard extends RaftActor {
 
     private final List<ActorSelection> dataChangeListeners = new ArrayList<>();
 
-    private Shard(ShardIdentifier name, Map<ShardIdentifier, String> peerAddresses) {
+    private Shard(ShardIdentifier name, Map<ShardIdentifier, String> peerAddresses,
+            InMemoryDOMDataStoreConfigProperties dataStoreProperties) {
         super(name.toString(), mapPeerAddresses(peerAddresses), Optional.of(configParams));
 
         this.name = name;
@@ -103,16 +107,18 @@ public class Shard extends RaftActor {
 
         LOG.info("Shard created : {} persistent : {}", name, persistent);
 
-        store = InMemoryDOMDataStoreFactory.create(name.toString(), null);
+        store = InMemoryDOMDataStoreFactory.create(name.toString(), null, dataStoreProperties);
 
         shardMBean = ShardMBeanFactory.getShardStatsMBean(name.toString());
 
     }
 
-    private static Map<String, String> mapPeerAddresses(Map<ShardIdentifier, String> peerAddresses){
-        Map<String , String> map = new HashMap<>();
+    private static Map<String, String> mapPeerAddresses(
+        Map<ShardIdentifier, String> peerAddresses) {
+        Map<String, String> map = new HashMap<>();
 
-        for(Map.Entry<ShardIdentifier, String> entry : peerAddresses.entrySet()){
+        for (Map.Entry<ShardIdentifier, String> entry : peerAddresses
+            .entrySet()) {
             map.put(entry.getKey().toString(), entry.getValue());
         }
 
@@ -123,15 +129,17 @@ public class Shard extends RaftActor {
 
 
     public static Props props(final ShardIdentifier name,
-        final Map<ShardIdentifier, String> peerAddresses) {
+        final Map<ShardIdentifier, String> peerAddresses,
+        final InMemoryDOMDataStoreConfigProperties dataStoreProperties) {
         Preconditions.checkNotNull(name, "name should not be null");
-        Preconditions.checkNotNull(peerAddresses, "peerAddresses 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);
+                return new Shard(name, peerAddresses, dataStoreProperties);
             }
 
         });
@@ -164,14 +172,16 @@ public class Shard extends RaftActor {
             }
         } else if (message instanceof PeerAddressResolved) {
             PeerAddressResolved resolved = (PeerAddressResolved) message;
-            setPeerAddress(resolved.getPeerId().toString(), resolved.getPeerAddress());
+            setPeerAddress(resolved.getPeerId().toString(),
+                resolved.getPeerAddress());
         } else {
             super.onReceiveCommand(message);
         }
     }
 
     private ActorRef createTypedTransactionActor(
-        CreateTransaction createTransaction, ShardTransactionIdentifier transactionId) {
+        CreateTransaction createTransaction,
+        ShardTransactionIdentifier transactionId) {
         if (createTransaction.getTransactionType()
             == TransactionProxy.TransactionType.READ_ONLY.ordinal()) {
 
@@ -203,24 +213,26 @@ public class Shard extends RaftActor {
                     .props(store.newWriteOnlyTransaction(), getSelf(),
                         schemaContext), transactionId.toString());
         } else {
-            // FIXME: This does not seem right
             throw new IllegalArgumentException(
-                "CreateTransaction message has unidentified transaction type="
+                "Shard="+name + ":CreateTransaction message has unidentified transaction type="
                     + createTransaction.getTransactionType());
         }
     }
 
     private void createTransaction(CreateTransaction createTransaction) {
 
-        ShardTransactionIdentifier transactionId = ShardTransactionIdentifier.builder().remoteTransactionId(createTransaction.getTransactionId()).build();
+        ShardTransactionIdentifier transactionId =
+            ShardTransactionIdentifier.builder()
+                .remoteTransactionId(createTransaction.getTransactionId())
+                .build();
         LOG.debug("Creating transaction : {} ", transactionId);
         ActorRef transactionActor =
             createTypedTransactionActor(createTransaction, transactionId);
 
         getSender()
             .tell(new CreateTransactionReply(
-                Serialization.serializedActorPath(transactionActor),
-                createTransaction.getTransactionId()).toSerializable(),
+                    Serialization.serializedActorPath(transactionActor),
+                    createTransaction.getTransactionId()).toSerializable(),
                 getSelf());
     }
 
@@ -255,22 +267,21 @@ public class Shard extends RaftActor {
 
         final ListenableFuture<Void> future = cohort.commit();
         final ActorRef self = getSelf();
-        future.addListener(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    future.get();
-                        sender
-                            .tell(new CommitTransactionReply().toSerializable(),
-                                self);
-                        shardMBean.incrementCommittedTransactionCount();
-                        shardMBean.setLastCommittedTransactionTime(new Date());
-                } catch (InterruptedException | ExecutionException e) {
-                    shardMBean.incrementFailedTransactionsCount();
-                    sender.tell(new akka.actor.Status.Failure(e),self);
-                }
+
+        Futures.addCallback(future, new FutureCallback<Void>() {
+            public void onSuccess(Void v) {
+               sender.tell(new CommitTransactionReply().toSerializable(),self);
+               shardMBean.incrementCommittedTransactionCount();
+               shardMBean.setLastCommittedTransactionTime(new Date());
             }
-        }, getContext().dispatcher());
+
+            public void onFailure(Throwable t) {
+                LOG.error(t, "An exception happened during commit");
+                shardMBean.incrementFailedTransactionsCount();
+                sender.tell(new akka.actor.Status.Failure(t), self);
+            }
+        });
+
     }
 
     private void handleForwardedCommit(ForwardedCommitTransaction message) {
@@ -329,7 +340,7 @@ public class Shard extends RaftActor {
 
         LOG.debug(
             "registerDataChangeListener sending reply, listenerRegistrationPath = {} "
-                , listenerRegistration.path().toString());
+            , listenerRegistration.path().toString());
 
         getSender()
             .tell(new RegisterChangeListenerReply(listenerRegistration.path()),
@@ -370,7 +381,7 @@ public class Shard extends RaftActor {
         // Update stats
         ReplicatedLogEntry lastLogEntry = getLastLogEntry();
 
-        if(lastLogEntry != null){
+        if (lastLogEntry != null) {
             shardMBean.setLastLogIndex(lastLogEntry.getIndex());
             shardMBean.setLastLogTerm(lastLogEntry.getTerm());
         }
index 6162a0327ca6ab229be75b4f8b8c2c994dcb253a..3396eb556456116005459540c66a78119ca64767 100644 (file)
@@ -30,6 +30,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 scala.concurrent.duration.Duration;
 
 import java.util.ArrayList;
@@ -68,15 +70,19 @@ public class ShardManager extends AbstractUntypedActor {
 
     private ShardManagerInfoMBean mBean;
 
+    private final InMemoryDOMDataStoreConfigProperties dataStoreProperties;
+
     /**
      * @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) {
+    private ShardManager(String type, ClusterWrapper cluster, Configuration configuration,
+            InMemoryDOMDataStoreConfigProperties dataStoreProperties) {
 
         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;
 
         // Subscribe this actor to cluster member events
         cluster.subscribeToMemberEvents(getSelf());
@@ -88,7 +94,8 @@ public class ShardManager extends AbstractUntypedActor {
 
     public static Props props(final String type,
         final ClusterWrapper cluster,
-        final Configuration configuration) {
+        final Configuration configuration,
+        final InMemoryDOMDataStoreConfigProperties dataStoreProperties) {
 
         Preconditions.checkNotNull(type, "type should not be null");
         Preconditions.checkNotNull(cluster, "cluster should not be null");
@@ -98,7 +105,7 @@ public class ShardManager extends AbstractUntypedActor {
 
             @Override
             public ShardManager create() throws Exception {
-                return new ShardManager(type, cluster, configuration);
+                return new ShardManager(type, cluster, configuration, dataStoreProperties);
             }
         });
     }
@@ -243,7 +250,7 @@ public class ShardManager extends AbstractUntypedActor {
             ShardIdentifier shardId = getShardIdentifier(memberName, shardName);
             Map<ShardIdentifier, String> peerAddresses = getPeerAddresses(shardName);
             ActorRef actor = getContext()
-                .actorOf(Shard.props(shardId, peerAddresses),
+                .actorOf(Shard.props(shardId, peerAddresses, dataStoreProperties),
                     shardId.toString());
             localShardActorNames.add(shardId.toString());
             localShards.put(shardName, new ShardInformation(shardName, actor, peerAddresses));
@@ -283,10 +290,12 @@ public class ShardManager extends AbstractUntypedActor {
 
     @Override
     public SupervisorStrategy supervisorStrategy() {
+
         return new OneForOneStrategy(10, Duration.create("1 minute"),
             new Function<Throwable, SupervisorStrategy.Directive>() {
                 @Override
                 public SupervisorStrategy.Directive apply(Throwable t) {
+                    LOG.warning("Supervisor Strategy of resume applied {}",t);
                     return SupervisorStrategy.resume();
                 }
             }
index 500b73ce9de6531c3a1d60df3e192dea18dc4606..25705bff418740c873af8334091b3961612c3f1e 100644 (file)
@@ -14,6 +14,8 @@ 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.messages.AbortTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.AbortTransactionReply;
@@ -26,8 +28,6 @@ import org.opendaylight.controller.cluster.datastore.messages.PreCommitTransacti
 import org.opendaylight.controller.cluster.datastore.modification.CompositeModification;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
 
-import java.util.concurrent.ExecutionException;
-
 public class ThreePhaseCommitCohort extends AbstractUntypedActor {
     private final DOMStoreThreePhaseCommitCohort cohort;
     private final ActorRef shardActor;
@@ -58,13 +58,17 @@ public class ThreePhaseCommitCohort extends AbstractUntypedActor {
 
     @Override
     public void handleReceive(Object message) throws Exception {
-        if (message.getClass().equals(CanCommitTransaction.SERIALIZABLE_CLASS)) {
+        if (message.getClass()
+            .equals(CanCommitTransaction.SERIALIZABLE_CLASS)) {
             canCommit(new CanCommitTransaction());
-        } else if (message.getClass().equals(PreCommitTransaction.SERIALIZABLE_CLASS)) {
+        } else if (message.getClass()
+            .equals(PreCommitTransaction.SERIALIZABLE_CLASS)) {
             preCommit(new PreCommitTransaction());
-        } else if (message.getClass().equals(CommitTransaction.SERIALIZABLE_CLASS)) {
+        } else if (message.getClass()
+            .equals(CommitTransaction.SERIALIZABLE_CLASS)) {
             commit(new CommitTransaction());
-        } else if (message.getClass().equals(AbortTransaction.SERIALIZABLE_CLASS)) {
+        } else if (message.getClass()
+            .equals(AbortTransaction.SERIALIZABLE_CLASS)) {
             abort(new AbortTransaction());
         } else {
             unknownMessage(message);
@@ -76,17 +80,19 @@ public class ThreePhaseCommitCohort extends AbstractUntypedActor {
         final ActorRef sender = getSender();
         final ActorRef self = getSelf();
 
-        future.addListener(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    future.get();
-                    sender.tell(new AbortTransactionReply().toSerializable(), self);
-                } catch (InterruptedException | ExecutionException e) {
-                    log.error(e, "An exception happened when aborting");
-                }
+        Futures.addCallback(future, new FutureCallback<Void>() {
+            public void onSuccess(Void v) {
+                sender
+                    .tell(new AbortTransactionReply().toSerializable(),
+                        self);
+            }
+
+            public void onFailure(Throwable t) {
+                LOG.error(t, "An exception happened during abort");
+                sender
+                    .tell(new akka.actor.Status.Failure(t), getSelf());
             }
-        }, getContext().dispatcher());
+        });
     }
 
     private void commit(CommitTransaction message) {
@@ -103,18 +109,19 @@ public class ThreePhaseCommitCohort extends AbstractUntypedActor {
         final ListenableFuture<Void> future = cohort.preCommit();
         final ActorRef sender = getSender();
         final ActorRef self = getSelf();
+        Futures.addCallback(future, new FutureCallback<Void>() {
+            public void onSuccess(Void v) {
+                sender
+                    .tell(new PreCommitTransactionReply().toSerializable(),
+                        self);
+            }
 
-        future.addListener(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    future.get();
-                    sender.tell(new PreCommitTransactionReply().toSerializable(), self);
-                } catch (InterruptedException | ExecutionException e) {
-                    log.error(e, "An exception happened when preCommitting");
-                }
+            public void onFailure(Throwable t) {
+                LOG.error(t, "An exception happened during pre-commit");
+                sender
+                    .tell(new akka.actor.Status.Failure(t), getSelf());
             }
-        }, getContext().dispatcher());
+        });
 
     }
 
@@ -122,18 +129,19 @@ public class ThreePhaseCommitCohort extends AbstractUntypedActor {
         final ListenableFuture<Boolean> future = cohort.canCommit();
         final ActorRef sender = getSender();
         final ActorRef self = getSelf();
+        Futures.addCallback(future, new FutureCallback<Boolean>() {
+            public void onSuccess(Boolean canCommit) {
+                sender.tell(new CanCommitTransactionReply(canCommit)
+                    .toSerializable(), self);
+            }
 
-        future.addListener(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    Boolean canCommit = future.get();
-                    sender.tell(new CanCommitTransactionReply(canCommit).toSerializable(), self);
-                } catch (InterruptedException | ExecutionException e) {
-                    log.error(e, "An exception happened when checking canCommit");
-                }
+            public void onFailure(Throwable t) {
+                LOG.error(t, "An exception happened during canCommit");
+                sender
+                    .tell(new akka.actor.Status.Failure(t), getSelf());
             }
-        }, getContext().dispatcher());
+        });
+
 
     }
 }
index 87a621f9d370fa21b4b8e6ea9df4ca5fb42e4c79..592bc49d9e40648a53e6d448666d34c58f2f4184 100644 (file)
@@ -1,6 +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;
 
 public class DistributedConfigDataStoreProviderModule extends
     org.opendaylight.controller.config.yang.config.distributed_datastore_provider.AbstractDistributedConfigDataStoreProviderModule {
@@ -25,8 +26,10 @@ public class DistributedConfigDataStoreProviderModule extends
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-        return DistributedDataStoreFactory
-            .createInstance("config", getConfigSchemaServiceDependency());
+        return DistributedDataStoreFactory.createInstance("config", getConfigSchemaServiceDependency(),
+                InMemoryDOMDataStoreConfigProperties.create(getMaxShardDataChangeExecutorPoolSize(),
+                        getMaxShardDataChangeExecutorQueueSize(),
+                        getMaxShardDataChangeListenerQueueSize()));
     }
 
 }
index 6af2748a8fa3e27ac0644d8fd184f258fa3e859e..9eb72d64d0e90079b5fe1ae7a0405bc5a522b8d0 100644 (file)
@@ -1,6 +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;
 
 public class DistributedOperationalDataStoreProviderModule extends
     org.opendaylight.controller.config.yang.config.distributed_datastore_provider.AbstractDistributedOperationalDataStoreProviderModule {
@@ -25,8 +26,11 @@ public class DistributedOperationalDataStoreProviderModule extends
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-        return DistributedDataStoreFactory
-            .createInstance("operational", getOperationalSchemaServiceDependency());
+        return DistributedDataStoreFactory.createInstance("operational",
+                getOperationalSchemaServiceDependency(),
+                InMemoryDOMDataStoreConfigProperties.create(getMaxShardDataChangeExecutorPoolSize(),
+                        getMaxShardDataChangeExecutorQueueSize(),
+                        getMaxShardDataChangeListenerQueueSize()));
     }
 
 }
index 6f355cbe63f612cda7e40a6f3c24e31c78e253fa..ecb823e624709bc84f167e522efa09bba06e53f8 100644 (file)
@@ -41,28 +41,64 @@ module distributed-datastore-provider {
         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;
-                                }
-                          }
-                        }
+                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.";
+            }
         }
     }
 
     // Augments the 'configuration' choice node under modules/module.
-        augment "/config:modules/config:module/config:configuration" {
-            case distributed-operational-datastore-provider {
-                when "/config:modules/config:module/config:type = 'distributed-operational-datastore-provider'";
+    augment "/config:modules/config:module/config:configuration" {
+        case distributed-operational-datastore-provider {
+            when "/config:modules/config:module/config:type = 'distributed-operational-datastore-provider'";
                 container operational-schema-service {
-                              uses config:service-ref {
-                                   refine type {
-                                          mandatory false;
-                                          config:required-identity sal: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.";
+            }
             }
         }
 }
index 319451f8f00587d7328f5e4c20e4fcc1454051d2..036b00a4c94bd46e77c480c32a16b7ad0b71b3f6 100644 (file)
@@ -58,7 +58,7 @@ public class BasicIntegrationTest extends AbstractActorTest {
                 ShardIdentifier.builder().memberName("member-1")
                     .shardName("inventory").type("config").build();
 
-            final Props props = Shard.props(identifier, Collections.EMPTY_MAP);
+            final Props props = Shard.props(identifier, Collections.EMPTY_MAP, null);
             final ActorRef shard = getSystem().actorOf(props);
 
             new Within(duration("5 seconds")) {
index fc527b6bffe13726d89d5923cee71a6c471af055..49408b741019c98debbe70b37857d871d0f80b8b 100644 (file)
@@ -72,7 +72,7 @@ public class DistributedDataStoreIntegrationTest {
                     protected void run() {
                         try {
                             final DistributedDataStore distributedDataStore =
-                                new DistributedDataStore(getSystem(), "config", new MockClusterWrapper(), configuration);
+                                new DistributedDataStore(getSystem(), "config", new MockClusterWrapper(), configuration, null);
 
                             distributedDataStore.onGlobalContextUpdated(TestModel.createTestContext());
 
@@ -154,7 +154,7 @@ public class DistributedDataStoreIntegrationTest {
                         try {
                             final DistributedDataStore distributedDataStore =
                                 new DistributedDataStore(getSystem(), "config",
-                                    new MockClusterWrapper(), configuration);
+                                    new MockClusterWrapper(), configuration, null);
 
                             distributedDataStore.onGlobalContextUpdated(
                                 SchemaContextHelper.full());
index 406f0ffd9e6383953554d400d31e3b19496bc7c2..69590e62fb1b5886fc0b5fb1223706d02c1706cd 100644 (file)
@@ -68,7 +68,7 @@ public class DistributedDataStoreTest extends AbstractActorTest{
         ActorSystem actorSystem = mock(ActorSystem.class);
 
         new DistributedDataStore(actorSystem, "config",
-            mock(ClusterWrapper.class), mock(Configuration.class));
+            mock(ClusterWrapper.class), mock(Configuration.class), null);
 
         verify(actorSystem).actorOf(any(Props.class), eq("shardmanager-config"));
     }
index e9ad450ed86614ff78114ff4bb545e23ab82367f..499b4e1f3111d097cc0696aa7cd23367fc4c591d 100644 (file)
@@ -42,7 +42,7 @@ public class ShardManagerTest {
         new JavaTestKit(system) {{
             final Props props = ShardManager
                 .props("config", new MockClusterWrapper(),
-                    new MockConfiguration());
+                    new MockConfiguration(), null);
             final TestActorRef<ShardManager> subject =
                 TestActorRef.create(system, props);
 
@@ -66,7 +66,7 @@ public class ShardManagerTest {
         new JavaTestKit(system) {{
             final Props props = ShardManager
                 .props("config", new MockClusterWrapper(),
-                    new MockConfiguration());
+                    new MockConfiguration(), null);
             final TestActorRef<ShardManager> subject =
                 TestActorRef.create(system, props);
 
@@ -89,7 +89,7 @@ public class ShardManagerTest {
         new JavaTestKit(system) {{
             final Props props = ShardManager
                 .props("config", new MockClusterWrapper(),
-                    new MockConfiguration());
+                    new MockConfiguration(), null);
             final TestActorRef<ShardManager> subject =
                 TestActorRef.create(system, props);
 
@@ -124,7 +124,7 @@ public class ShardManagerTest {
         new JavaTestKit(system) {{
             final Props props = ShardManager
                 .props("config", mockClusterWrapper,
-                    new MockConfiguration());
+                    new MockConfiguration(), null);
             final TestActorRef<ShardManager> subject =
                 TestActorRef.create(system, props);
 
@@ -158,7 +158,7 @@ public class ShardManagerTest {
         new JavaTestKit(system) {{
             final Props props = ShardManager
                 .props("config", new MockClusterWrapper(),
-                    new MockConfiguration());
+                    new MockConfiguration(), null);
             final TestActorRef<ShardManager> subject =
                 TestActorRef.create(system, props);
 
@@ -196,7 +196,7 @@ public class ShardManagerTest {
         new JavaTestKit(system) {{
             final Props props = ShardManager
                 .props("config", new MockClusterWrapper(),
-                    new MockConfiguration());
+                    new MockConfiguration(), null);
             final TestActorRef<ShardManager> subject =
                 TestActorRef.create(system, props);
 
index 0d86ffb8444bd7c4ff72bd27b079ab17427db066..7740b8e667a974c10b53d0e436edb41455e40cf5 100644 (file)
@@ -40,7 +40,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);
+            final Props props = Shard.props(identifier, Collections.EMPTY_MAP, null);
             final ActorRef subject =
                 getSystem().actorOf(props, "testCreateTransactionChain");
 
@@ -96,7 +96,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);
+            final Props props = Shard.props(identifier, Collections.EMPTY_MAP, null);
             final ActorRef subject =
                 getSystem().actorOf(props, "testRegisterChangeListener");
 
@@ -154,7 +154,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);
+            final Props props = Shard.props(identifier, Collections.EMPTY_MAP, null);
             final ActorRef subject =
                 getSystem().actorOf(props, "testCreateTransaction");
 
@@ -216,7 +216,7 @@ public class ShardTest extends AbstractActorTest {
                     .shardName("inventory").type("config").build();
 
             peerAddresses.put(identifier, null);
-            final Props props = Shard.props(identifier, peerAddresses);
+            final Props props = Shard.props(identifier, peerAddresses, null);
             final ActorRef subject =
                 getSystem().actorOf(props, "testPeerAddressResolved");
 
index 02ceee82e05d2f78981bb89f3e1c6e9a3b4e1f61..16b73040a5b6e5375a24570fb5b1617240eadb04 100644 (file)
@@ -33,6 +33,7 @@ import static org.junit.Assert.assertTrue;
 
 /**
  * Covers negative test cases
+ *
  * @author Basheeruddin Ahmed <syedbahm@cisco.com>
  */
 public class ShardTransactionFailureTest extends AbstractActorTest {
@@ -48,7 +49,7 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
 
     private static final ShardIdentifier SHARD_IDENTIFIER =
         ShardIdentifier.builder().memberName("member-1")
-            .shardName("inventory").type("config").build();
+            .shardName("inventory").type("operational").build();
 
     static {
         store.onGlobalContextUpdated(testSchemaContext);
@@ -60,7 +61,7 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
         throws Throwable {
 
         final ActorRef shard =
-            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
+            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
         final Props props =
             ShardTransaction.props(store.newReadOnlyTransaction(), shard,
                 TestModel.createTestContext());
@@ -95,7 +96,7 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
         throws Throwable {
 
         final ActorRef shard =
-            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
+            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP,null));
         final Props props =
             ShardTransaction.props(store.newReadWriteTransaction(), shard,
                 TestModel.createTestContext());
@@ -129,7 +130,7 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
         throws Throwable {
 
         final ActorRef shard =
-            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
+            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP,null));
         final Props props =
             ShardTransaction.props(store.newReadWriteTransaction(), shard,
                 TestModel.createTestContext());
@@ -164,7 +165,7 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
 
 
         final ActorRef shard =
-            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
+            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP,null));
         final Props props =
             ShardTransaction.props(store.newWriteOnlyTransaction(), shard,
                 TestModel.createTestContext());
@@ -203,7 +204,7 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
 
 
         final ActorRef shard =
-            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
+            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP,null));
         final Props props =
             ShardTransaction.props(store.newReadWriteTransaction(), shard,
                 TestModel.createTestContext());
@@ -241,7 +242,7 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
 
 
         final ActorRef shard =
-            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
+            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP,null));
         final Props props =
             ShardTransaction.props(store.newReadWriteTransaction(), shard,
                 TestModel.createTestContext());
@@ -279,7 +280,7 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
 
 
         final ActorRef shard =
-            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
+            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP,null));
         final Props props =
             ShardTransaction.props(store.newReadWriteTransaction(), shard,
                 TestModel.createTestContext());
@@ -308,6 +309,4 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
 
 
     }
-
-
 }
index 78895b2366a96aa7e2c85aaa97f2b7a6218a92a2..8f5d0c28d603c39a008f9638ece377aacdf6f1f8 100644 (file)
@@ -62,7 +62,7 @@ public class ShardTransactionTest extends AbstractActorTest {
     @Test
     public void testOnReceiveReadData() throws Exception {
         new JavaTestKit(getSystem()) {{
-            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
+            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
             final Props props =
                 ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
             final ActorRef subject = getSystem().actorOf(props, "testReadData");
@@ -104,7 +104,7 @@ 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));
+            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
             final Props props =
                 ShardTransaction.props( store.newReadOnlyTransaction(), shard, testSchemaContext);
             final ActorRef subject = getSystem().actorOf(props, "testReadDataWhenDataNotFound");
@@ -147,7 +147,7 @@ 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));
+            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
             final Props props =
                 ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
             final ActorRef subject = getSystem().actorOf(props, "testDataExistsPositive");
@@ -189,7 +189,8 @@ public class ShardTransactionTest extends AbstractActorTest {
     @Test
     public void testOnReceiveDataExistsNegative() throws Exception {
         new JavaTestKit(getSystem()) {{
-            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
+            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER,
+                    Collections.EMPTY_MAP, null));
             final Props props =
                 ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
             final ActorRef subject = getSystem().actorOf(props, "testDataExistsNegative");
@@ -266,7 +267,7 @@ 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));
+            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 subject =
@@ -306,7 +307,7 @@ 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));
+            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
             final Props props =
                 ShardTransaction.props(store.newReadWriteTransaction(), shard, testSchemaContext);
             final ActorRef subject =
@@ -347,7 +348,7 @@ 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));
+            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 subject =
@@ -386,7 +387,7 @@ 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));
+            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 subject =
@@ -424,7 +425,7 @@ 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));
+            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 subject =
@@ -479,7 +480,7 @@ public class ShardTransactionTest extends AbstractActorTest {
   public void testNegativePerformingWriteOperationOnReadTransaction() throws Exception {
     try {
 
-        final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
+        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());
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohortFailureTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohortFailureTest.java
new file mode 100644 (file)
index 0000000..870889b
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ *
+ *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ *  This program and the accompanying materials are made available under the
+ *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ *  and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ */
+
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.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.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier;
+import org.opendaylight.controller.cluster.datastore.messages.ForwardedCommitTransaction;
+import org.opendaylight.controller.cluster.datastore.modification.CompositeModification;
+import org.opendaylight.controller.cluster.datastore.modification.Modification;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+import org.opendaylight.controller.protobuff.messages.cohort3pc.ThreePhaseCommitCohortMessages;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
+import org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages;
+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;
+import scala.concurrent.duration.FiniteDuration;
+
+import java.util.Collections;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+
+public class ThreePhaseCommitCohortFailureTest extends AbstractActorTest {
+
+    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 ShardIdentifier SHARD_IDENTIFIER =
+        ShardIdentifier.builder().memberName("member-1")
+            .shardName("inventory").type("config").build();
+
+    static {
+        store.onGlobalContextUpdated(testSchemaContext);
+    }
+
+    private FiniteDuration ASK_RESULT_DURATION = Duration.create(3000, 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 DOMStoreThreePhaseCommitCohort mockCohort = Mockito
+            .mock(DOMStoreThreePhaseCommitCohort.class);
+        final CompositeModification mockComposite =
+            Mockito.mock(CompositeModification.class);
+        final Props props =
+            ThreePhaseCommitCohort.props(mockCohort, shard, mockComposite);
+
+        final TestActorRef<ThreePhaseCommitCohort> subject = TestActorRef
+            .create(getSystem(), props,
+                "testNegativeAbortResultsInException");
+
+        when(mockCohort.abort()).thenReturn(
+            Futures.<Void>immediateFailedFuture(new TestException()));
+
+        Future<Object> future =
+            akka.pattern.Patterns.ask(subject,
+                ThreePhaseCommitCohortMessages.AbortTransaction.newBuilder()
+                    .build(), 3000);
+        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 DOMStoreThreePhaseCommitCohort mockCohort = Mockito
+            .mock(DOMStoreThreePhaseCommitCohort.class);
+        final CompositeModification mockComposite =
+            Mockito.mock(CompositeModification.class);
+        final Props props =
+            ThreePhaseCommitCohort.props(mockCohort, shard, mockComposite);
+
+        final TestActorRef<ThreePhaseCommitCohort> subject = TestActorRef
+            .create(getSystem(), props,
+                "testNegativeCanCommitResultsInException");
+
+        when(mockCohort.canCommit()).thenReturn(
+            Futures
+                .<Boolean>immediateFailedFuture(
+                    new OptimisticLockFailedException("some exception")));
+
+        Future<Object> future =
+            akka.pattern.Patterns.ask(subject,
+                ThreePhaseCommitCohortMessages.CanCommitTransaction.newBuilder()
+                    .build(), 3000);
+
+
+        Await.result(future, ASK_RESULT_DURATION);
+
+    }
+
+
+    @Test(expected = TestException.class)
+    public void testNegativePreCommitResultsInException() throws Exception {
+
+        final ActorRef shard =
+            getSystem()
+                .actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP,null));
+        final DOMStoreThreePhaseCommitCohort mockCohort = Mockito
+            .mock(DOMStoreThreePhaseCommitCohort.class);
+        final CompositeModification mockComposite =
+            Mockito.mock(CompositeModification.class);
+        final Props props =
+            ThreePhaseCommitCohort.props(mockCohort, shard, mockComposite);
+
+        final TestActorRef<ThreePhaseCommitCohort> subject = TestActorRef
+            .create(getSystem(), props,
+                "testNegativePreCommitResultsInException");
+
+        when(mockCohort.preCommit()).thenReturn(
+            Futures
+                .<Void>immediateFailedFuture(
+                    new TestException()));
+
+        Future<Object> future =
+            akka.pattern.Patterns.ask(subject,
+                ThreePhaseCommitCohortMessages.PreCommitTransaction.newBuilder()
+                    .build(), 3000);
+
+        Await.result(future, ASK_RESULT_DURATION);
+
+    }
+
+    @Test(expected = TestException.class)
+    public void testNegativeCommitResultsInException() throws Exception {
+
+        final TestActorRef<Shard> subject = TestActorRef
+            .create(getSystem(),
+                Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP,null),
+                "testNegativeCommitResultsInException");
+
+        final ActorRef shardTransaction =
+            getSystem().actorOf(
+                ShardTransaction.props(store.newReadWriteTransaction(), subject,
+                    TestModel.createTestContext()));
+
+        ShardTransactionMessages.WriteData writeData =
+            ShardTransactionMessages.WriteData.newBuilder()
+                .setInstanceIdentifierPathArguments(
+                    NormalizedNodeMessages.InstanceIdentifier.newBuilder()
+                        .build()).setNormalizedNode(
+                NormalizedNodeMessages.Node.newBuilder().build()
+
+            ).build();
+
+        //This is done so that Modification list is updated which is used during commit
+        Future future =
+            akka.pattern.Patterns.ask(shardTransaction, writeData, 3000);
+
+        //ready transaction creates the cohort so that we get into the
+        //block where in commmit is done
+        ShardTransactionMessages.ReadyTransaction readyTransaction =
+            ShardTransactionMessages.ReadyTransaction.newBuilder().build();
+
+        future =
+            akka.pattern.Patterns.ask(shardTransaction, readyTransaction, 3000);
+
+        //but when the message is sent it will have the MockCommit object
+        //so that we can simulate throwing of exception
+        ForwardedCommitTransaction mockForwardCommitTransaction =
+            Mockito.mock(ForwardedCommitTransaction.class);
+        DOMStoreThreePhaseCommitCohort mockThreePhaseCommitTransaction =
+            Mockito.mock(DOMStoreThreePhaseCommitCohort.class);
+        when(mockForwardCommitTransaction.getCohort())
+            .thenReturn(mockThreePhaseCommitTransaction);
+        when(mockThreePhaseCommitTransaction.commit()).thenReturn(Futures
+            .<Void>immediateFailedFuture(
+                new TestException()));
+        Modification mockModification = Mockito.mock(
+            Modification.class);
+        when(mockForwardCommitTransaction.getModification())
+            .thenReturn(mockModification);
+
+        when(mockModification.toSerializable()).thenReturn(
+            PersistentMessages.CompositeModification.newBuilder().build());
+
+        future =
+            akka.pattern.Patterns.ask(subject,
+                mockForwardCommitTransaction
+                , 3000);
+        Await.result(future, ASK_RESULT_DURATION);
+
+
+    }
+
+    private class TestException extends Exception {
+    }
+
+
+}
index 948f3c8d8b637b8dfb72fdd376fa7ee1f49aa3c3..8664e8910b46bda523951f22961d59c13cbaec42 100644 (file)
@@ -16,8 +16,6 @@ import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreFac
 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
 import org.opendaylight.yangtools.util.concurrent.DeadlockDetectingListeningExecutorService;
 import org.opendaylight.yangtools.util.concurrent.SpecialExecutors;
-import org.opendaylight.yangtools.util.PropertyUtils;
-
 import com.google.common.collect.ImmutableMap;
 
 /**
@@ -26,17 +24,6 @@ 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 FUTURE_CALLBACK_EXECUTOR_MAX_QUEUE_SIZE_PROP =
-            "mdsal.datastore-future-callback-queue.size";
-    private static final int DEFAULT_FUTURE_CALLBACK_EXECUTOR_MAX_QUEUE_SIZE = 1000;
-
-    private static final String FUTURE_CALLBACK_EXECUTOR_MAX_POOL_SIZE_PROP =
-            "mdsal.datastore-future-callback-pool.size";
-    private static final int DEFAULT_FUTURE_CALLBACK_EXECUTOR_MAX_POOL_SIZE = 20;
-    private static final String COMMIT_EXECUTOR_MAX_QUEUE_SIZE_PROP =
-            "mdsal.datastore-commit-queue.size";
-    private static final int DEFAULT_COMMIT_EXECUTOR_MAX_QUEUE_SIZE = 5000;
-
     public DomInmemoryDataBrokerModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
             final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
         super(identifier, dependencyResolver);
@@ -81,9 +68,7 @@ public final class DomInmemoryDataBrokerModule extends
          * system it's running on.
          */
         ExecutorService commitExecutor = SpecialExecutors.newBoundedSingleThreadExecutor(
-                PropertyUtils.getIntSystemProperty(
-                        COMMIT_EXECUTOR_MAX_QUEUE_SIZE_PROP,
-                        DEFAULT_COMMIT_EXECUTOR_MAX_QUEUE_SIZE), "WriteTxCommit");
+                getMaxDataBrokerCommitQueueSize(), "WriteTxCommit");
 
         /*
          * We use an executor for commit ListenableFuture callbacks that favors reusing available
@@ -94,12 +79,8 @@ public final class DomInmemoryDataBrokerModule extends
          * reached, subsequent submitted tasks will block the caller.
          */
         Executor listenableFutureExecutor = SpecialExecutors.newBlockingBoundedCachedThreadPool(
-                PropertyUtils.getIntSystemProperty(
-                        FUTURE_CALLBACK_EXECUTOR_MAX_POOL_SIZE_PROP,
-                        DEFAULT_FUTURE_CALLBACK_EXECUTOR_MAX_POOL_SIZE),
-                PropertyUtils.getIntSystemProperty(
-                        FUTURE_CALLBACK_EXECUTOR_MAX_QUEUE_SIZE_PROP,
-                        DEFAULT_FUTURE_CALLBACK_EXECUTOR_MAX_QUEUE_SIZE), "CommitFutures");
+                getMaxDataBrokerFutureCallbackPoolSize(), getMaxDataBrokerFutureCallbackQueueSize(),
+                "CommitFutures");
 
         DOMDataBrokerImpl newDataBroker = new DOMDataBrokerImpl(datastores,
                 new DeadlockDetectingListeningExecutorService(commitExecutor,
index a0ee5c50c93bc8a576c2d71b2dd7b37b86cda896..b1df7efcdbb6e4efb0ad6fdd2ecbf85aed2b98d1 100644 (file)
@@ -108,6 +108,24 @@ module opendaylight-sal-dom-broker-impl {
                        }
                    }
             }
+
+            leaf max-data-broker-future-callback-queue-size {
+                default 1000;
+                type uint16;
+                description "The maximum queue size for the data broker's commit future callback executor.";
+            }
+
+            leaf max-data-broker-future-callback-pool-size {
+                default 20;
+                type uint16;
+                description "The maximum thread pool size for the data broker's commit future callback executor.";
+            }
+
+            leaf max-data-broker-commit-queue-size {
+                default 5000;
+                type uint16;
+                description "The maximum queue size for the data broker's commit executor.";
+            }
         }
     }
     
index 39a448ff6c861ac4db998bf0d17f4ec4d8e22d6d..fd1627c6f994677abe043f767519fbb78e2d5eeb 100644 (file)
@@ -1,5 +1,6 @@
 package org.opendaylight.controller.config.yang.inmemory_datastore_provider;
 
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreConfigProperties;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreFactory;
 
 public class InMemoryConfigDataStoreProviderModule extends org.opendaylight.controller.config.yang.inmemory_datastore_provider.AbstractInMemoryConfigDataStoreProviderModule {
@@ -19,7 +20,9 @@ public class InMemoryConfigDataStoreProviderModule extends org.opendaylight.cont
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-        return InMemoryDOMDataStoreFactory.create("DOM-CFG", getSchemaServiceDependency());
+        return InMemoryDOMDataStoreFactory.create("DOM-CFG", getSchemaServiceDependency(),
+                InMemoryDOMDataStoreConfigProperties.create(getMaxDataChangeExecutorPoolSize(),
+                        getMaxDataChangeExecutorQueueSize(), getMaxDataChangeListenerQueueSize()));
     }
 
 }
index 615fe0211c0cbba8c1bc5c1a5687dd1ccea8dc33..7026b03022ff47b548743b34efb3f0f35d6d6e94 100644 (file)
@@ -1,5 +1,6 @@
 package org.opendaylight.controller.config.yang.inmemory_datastore_provider;
 
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreConfigProperties;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreFactory;
 
 public class InMemoryOperationalDataStoreProviderModule extends org.opendaylight.controller.config.yang.inmemory_datastore_provider.AbstractInMemoryOperationalDataStoreProviderModule {
@@ -19,7 +20,9 @@ public class InMemoryOperationalDataStoreProviderModule extends org.opendaylight
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-        return InMemoryDOMDataStoreFactory.create("DOM-OPER", getOperationalSchemaServiceDependency());
+        return InMemoryDOMDataStoreFactory.create("DOM-OPER", getOperationalSchemaServiceDependency(),
+                InMemoryDOMDataStoreConfigProperties.create(getMaxDataChangeExecutorPoolSize(),
+                        getMaxDataChangeExecutorQueueSize(), getMaxDataChangeListenerQueueSize()));
     }
 
 }
index b61b3671034601fc09d7658280f986d4d30cc3ce..d0d3fe9e6aa1b928b0e6524307ba60b8900720ee 100644 (file)
@@ -21,7 +21,6 @@ import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedEx
 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.PropertyUtils;
 import org.opendaylight.yangtools.util.concurrent.NotificationManager;
 import org.opendaylight.yangtools.util.concurrent.QueuedNotificationManager;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificationAppliedException;
@@ -85,11 +84,6 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
                 }
             };
 
-    private static final String DCL_NOTIFICATION_MGR_MAX_QUEUE_SIZE_PROP =
-            "mdsal.datastore-dcl-notification-queue.size";
-
-    private static final int DEFAULT_DCL_NOTIFICATION_MGR_MAX_QUEUE_SIZE = 1000;
-
     private final DataTree dataTree = InMemoryDataTreeFactory.getInstance().create();
     private final ListenerTree listenerTree = ListenerTree.create();
     private final AtomicLong txCounter = new AtomicLong(0);
@@ -104,17 +98,21 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
 
     public InMemoryDOMDataStore(final String name, final ListeningExecutorService listeningExecutor,
             final ExecutorService dataChangeListenerExecutor) {
+        this(name, listeningExecutor, dataChangeListenerExecutor,
+                InMemoryDOMDataStoreConfigProperties.DEFAULT_MAX_DATA_CHANGE_LISTENER_QUEUE_SIZE);
+    }
+
+    public InMemoryDOMDataStore(final String name, final ListeningExecutorService listeningExecutor,
+            final ExecutorService dataChangeListenerExecutor, int maxDataChangeListenerQueueSize) {
         this.name = Preconditions.checkNotNull(name);
         this.listeningExecutor = Preconditions.checkNotNull(listeningExecutor);
 
         this.dataChangeListenerExecutor = Preconditions.checkNotNull(dataChangeListenerExecutor);
 
-        int maxDCLQueueSize = PropertyUtils.getIntSystemProperty(
-                DCL_NOTIFICATION_MGR_MAX_QUEUE_SIZE_PROP, DEFAULT_DCL_NOTIFICATION_MGR_MAX_QUEUE_SIZE );
-
         dataChangeListenerNotificationManager =
                 new QueuedNotificationManager<>(this.dataChangeListenerExecutor,
-                        DCL_NOTIFICATION_MGR_INVOKER, maxDCLQueueSize, "DataChangeListenerQueueMgr");
+                        DCL_NOTIFICATION_MGR_INVOKER, maxDataChangeListenerQueueSize,
+                        "DataChangeListenerQueueMgr");
     }
 
     @Override
diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStoreConfigProperties.java b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStoreConfigProperties.java
new file mode 100644 (file)
index 0000000..6e451ba
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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;
+
+/**
+ * Holds configuration properties when creating an {@link InMemoryDOMDataStore} instance via the
+ * {@link InMemoryDOMDataStoreFactory}
+ *
+ * @author Thomas Pantelis
+ * @see InMemoryDOMDataStoreFactory
+ */
+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;
+
+    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);
+
+    private final int maxDataChangeExecutorQueueSize;
+    private final int maxDataChangeExecutorPoolSize;
+    private final int maxDataChangeListenerQueueSize;
+
+    /**
+     * Constructs an instance with the given property values.
+     *
+     * @param maxDataChangeExecutorPoolSize
+     *            maximum thread pool size for the data change notification executor.
+     * @param maxDataChangeExecutorQueueSize
+     *            maximum queue size for the data change notification executor.
+     * @param maxDataChangeListenerQueueSize
+     *            maximum queue size for the data change listeners.
+     */
+    public static InMemoryDOMDataStoreConfigProperties create(int maxDataChangeExecutorPoolSize,
+            int maxDataChangeExecutorQueueSize, int maxDataChangeListenerQueueSize) {
+        return new InMemoryDOMDataStoreConfigProperties(maxDataChangeExecutorPoolSize,
+                maxDataChangeExecutorQueueSize, maxDataChangeListenerQueueSize);
+    }
+
+    /**
+     * Returns the InMemoryDOMDataStoreConfigProperties instance with default values.
+     */
+    public static InMemoryDOMDataStoreConfigProperties getDefault() {
+        return DEFAULT;
+    }
+
+    private InMemoryDOMDataStoreConfigProperties(int maxDataChangeExecutorPoolSize,
+            int maxDataChangeExecutorQueueSize, int maxDataChangeListenerQueueSize) {
+        this.maxDataChangeExecutorQueueSize = maxDataChangeExecutorQueueSize;
+        this.maxDataChangeExecutorPoolSize = maxDataChangeExecutorPoolSize;
+        this.maxDataChangeListenerQueueSize = maxDataChangeListenerQueueSize;
+    }
+
+    /**
+     * Returns the maximum queue size for the data change notification executor.
+     */
+    public int getMaxDataChangeExecutorQueueSize() {
+        return maxDataChangeExecutorQueueSize;
+    }
+
+    /**
+     * Returns the maximum thread pool size for the data change notification executor.
+     */
+    public int getMaxDataChangeExecutorPoolSize() {
+        return maxDataChangeExecutorPoolSize;
+    }
+
+    /**
+     * Returns the maximum queue size for the data change listeners.
+     */
+    public int getMaxDataChangeListenerQueueSize() {
+        return maxDataChangeListenerQueueSize;
+    }
+}
index c853a132de6395fb1b562406e0edfcddeeed1166..a3512743ed1a34acac5a1923983e06995e0d0f24 100644 (file)
@@ -15,7 +15,6 @@ import javax.annotation.Nullable;
 
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
 import org.opendaylight.yangtools.util.concurrent.SpecialExecutors;
-import org.opendaylight.yangtools.util.PropertyUtils;
 import com.google.common.util.concurrent.MoreExecutors;
 
 /**
@@ -25,43 +24,46 @@ import com.google.common.util.concurrent.MoreExecutors;
  */
 public final class InMemoryDOMDataStoreFactory {
 
-    private static final String DCL_EXECUTOR_MAX_QUEUE_SIZE_PROP =
-            "mdsal.datastore-dcl-notification-queue.size";
-    private static final int DEFAULT_DCL_EXECUTOR_MAX_QUEUE_SIZE = 1000;
-
-    private static final String DCL_EXECUTOR_MAX_POOL_SIZE_PROP =
-            "mdsal.datastore-dcl-notification-pool.size";
-    private static final int DEFAULT_DCL_EXECUTOR_MAX_POOL_SIZE = 20;
-
     private InMemoryDOMDataStoreFactory() {
     }
 
+    public static InMemoryDOMDataStore create(final String name,
+            @Nullable final SchemaService schemaService) {
+        return create(name, schemaService, null);
+    }
+
     /**
      * Creates an InMemoryDOMDataStore instance.
      *
      * @param name the name of the data store
      * @param schemaService the SchemaService to which to register the data store.
+     * @param properties configuration properties for the InMemoryDOMDataStore instance. If null,
+     *                   default property values are used.
      * @return an InMemoryDOMDataStore instance
      */
     public static InMemoryDOMDataStore create(final String name,
-            @Nullable final SchemaService schemaService) {
+            @Nullable final SchemaService schemaService,
+            @Nullable final InMemoryDOMDataStoreConfigProperties properties) {
+
+        InMemoryDOMDataStoreConfigProperties actualProperties = properties;
+        if(actualProperties == null) {
+            actualProperties = InMemoryDOMDataStoreConfigProperties.getDefault();
+        }
 
         // For DataChangeListener notifications we use an executor that provides the fastest
         // task execution time to get higher throughput as DataChangeListeners typically provide
         // much of the business logic for a data model. If the executor queue size limit is reached,
         // subsequent submitted notifications will block the calling thread.
 
-        int dclExecutorMaxQueueSize = PropertyUtils.getIntSystemProperty(
-                DCL_EXECUTOR_MAX_QUEUE_SIZE_PROP, DEFAULT_DCL_EXECUTOR_MAX_QUEUE_SIZE);
-        int dclExecutorMaxPoolSize = PropertyUtils.getIntSystemProperty(
-                DCL_EXECUTOR_MAX_POOL_SIZE_PROP, DEFAULT_DCL_EXECUTOR_MAX_POOL_SIZE);
+        int dclExecutorMaxQueueSize = actualProperties.getMaxDataChangeExecutorQueueSize();
+        int dclExecutorMaxPoolSize = actualProperties.getMaxDataChangeExecutorPoolSize();
 
         ExecutorService dataChangeListenerExecutor = SpecialExecutors.newBlockingBoundedFastThreadPool(
                 dclExecutorMaxPoolSize, dclExecutorMaxQueueSize, name + "-DCL" );
 
         InMemoryDOMDataStore dataStore = new InMemoryDOMDataStore(name,
                 MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()),
-                dataChangeListenerExecutor);
+                dataChangeListenerExecutor, actualProperties.getMaxDataChangeListenerQueueSize());
 
         if(schemaService != null) {
             schemaService.registerSchemaContextListener(dataStore);
index d4f57b53fed168dae3f1402123f9164f8c772455..1292d3772a6a9d99fb9527fa8688d1925f83a599 100644 (file)
@@ -41,34 +41,68 @@ module opendaylight-inmemory-datastore-provider {
             when "/config:modules/config:module/config:type = 'inmemory-config-datastore-provider'";
 
             container schema-service {
-              uses config:service-ref {
+                uses config:service-ref {
                    refine type {
                           mandatory false;
                           config:required-identity sal:schema-service;
                     }
-              }
+                }
+            }
+
+            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.";
+            }
+
+            leaf max-data-change-listener-queue-size {
+                default 1000;
+                type uint16;
+                description "The maximum queue size for the data change listeners.";
             }
         }
     }
 
+    // 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'";
 
+            // 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;
+                    }
+                }
+            }
+
+            leaf max-data-change-executor-queue-size {
+                default 1000;
+                type uint16;
+                description "The maximum queue 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-executor-pool-size {
+                default 20;
+                type uint16;
+                description "The maximum thread pool size for the data change notification executor.";
+            }
 
-                // 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;
-                        }
-                  }
-                }
+            leaf max-data-change-listener-queue-size {
+                default 1000;
+                type uint16;
+                description "The maximum queue size for the data change listeners.";
             }
         }
+    }
 }
index 674c5bf5a596bb03a34f785d854ffdb305aac12b..c47af93c4eb362d7dc00ec2088f2b8e6099df180 100644 (file)
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-core-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>netconf-util</artifactId>
     </dependency>
       <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>sal-core-spi</artifactId>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-core-spi</artifactId>
       </dependency>
       <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>sal-common-impl</artifactId>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-common-impl</artifactId>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>netconf-util</artifactId>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-clustering-commons</artifactId>
+      </dependency>
+
     <!-- Yang tools-->
 
     <dependency>
             <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
             <Export-package></Export-package>
             <Private-Package></Private-Package>
-            <Import-Package>!org.jboss.*;!com.jcraft.*;*</Import-Package>
+            <Import-Package>!org.iq80.*;!*snappy;!org.jboss.*;!com.jcraft.*;!org.fusesource.*;*</Import-Package>
             <Embed-Dependency>
+                sal-clustering-commons;
+                sal-akka-raft;
                 !sal*;
                 !*config-api*;
                 !*testkit*;
           </execution>
         </executions>
       </plugin>
+
+
+
     </plugins>
   </build>
   <scm>
index 1f1a0f5cc6bde65f8b450aa90020593664752483..da0d62897a9d77cdbf6273acd7a80fdc7e11c6e0 100644 (file)
@@ -16,4 +16,5 @@ public class ActorConstants {
 
   public static final String RPC_BROKER_PATH= "/user/rpc/rpc-broker";
   public static final String RPC_REGISTRY_PATH = "/user/rpc/rpc-registry";
+  public static final String RPC_MANAGER_PATH = "/user/rpc";
 }
index d384144f4fde6389861597777bd795b30478e773..4496bd3263f9f80c6d1594e2e51de474ecb22a46 100644 (file)
@@ -4,11 +4,10 @@ import akka.actor.ActorRef;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.controller.remote.rpc.messages.ErrorResponse;
-import org.opendaylight.controller.remote.rpc.messages.InvokeRoutedRpc;
 import org.opendaylight.controller.remote.rpc.messages.InvokeRpc;
 import org.opendaylight.controller.remote.rpc.messages.RpcResponse;
 import org.opendaylight.controller.remote.rpc.utils.ActorUtil;
-import org.opendaylight.controller.remote.rpc.utils.XmlUtils;
+import org.opendaylight.controller.xml.codec.XmlUtils;
 import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
 import org.opendaylight.controller.sal.core.api.RpcImplementation;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -36,7 +35,7 @@ public class RemoteRpcImplementation implements RpcImplementation,
 
   @Override
   public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, YangInstanceIdentifier identifier, CompositeNode input) {
-    InvokeRoutedRpc rpcMsg = new InvokeRoutedRpc(rpc, identifier, input);
+    InvokeRpc rpcMsg = new InvokeRpc(rpc, identifier, input);
 
     return executeMsg(rpcMsg);
   }
@@ -49,7 +48,7 @@ public class RemoteRpcImplementation implements RpcImplementation,
 
   @Override
   public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
-    InvokeRpc rpcMsg = new InvokeRpc(rpc, input);
+    InvokeRpc rpcMsg = new InvokeRpc(rpc, null, input);
     return executeMsg(rpcMsg);
   }
 
@@ -57,7 +56,7 @@ public class RemoteRpcImplementation implements RpcImplementation,
     ListenableFuture<RpcResult<CompositeNode>> listenableFuture = null;
 
     try {
-      Object response = ActorUtil.executeLocalOperation(rpcBroker, rpcMsg, ActorUtil.ASK_DURATION, ActorUtil.AWAIT_DURATION);
+      Object response = ActorUtil.executeOperation(rpcBroker, rpcMsg, ActorUtil.ASK_DURATION, ActorUtil.AWAIT_DURATION);
       if(response instanceof RpcResponse) {
 
         RpcResponse rpcResponse = (RpcResponse) response;
@@ -74,7 +73,7 @@ public class RemoteRpcImplementation implements RpcImplementation,
 
       }
     } catch (Exception e) {
-      LOG.error("Error occurred while invoking RPC actor {}", e.toString());
+      LOG.error("Error occurred while invoking RPC actor {}", e);
 
       final RpcResultBuilder<CompositeNode> failed = RpcResultBuilder.failed();
       failed.withError(null, null, e.getMessage(), null, null, e.getCause());
index ac50b8fe5b0fcdcbfb9f78ef495308586a4a313c..d088f2284d65904cc90d3aa3d6f39a4ca2cc99aa 100644 (file)
@@ -12,8 +12,6 @@ package org.opendaylight.controller.remote.rpc;
 import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
 import org.opendaylight.controller.remote.rpc.messages.UpdateSchemaContext;
-import org.opendaylight.controller.remote.rpc.registry.ClusterWrapper;
-import org.opendaylight.controller.remote.rpc.registry.ClusterWrapperImpl;
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.controller.sal.core.api.Provider;
 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
@@ -64,11 +62,10 @@ public class RemoteRpcProvider implements AutoCloseable, Provider, SchemaContext
   private void start() {
     LOG.info("Starting all rpc listeners and actors.");
     // Create actor to handle and sync routing table in cluster
-    ClusterWrapper clusterWrapper = new ClusterWrapperImpl(actorSystem);
     SchemaService schemaService = brokerSession.getService(SchemaService.class);
     schemaContext = schemaService.getGlobalContext();
 
-    rpcManager = actorSystem.actorOf(RpcManager.props(clusterWrapper, schemaContext, brokerSession, rpcProvisionRegistry), ActorConstants.RPC_MANAGER);
+    rpcManager = actorSystem.actorOf(RpcManager.props(schemaContext, brokerSession, rpcProvisionRegistry), ActorConstants.RPC_MANAGER);
 
     LOG.debug("Rpc actors are created.");
   }
index a6eeac02708a20e8a746581d80c5054a776ed671..98cf6a329f655f3caeebb39b989a1b761ca9a5cd 100644 (file)
@@ -13,15 +13,14 @@ import akka.actor.ActorRef;
 import com.google.common.base.Preconditions;
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
-import org.opendaylight.controller.remote.rpc.messages.AddRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.RemoveRoutedRpc;
-import org.opendaylight.controller.remote.rpc.utils.ActorUtil;
+import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
@@ -29,23 +28,24 @@ import java.util.Set;
 public class RoutedRpcListener implements RouteChangeListener<RpcRoutingContext, YangInstanceIdentifier>{
   private static final Logger LOG = LoggerFactory.getLogger(RoutedRpcListener.class);
   private final ActorRef rpcRegistry;
-  private final String actorPath;
 
-  public RoutedRpcListener(ActorRef rpcRegistry, String actorPath) {
+  public RoutedRpcListener(ActorRef rpcRegistry) {
     Preconditions.checkNotNull(rpcRegistry, "rpc registry actor should not be null");
-    Preconditions.checkNotNull(actorPath, "actor path of rpc broker on current node should not be null");
 
     this.rpcRegistry = rpcRegistry;
-    this.actorPath = actorPath;
   }
 
   @Override
   public void onRouteChange(RouteChange<RpcRoutingContext, YangInstanceIdentifier> routeChange) {
     Map<RpcRoutingContext, Set<YangInstanceIdentifier>> announcements = routeChange.getAnnouncements();
-    announce(getRouteIdentifiers(announcements));
+    if(announcements != null && announcements.size() > 0){
+      announce(getRouteIdentifiers(announcements));
+    }
 
     Map<RpcRoutingContext, Set<YangInstanceIdentifier>> removals = routeChange.getRemovals();
-    remove(getRouteIdentifiers(removals));
+    if(removals != null && removals.size() > 0 ) {
+      remove(getRouteIdentifiers(removals));
+    }
   }
 
   /**
@@ -54,13 +54,8 @@ public class RoutedRpcListener implements RouteChangeListener<RpcRoutingContext,
    */
   private void announce(Set<RpcRouter.RouteIdentifier<?, ?, ?>> announcements) {
     LOG.debug("Announcing [{}]", announcements);
-    AddRoutedRpc addRpcMsg = new AddRoutedRpc(announcements, actorPath);
-    try {
-      ActorUtil.executeLocalOperation(rpcRegistry, addRpcMsg, ActorUtil.LOCAL_ASK_DURATION, ActorUtil.LOCAL_AWAIT_DURATION);
-    } catch (Exception e) {
-      // Just logging it because Akka API throws this exception
-      LOG.error(e.toString());
-    }
+    RpcRegistry.Messages.AddOrUpdateRoutes addRpcMsg = new RpcRegistry.Messages.AddOrUpdateRoutes(new ArrayList<>(announcements));
+    rpcRegistry.tell(addRpcMsg, ActorRef.noSender());
   }
 
   /**
@@ -69,13 +64,8 @@ public class RoutedRpcListener implements RouteChangeListener<RpcRoutingContext,
    */
   private void remove(Set<RpcRouter.RouteIdentifier<?, ?, ?>> removals){
     LOG.debug("Removing [{}]", removals);
-    RemoveRoutedRpc removeRpcMsg = new RemoveRoutedRpc(removals, actorPath);
-    try {
-      ActorUtil.executeLocalOperation(rpcRegistry, removeRpcMsg, ActorUtil.LOCAL_ASK_DURATION, ActorUtil.LOCAL_AWAIT_DURATION);
-    } catch (Exception e) {
-      // Just logging it because Akka API throws this exception
-      LOG.error(e.toString());
-    }
+    RpcRegistry.Messages.RemoveRoutes removeRpcMsg = new RpcRegistry.Messages.RemoveRoutes(new ArrayList<>(removals));
+    rpcRegistry.tell(removeRpcMsg, ActorRef.noSender());
   }
 
   /**
index 26e8e960e3ce46d5f9ea9b3047160134a1f2df36..4ec96c29cd2510175defa6327a235ffecb519b28 100644 (file)
@@ -11,17 +11,17 @@ package org.opendaylight.controller.remote.rpc;
 import akka.actor.ActorRef;
 import akka.actor.Props;
 import akka.japi.Creator;
+import akka.japi.Pair;
 import org.opendaylight.controller.remote.rpc.messages.ErrorResponse;
 import org.opendaylight.controller.remote.rpc.messages.ExecuteRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpcReply;
-import org.opendaylight.controller.remote.rpc.messages.GetRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRpcReply;
-import org.opendaylight.controller.remote.rpc.messages.InvokeRoutedRpc;
 import org.opendaylight.controller.remote.rpc.messages.InvokeRpc;
 import org.opendaylight.controller.remote.rpc.messages.RpcResponse;
+import org.opendaylight.controller.remote.rpc.utils.LatestEntryRoutingLogic;
+import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
 import org.opendaylight.controller.remote.rpc.utils.ActorUtil;
-import org.opendaylight.controller.remote.rpc.utils.XmlUtils;
+import org.opendaylight.controller.remote.rpc.utils.RoutingLogic;
+import org.opendaylight.controller.xml.codec.XmlUtils;
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
@@ -29,6 +29,7 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.List;
 import java.util.concurrent.Future;
 
 /**
@@ -59,81 +60,57 @@ public class RpcBroker extends AbstractUntypedActor {
   }
   @Override
   protected void handleReceive(Object message) throws Exception {
-    if(message instanceof InvokeRoutedRpc) {
-      invokeRemoteRoutedRpc((InvokeRoutedRpc) message);
-    } else if(message instanceof InvokeRpc) {
+   if(message instanceof InvokeRpc) {
       invokeRemoteRpc((InvokeRpc) message);
     } else if(message instanceof ExecuteRpc) {
       executeRpc((ExecuteRpc) message);
     }
   }
 
-  private void invokeRemoteRoutedRpc(InvokeRoutedRpc msg) {
-    // Look up the remote actor to execute rpc
-    LOG.debug("Looking up the remote actor for route {}", msg);
-    try {
-      RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, msg.getRpc(), msg.getIdentifier());
-      GetRoutedRpc routedRpcMsg = new GetRoutedRpc(routeId);
-      GetRoutedRpcReply rpcReply = (GetRoutedRpcReply) ActorUtil.executeLocalOperation(rpcRegistry, routedRpcMsg, ActorUtil.LOCAL_ASK_DURATION, ActorUtil.LOCAL_AWAIT_DURATION);
-
-      String remoteActorPath = rpcReply.getRoutePath();
-      if(remoteActorPath == null) {
-        LOG.debug("No remote actor found for rpc execution.");
-
-        getSender().tell(new ErrorResponse(
-          new IllegalStateException("No remote actor found for rpc execution.")), self());
-      } else {
-
-        ExecuteRpc executeMsg = new ExecuteRpc(XmlUtils.inputCompositeNodeToXml(msg.getInput(), schemaContext), msg.getRpc());
-
-        Object operationRes = ActorUtil.executeRemoteOperation(this.context().actorSelection(remoteActorPath),
-            executeMsg, ActorUtil.REMOTE_ASK_DURATION, ActorUtil.REMOTE_AWAIT_DURATION);
-
-        getSender().tell(operationRes, self());
-      }
-    } catch (Exception e) {
-        LOG.error(e.toString());
-        getSender().tell(new ErrorResponse(e), self());
-    }
-  }
-
   private void invokeRemoteRpc(InvokeRpc msg) {
     // Look up the remote actor to execute rpc
     LOG.debug("Looking up the remote actor for route {}", msg);
     try {
-      RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, msg.getRpc(), null);
-      GetRpc rpcMsg = new GetRpc(routeId);
-      GetRpcReply rpcReply = (GetRpcReply)ActorUtil.executeLocalOperation(rpcRegistry, rpcMsg, ActorUtil.LOCAL_ASK_DURATION, ActorUtil.LOCAL_AWAIT_DURATION);
-      String remoteActorPath = rpcReply.getRoutePath();
+      // Find router
+      RpcRouter.RouteIdentifier<?,?,?> routeId = new RouteIdentifierImpl(null, msg.getRpc(), msg.getIdentifier());
+      RpcRegistry.Messages.FindRouters rpcMsg = new RpcRegistry.Messages.FindRouters(routeId);
+      RpcRegistry.Messages.FindRoutersReply rpcReply =
+          (RpcRegistry.Messages.FindRoutersReply) ActorUtil.executeOperation(rpcRegistry, rpcMsg, ActorUtil.LOCAL_ASK_DURATION, ActorUtil.LOCAL_AWAIT_DURATION);
+
+      List<Pair<ActorRef, Long>> actorRefList = rpcReply.getRouterWithUpdateTime();
 
-      if(remoteActorPath == null) {
+      if(actorRefList == null || actorRefList.isEmpty()) {
         LOG.debug("No remote actor found for rpc {{}}.", msg.getRpc());
 
         getSender().tell(new ErrorResponse(
-          new IllegalStateException("No remote actor found for rpc execution of : " + msg.getRpc())), self());
+            new IllegalStateException("No remote actor found for rpc execution of : " + msg.getRpc())), self());
       } else {
+        RoutingLogic logic = new LatestEntryRoutingLogic(actorRefList);
 
         ExecuteRpc executeMsg = new ExecuteRpc(XmlUtils.inputCompositeNodeToXml(msg.getInput(), schemaContext), msg.getRpc());
-        Object operationRes = ActorUtil.executeRemoteOperation(this.context().actorSelection(remoteActorPath),
+        Object operationRes = ActorUtil.executeOperation(logic.select(),
             executeMsg, ActorUtil.REMOTE_ASK_DURATION, ActorUtil.REMOTE_AWAIT_DURATION);
 
         getSender().tell(operationRes, self());
       }
     } catch (Exception e) {
-        LOG.error(e.toString());
+        LOG.error("invokeRemoteRpc: {}", e);
         getSender().tell(new ErrorResponse(e), self());
     }
   }
 
+
+
   private void executeRpc(ExecuteRpc msg) {
     LOG.debug("Executing rpc for rpc {}", msg.getRpc());
     try {
-      Future<RpcResult<CompositeNode>> rpc = brokerSession.rpc(msg.getRpc(), XmlUtils.inputXmlToCompositeNode(msg.getRpc(), msg.getInputCompositeNode(), schemaContext));
+      Future<RpcResult<CompositeNode>> rpc = brokerSession.rpc(msg.getRpc(),
+          XmlUtils.inputXmlToCompositeNode(msg.getRpc(), msg.getInputCompositeNode(), schemaContext));
       RpcResult<CompositeNode> rpcResult = rpc != null ? rpc.get():null;
       CompositeNode result = rpcResult != null ? rpcResult.getResult() : null;
       getSender().tell(new RpcResponse(XmlUtils.outputCompositeNodeToXml(result, schemaContext)), self());
     } catch (Exception e) {
-      LOG.error(e.toString());
+      LOG.error("executeRpc: {}", e);
       getSender().tell(new ErrorResponse(e), self());
     }
   }
index f6149906692ad0e5133938068508e80364d0769e..dee98521ae9f2d56893d591b30bc30a8489d89ef 100644 (file)
@@ -10,50 +10,42 @@ package org.opendaylight.controller.remote.rpc;
 
 
 import akka.actor.ActorRef;
-import org.opendaylight.controller.remote.rpc.messages.AddRpc;
-import org.opendaylight.controller.remote.rpc.messages.RemoveRpc;
-import org.opendaylight.controller.remote.rpc.utils.ActorUtil;
+import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
+import java.util.List;
+
 public class RpcListener implements RpcRegistrationListener{
 
   private static final Logger LOG = LoggerFactory.getLogger(RpcListener.class);
   private final ActorRef rpcRegistry;
-  private final String actorPath;
 
-  public RpcListener(ActorRef rpcRegistry, String actorPath) {
+  public RpcListener(ActorRef rpcRegistry) {
     this.rpcRegistry = rpcRegistry;
-    this.actorPath = actorPath;
   }
 
   @Override
   public void onRpcImplementationAdded(QName rpc) {
     LOG.debug("Adding registration for [{}]", rpc);
-    RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, rpc, null);
-    AddRpc addRpcMsg = new AddRpc(routeId, actorPath);
-    try {
-      ActorUtil.executeLocalOperation(rpcRegistry, addRpcMsg, ActorUtil.LOCAL_ASK_DURATION, ActorUtil.LOCAL_AWAIT_DURATION);
-      LOG.debug("Route added [{}-{}]", routeId, this.actorPath);
-    } catch (Exception e) {
-      // Just logging it because Akka API throws this exception
-      LOG.error(e.toString());
-    }
-
+    RpcRouter.RouteIdentifier<?,?,?> routeId = new RouteIdentifierImpl(null, rpc, null);
+    List<RpcRouter.RouteIdentifier<?,?,?>> routeIds = new ArrayList<>();
+    routeIds.add(routeId);
+    RpcRegistry.Messages.AddOrUpdateRoutes addRpcMsg = new RpcRegistry.Messages.AddOrUpdateRoutes(routeIds);
+    rpcRegistry.tell(addRpcMsg, ActorRef.noSender());
   }
 
   @Override
   public void onRpcImplementationRemoved(QName rpc) {
     LOG.debug("Removing registration for [{}]", rpc);
-    RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, rpc, null);
-    RemoveRpc removeRpcMsg = new RemoveRpc(routeId);
-    try {
-      ActorUtil.executeLocalOperation(rpcRegistry, removeRpcMsg, ActorUtil.LOCAL_ASK_DURATION, ActorUtil.LOCAL_AWAIT_DURATION);
-    } catch (Exception e) {
-      // Just logging it because Akka API throws this exception
-      LOG.error(e.toString());
-    }
+    RpcRouter.RouteIdentifier<?,?,?> routeId = new RouteIdentifierImpl(null, rpc, null);
+    List<RpcRouter.RouteIdentifier<?,?,?>> routeIds = new ArrayList<>();
+    routeIds.add(routeId);
+    RpcRegistry.Messages.RemoveRoutes removeRpcMsg = new RpcRegistry.Messages.RemoveRoutes(routeIds);
+    rpcRegistry.tell(removeRpcMsg, ActorRef.noSender());
   }
 }
index 514a2f141daea13e5e71ec1f0f0a8acf9eadcf9d..96f24724286192131c08177943a572c45dba5a96 100644 (file)
@@ -16,8 +16,7 @@ import akka.actor.SupervisorStrategy;
 import akka.japi.Creator;
 import akka.japi.Function;
 import org.opendaylight.controller.remote.rpc.messages.UpdateSchemaContext;
-import org.opendaylight.controller.remote.rpc.registry.ClusterWrapper;
-import org.opendaylight.controller.remote.rpc.registry.RpcRegistryOld;
+import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -38,7 +37,6 @@ public class RpcManager extends AbstractUntypedActor {
   private static final Logger LOG = LoggerFactory.getLogger(RpcManager.class);
 
   private SchemaContext schemaContext;
-  private final ClusterWrapper clusterWrapper;
   private ActorRef rpcBroker;
   private ActorRef rpcRegistry;
   private final Broker.ProviderSession brokerSession;
@@ -47,9 +45,8 @@ public class RpcManager extends AbstractUntypedActor {
   private RemoteRpcImplementation rpcImplementation;
   private final RpcProvisionRegistry rpcProvisionRegistry;
 
-  private RpcManager(ClusterWrapper clusterWrapper, SchemaContext schemaContext,
+  private RpcManager(SchemaContext schemaContext,
                      Broker.ProviderSession brokerSession, RpcProvisionRegistry rpcProvisionRegistry) {
-    this.clusterWrapper = clusterWrapper;
     this.schemaContext = schemaContext;
     this.brokerSession = brokerSession;
     this.rpcProvisionRegistry = rpcProvisionRegistry;
@@ -59,12 +56,12 @@ public class RpcManager extends AbstractUntypedActor {
   }
 
 
-  public static Props props(final ClusterWrapper clusterWrapper, final SchemaContext schemaContext,
+  public static Props props(final SchemaContext schemaContext,
                             final Broker.ProviderSession brokerSession, final RpcProvisionRegistry rpcProvisionRegistry) {
     return Props.create(new Creator<RpcManager>() {
       @Override
       public RpcManager create() throws Exception {
-        return new RpcManager(clusterWrapper, schemaContext, brokerSession, rpcProvisionRegistry);
+        return new RpcManager(schemaContext, brokerSession, rpcProvisionRegistry);
       }
     });
   }
@@ -72,16 +69,19 @@ public class RpcManager extends AbstractUntypedActor {
   private void createRpcActors() {
     LOG.debug("Create rpc registry and broker actors");
 
-    rpcRegistry = getContext().actorOf(RpcRegistryOld.props(clusterWrapper), ActorConstants.RPC_REGISTRY);
+
+    rpcRegistry = getContext().actorOf(Props.create(RpcRegistry.class), ActorConstants.RPC_REGISTRY);
+
     rpcBroker = getContext().actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext), ActorConstants.RPC_BROKER);
+    RpcRegistry.Messages.SetLocalRouter localRouter = new RpcRegistry.Messages.SetLocalRouter(rpcBroker);
+    rpcRegistry.tell(localRouter, self());
   }
 
   private void startListeners() {
     LOG.debug("Registers rpc listeners");
 
-    String rpcBrokerPath = clusterWrapper.getAddress().toString() + ActorConstants.RPC_BROKER_PATH;
-    rpcListener = new RpcListener(rpcRegistry, rpcBrokerPath);
-    routeChangeListener = new RoutedRpcListener(rpcRegistry, rpcBrokerPath);
+    rpcListener = new RpcListener(rpcRegistry);
+    routeChangeListener = new RoutedRpcListener(rpcRegistry);
     rpcImplementation = new RemoteRpcImplementation(rpcBroker, schemaContext);
 
     brokerSession.addRpcRegistrationListener(rpcListener);
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/AddRoutedRpc.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/AddRoutedRpc.java
deleted file mode 100644 (file)
index fd1af2b..0000000
+++ /dev/null
@@ -1,37 +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.remote.rpc.messages;
-
-import com.google.common.base.Preconditions;
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-
-import java.io.Serializable;
-import java.util.Set;
-
-public class AddRoutedRpc implements Serializable {
-
-  private final Set<RpcRouter.RouteIdentifier<?, ?, ?>> announcements;
-  private final String actorPath;
-
-  public AddRoutedRpc(final Set<RpcRouter.RouteIdentifier<?, ?, ?>> announcements, final String actorPath) {
-    Preconditions.checkNotNull(announcements, "Route identifier should not be null");
-    Preconditions.checkNotNull(actorPath, "Actor path should not be null");
-
-    this.announcements = announcements;
-    this.actorPath = actorPath;
-  }
-
-  public Set<RpcRouter.RouteIdentifier<?, ?, ?>> getAnnouncements() {
-    return announcements;
-  }
-
-  public String getActorPath() {
-    return actorPath;
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/AddRpc.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/AddRpc.java
deleted file mode 100644 (file)
index 7eaa8f0..0000000
+++ /dev/null
@@ -1,36 +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.remote.rpc.messages;
-
-import com.google.common.base.Preconditions;
-import org.opendaylight.controller.remote.rpc.RouteIdentifierImpl;
-
-import java.io.Serializable;
-
-public class AddRpc implements Serializable {
-
-  private final RouteIdentifierImpl routeId;
-  private final String actorPath;
-
-  public AddRpc(final RouteIdentifierImpl routeId, final String actorPath) {
-    Preconditions.checkNotNull(routeId, "Route identifier should not be null");
-    Preconditions.checkNotNull(actorPath, "Actor path should not be null");
-
-    this.routeId = routeId;
-    this.actorPath = actorPath;
-  }
-
-  public RouteIdentifierImpl getRouteId() {
-    return routeId;
-  }
-
-  public String getActorPath() {
-    return actorPath;
-  }
-}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRoutedRpc.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRoutedRpc.java
deleted file mode 100644 (file)
index e8d2262..0000000
+++ /dev/null
@@ -1,29 +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.remote.rpc.messages;
-
-
-import com.google.common.base.Preconditions;
-import org.opendaylight.controller.remote.rpc.RouteIdentifierImpl;
-
-import java.io.Serializable;
-
-public class GetRoutedRpc implements Serializable {
-
-  private final RouteIdentifierImpl routeId;
-
-  public GetRoutedRpc(final RouteIdentifierImpl routeId) {
-    Preconditions.checkNotNull(routeId, "route id should not be null");
-    this.routeId = routeId;
-  }
-
-  public RouteIdentifierImpl getRouteId() {
-    return routeId;
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRoutedRpcReply.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRoutedRpcReply.java
deleted file mode 100644 (file)
index d426662..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.opendaylight.controller.remote.rpc.messages;
-
-/*
- * 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
- */
-
-import java.io.Serializable;
-
-public class GetRoutedRpcReply implements Serializable {
-
-  private final String routePath;
-
-  public GetRoutedRpcReply(final String routePath) {
-    this.routePath = routePath;
-  }
-
-  public String getRoutePath() {
-    return routePath;
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRpc.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRpc.java
deleted file mode 100644 (file)
index c1d4240..0000000
+++ /dev/null
@@ -1,27 +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.remote.rpc.messages;
-
-import com.google.common.base.Preconditions;
-import org.opendaylight.controller.remote.rpc.RouteIdentifierImpl;
-
-import java.io.Serializable;
-
-public class GetRpc implements Serializable {
-
-  private final RouteIdentifierImpl routeId;
-
-  public GetRpc(final RouteIdentifierImpl routeId) {
-    Preconditions.checkNotNull(routeId, "Route Id should not be null");
-    this.routeId = routeId;
-  }
-
-  public RouteIdentifierImpl getRouteId() {
-    return routeId;
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRpcReply.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRpcReply.java
deleted file mode 100644 (file)
index aaf089d..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.opendaylight.controller.remote.rpc.messages;
-
-/*
- * 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
- */
-
-import java.io.Serializable;
-
-public class GetRpcReply implements Serializable {
-
-  private final String routePath;
-
-  public GetRpcReply(final String routePath) {
-    this.routePath = routePath;
-  }
-
-  public String getRoutePath() {
-    return routePath;
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/InvokeRoutedRpc.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/InvokeRoutedRpc.java
deleted file mode 100644 (file)
index fd73144..0000000
+++ /dev/null
@@ -1,44 +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.remote.rpc.messages;
-
-import com.google.common.base.Preconditions;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-import java.io.Serializable;
-
-public class InvokeRoutedRpc implements Serializable {
-
-  private final QName rpc;
-  private final YangInstanceIdentifier identifier;
-  private final CompositeNode input;
-
-  public InvokeRoutedRpc(final QName rpc, final YangInstanceIdentifier identifier, final CompositeNode input) {
-    Preconditions.checkNotNull(rpc, "rpc qname should not be null");
-    Preconditions.checkNotNull(identifier, "instance identifier of routed rpc should not be null");
-    Preconditions.checkNotNull(input, "rpc input should not be null");
-
-    this.rpc = rpc;
-    this.identifier = identifier;
-    this.input = input;
-  }
-
-  public QName getRpc() {
-    return rpc;
-  }
-
-  public YangInstanceIdentifier getIdentifier() {
-    return identifier;
-  }
-
-  public CompositeNode getInput() {
-    return input;
-  }
-}
index 94b7fe40244838f6115469502af862cde4daa7cc..59d09fc41b6e783491f16a2279d1124db266da09 100644 (file)
@@ -10,19 +10,22 @@ package org.opendaylight.controller.remote.rpc.messages;
 import com.google.common.base.Preconditions;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 
 import java.io.Serializable;
 
 public class InvokeRpc implements Serializable {
 
   private final QName rpc;
+  private final YangInstanceIdentifier identifier;
   private final CompositeNode input;
 
-  public InvokeRpc(final QName rpc, final CompositeNode input) {
+  public InvokeRpc(final QName rpc, final YangInstanceIdentifier identifier, final CompositeNode input) {
     Preconditions.checkNotNull(rpc, "rpc qname should not be null");
     Preconditions.checkNotNull(input, "rpc input should not be null");
 
     this.rpc = rpc;
+    this.identifier = identifier;
     this.input = input;
   }
 
@@ -30,6 +33,10 @@ public class InvokeRpc implements Serializable {
     return rpc;
   }
 
+  public YangInstanceIdentifier getIdentifier() {
+    return identifier;
+  }
+
   public CompositeNode getInput() {
     return input;
   }
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RemoveRoutedRpc.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RemoveRoutedRpc.java
deleted file mode 100644 (file)
index b560b8c..0000000
+++ /dev/null
@@ -1,37 +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.remote.rpc.messages;
-
-import com.google.common.base.Preconditions;
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-
-import java.io.Serializable;
-import java.util.Set;
-
-public class RemoveRoutedRpc implements Serializable {
-
-  private final Set<RpcRouter.RouteIdentifier<?, ?, ?>> announcements;
-  private final String actorPath;
-
-  public RemoveRoutedRpc(final Set<RpcRouter.RouteIdentifier<?, ?, ?>> announcements, final String actorPath) {
-    Preconditions.checkNotNull(announcements, "Route identifier should not be null");
-    Preconditions.checkNotNull(actorPath, "Actor path should not be null");
-
-    this.announcements = announcements;
-    this.actorPath = actorPath;
-  }
-
-  public Set<RpcRouter.RouteIdentifier<?, ?, ?>> getAnnouncements() {
-    return announcements;
-  }
-
-  public String getActorPath() {
-    return actorPath;
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RemoveRpc.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RemoveRpc.java
deleted file mode 100644 (file)
index 289334f..0000000
+++ /dev/null
@@ -1,29 +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.remote.rpc.messages;
-
-import com.google.common.base.Preconditions;
-import org.opendaylight.controller.remote.rpc.RouteIdentifierImpl;
-
-import java.io.Serializable;
-
-public class RemoveRpc implements Serializable {
-
-  private final RouteIdentifierImpl routeId;
-
-  public RemoveRpc(final RouteIdentifierImpl routeId) {
-    Preconditions.checkNotNull(routeId, "Route Id should not be null");
-
-    this.routeId = routeId;
-  }
-
-  public RouteIdentifierImpl getRouteId() {
-    return routeId;
-  }
-}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RoutingTableData.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RoutingTableData.java
deleted file mode 100644 (file)
index c57a258..0000000
+++ /dev/null
@@ -1,34 +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.remote.rpc.messages;
-
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-
-import java.io.Serializable;
-import java.util.LinkedHashSet;
-import java.util.Map;
-
-public class RoutingTableData implements Serializable {
-  private final Map<RpcRouter.RouteIdentifier<?, ?, ?>, String> rpcMap;
-  private final Map<RpcRouter.RouteIdentifier<?, ?, ?>, LinkedHashSet<String>> routedRpcMap;
-
-  public RoutingTableData(final Map<RpcRouter.RouteIdentifier<?, ?, ?>, String> rpcMap,
-                          final Map<RpcRouter.RouteIdentifier<?, ?, ?>, LinkedHashSet<String>> routedRpcMap) {
-    this.rpcMap = rpcMap;
-    this.routedRpcMap = routedRpcMap;
-  }
-
-  public Map<RpcRouter.RouteIdentifier<?, ?, ?>, String> getRpcMap() {
-    return rpcMap;
-  }
-
-  public Map<RpcRouter.RouteIdentifier<?, ?, ?>, LinkedHashSet<String>> getRoutedRpcMap() {
-    return routedRpcMap;
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/ClusterWrapper.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/ClusterWrapper.java
deleted file mode 100644 (file)
index 4ddc2be..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.remote.rpc.registry;
-
-
-import akka.actor.Address;
-import akka.cluster.ClusterEvent;
-
-public interface ClusterWrapper {
-
-  ClusterEvent.CurrentClusterState getState();
-
-  Address getAddress();
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/ClusterWrapperImpl.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/ClusterWrapperImpl.java
deleted file mode 100644 (file)
index 89603a1..0000000
+++ /dev/null
@@ -1,35 +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.remote.rpc.registry;
-
-
-import akka.actor.ActorSystem;
-import akka.actor.Address;
-import akka.cluster.Cluster;
-import akka.cluster.ClusterEvent;
-
-
-public class ClusterWrapperImpl  implements ClusterWrapper{
-
-  private Cluster cluster;
-
-  public ClusterWrapperImpl(ActorSystem actorSystem) {
-    cluster = Cluster.get(actorSystem);
-  }
-
-  @Override
-  public ClusterEvent.CurrentClusterState getState() {
-    return cluster.state();
-  }
-
-  @Override
-  public Address getAddress() {
-    return cluster.selfAddress();
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RoutingTableOld.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RoutingTableOld.java
deleted file mode 100644 (file)
index 5951776..0000000
+++ /dev/null
@@ -1,171 +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.remote.rpc.registry;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-public class RoutingTableOld<I, R> {
-
-  private final Logger LOG = LoggerFactory.getLogger(RoutingTableOld.class);
-
-  private ConcurrentMap<I,R> globalRpcMap = new ConcurrentHashMap<>();
-  private ConcurrentMap<I, LinkedHashSet<R>> routedRpcMap = new ConcurrentHashMap<>();
-
-  public ConcurrentMap<I, R> getGlobalRpcMap() {
-    return globalRpcMap;
-  }
-
-  public ConcurrentMap<I, LinkedHashSet<R>> getRoutedRpcMap() {
-    return routedRpcMap;
-  }
-
-  public R getGlobalRoute(final I routeId) {
-    Preconditions.checkNotNull(routeId, "getGlobalRoute: routeId cannot be null!");
-    return globalRpcMap.get(routeId);
-  }
-
-  public void addGlobalRoute(final I routeId, final R route) {
-    Preconditions.checkNotNull(routeId, "addGlobalRoute: routeId cannot be null!");
-    Preconditions.checkNotNull(route, "addGlobalRoute: route cannot be null!");
-    LOG.debug("addGlobalRoute: adding  a new route with id[{}] and value [{}]", routeId, route);
-    if(globalRpcMap.putIfAbsent(routeId, route) != null) {
-      LOG.debug("A route already exist for route id [{}] ", routeId);
-    }
-  }
-
-  public void removeGlobalRoute(final I routeId) {
-    Preconditions.checkNotNull(routeId, "removeGlobalRoute: routeId cannot be null!");
-    LOG.debug("removeGlobalRoute: removing  a new route with id [{}]", routeId);
-    globalRpcMap.remove(routeId);
-  }
-
-  public Set<R> getRoutedRpc(final I routeId) {
-    Preconditions.checkNotNull(routeId, "getRoutes: routeId cannot be null!");
-    Set<R> routes = routedRpcMap.get(routeId);
-
-    if (routes == null) {
-      return Collections.emptySet();
-    }
-
-    return ImmutableSet.copyOf(routes);
-  }
-
-  public R getLastAddedRoutedRpc(final I routeId) {
-
-    Set<R> routes = getRoutedRpc(routeId);
-
-    if (routes.isEmpty()) {
-      return null;
-    }
-
-    R route = null;
-    Iterator<R> iter = routes.iterator();
-    while (iter.hasNext()) {
-      route = iter.next();
-    }
-
-    return route;
-  }
-
-  public void addRoutedRpc(final I routeId, final R route)   {
-    Preconditions.checkNotNull(routeId, "addRoute: routeId cannot be null");
-    Preconditions.checkNotNull(route, "addRoute: route cannot be null");
-    LOG.debug("addRoute: adding a route with k/v [{}/{}]", routeId, route);
-    threadSafeAdd(routeId, route);
-  }
-
-  public void addRoutedRpcs(final Set<I> routeIds, final R route) {
-    Preconditions.checkNotNull(routeIds, "addRoutes: routeIds must not be null");
-    for (I routeId : routeIds){
-      addRoutedRpc(routeId, route);
-    }
-  }
-
-  public void removeRoute(final I routeId, final R route) {
-    Preconditions.checkNotNull(routeId, "removeRoute: routeId cannot be null!");
-    Preconditions.checkNotNull(route, "removeRoute: route cannot be null!");
-
-    LinkedHashSet<R> routes = routedRpcMap.get(routeId);
-    if (routes == null) {
-      return;
-    }
-    LOG.debug("removeRoute: removing  a new route with k/v [{}/{}]", routeId, route);
-    threadSafeRemove(routeId, route);
-  }
-
-  public void removeRoutes(final Set<I> routeIds, final R route) {
-    Preconditions.checkNotNull(routeIds, "removeRoutes: routeIds must not be null");
-    for (I routeId : routeIds){
-      removeRoute(routeId, route);
-    }
-  }
-
-  /**
-   * This method guarantees that no 2 thread over write each other's changes.
-   * Just so that we dont end up in infinite loop, it tries for 100 times then throw
-   */
-  private void threadSafeAdd(final I routeId, final R route) {
-
-    for (int i=0;i<100;i++){
-
-      LinkedHashSet<R> updatedRoutes = new LinkedHashSet<>();
-      updatedRoutes.add(route);
-      LinkedHashSet<R> oldRoutes = routedRpcMap.putIfAbsent(routeId, updatedRoutes);
-      if (oldRoutes == null) {
-        return;
-      }
-
-      updatedRoutes = new LinkedHashSet<>(oldRoutes);
-      updatedRoutes.add(route);
-
-      if (routedRpcMap.replace(routeId, oldRoutes, updatedRoutes)) {
-        return;
-      }
-    }
-    //the method did not already return means it failed to add route in 100 attempts
-    throw new IllegalStateException("Failed to add route [" + routeId + "]");
-  }
-
-  /**
-   * This method guarantees that no 2 thread over write each other's changes.
-   * Just so that we dont end up in infinite loop, it tries for 100 times then throw
-   */
-  private void threadSafeRemove(final I routeId, final R route) {
-    LinkedHashSet<R> updatedRoutes = null;
-    for (int i=0;i<100;i++){
-      LinkedHashSet<R> oldRoutes = routedRpcMap.get(routeId);
-
-      // if route to be deleted is the only entry in the set then remove routeId from the cache
-      if ((oldRoutes.size() == 1) && oldRoutes.contains(route)){
-        routedRpcMap.remove(routeId);
-        return;
-      }
-
-      // if there are multiple routes for this routeId, remove the route to be deleted only from the set.
-      updatedRoutes = new LinkedHashSet<>(oldRoutes);
-      updatedRoutes.remove(route);
-      if (routedRpcMap.replace(routeId, oldRoutes, updatedRoutes)) {
-        return;
-      }
-
-    }
-    //the method did not already return means it failed to remove route in 100 attempts
-    throw new IllegalStateException("Failed to remove route [" + routeId + "]");
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistryOld.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistryOld.java
deleted file mode 100644 (file)
index 96c8802..0000000
+++ /dev/null
@@ -1,203 +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.remote.rpc.registry;
-
-import akka.actor.ActorSelection;
-import akka.actor.Address;
-import akka.actor.Props;
-import akka.cluster.ClusterEvent;
-import akka.cluster.Member;
-import akka.japi.Creator;
-import org.opendaylight.controller.remote.rpc.AbstractUntypedActor;
-import org.opendaylight.controller.remote.rpc.ActorConstants;
-import org.opendaylight.controller.remote.rpc.messages.AddRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.AddRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpcReply;
-import org.opendaylight.controller.remote.rpc.messages.GetRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRpcReply;
-import org.opendaylight.controller.remote.rpc.messages.RemoveRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.RemoveRpc;
-import org.opendaylight.controller.remote.rpc.messages.RoutingTableData;
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import scala.collection.JavaConversions;
-
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-
-/**
- * This Actor maintains the routing table state and sync it with other nodes in the cluster.
- *
- * A scheduler runs after an interval of time, which pick a random member from the cluster
- * and send the current state of routing table to the member.
- *
- * when a message of routing table data is received, it gets merged with the local routing table
- * to keep the latest data.
- */
-
-public class RpcRegistryOld extends AbstractUntypedActor {
-
-  private static final Logger LOG = LoggerFactory.getLogger(RpcRegistryOld.class);
-  private RoutingTableOld<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable;
-  private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
-  private final ClusterWrapper clusterWrapper;
-  private final ScheduledFuture<?> syncScheduler;
-
-  private RpcRegistryOld(ClusterWrapper clusterWrapper){
-    this.routingTable = new RoutingTableOld<>();
-    this.clusterWrapper = clusterWrapper;
-    this.syncScheduler = scheduler.scheduleAtFixedRate(new SendRoutingTable(), 10, 10, TimeUnit.SECONDS);
-  }
-
-  public static Props props(final ClusterWrapper clusterWrapper){
-    return Props.create(new Creator<RpcRegistryOld>(){
-
-      @Override
-      public RpcRegistryOld create() throws Exception {
-        return new RpcRegistryOld(clusterWrapper);
-      }
-    });
-  }
-
-  @Override
-  protected void handleReceive(Object message) throws Exception {
-    LOG.debug("Received message {}", message);
-    if(message instanceof RoutingTableData) {
-      syncRoutingTable((RoutingTableData) message);
-    } else if(message instanceof GetRoutedRpc) {
-      getRoutedRpc((GetRoutedRpc) message);
-    } else if(message instanceof GetRpc) {
-      getRpc((GetRpc) message);
-    } else if(message instanceof AddRpc) {
-      addRpc((AddRpc) message);
-    } else if(message instanceof RemoveRpc) {
-      removeRpc((RemoveRpc) message);
-    } else if(message instanceof AddRoutedRpc) {
-      addRoutedRpc((AddRoutedRpc) message);
-    } else if(message instanceof RemoveRoutedRpc) {
-      removeRoutedRpc((RemoveRoutedRpc) message);
-    }
-  }
-
-  private void getRoutedRpc(GetRoutedRpc rpcMsg){
-    LOG.debug("Get latest routed Rpc location from routing table {}", rpcMsg);
-    String remoteActorPath = routingTable.getLastAddedRoutedRpc(rpcMsg.getRouteId());
-    GetRoutedRpcReply routedRpcReply = new GetRoutedRpcReply(remoteActorPath);
-
-    getSender().tell(routedRpcReply, self());
-  }
-
-  private void getRpc(GetRpc rpcMsg) {
-    LOG.debug("Get global Rpc location from routing table {}", rpcMsg);
-    String remoteActorPath = routingTable.getGlobalRoute(rpcMsg.getRouteId());
-    GetRpcReply rpcReply = new GetRpcReply(remoteActorPath);
-
-    getSender().tell(rpcReply, self());
-  }
-
-  private void addRpc(AddRpc rpcMsg) {
-    LOG.debug("Add Rpc to routing table {}", rpcMsg);
-    routingTable.addGlobalRoute(rpcMsg.getRouteId(), rpcMsg.getActorPath());
-
-    getSender().tell("Success", self());
-  }
-
-  private void removeRpc(RemoveRpc rpcMsg) {
-    LOG.debug("Removing Rpc to routing table {}", rpcMsg);
-    routingTable.removeGlobalRoute(rpcMsg.getRouteId());
-
-    getSender().tell("Success", self());
-  }
-
-  private void addRoutedRpc(AddRoutedRpc rpcMsg) {
-    routingTable.addRoutedRpcs(rpcMsg.getAnnouncements(), rpcMsg.getActorPath());
-    getSender().tell("Success", self());
-  }
-
-  private void removeRoutedRpc(RemoveRoutedRpc rpcMsg) {
-    routingTable.removeRoutes(rpcMsg.getAnnouncements(), rpcMsg.getActorPath());
-    getSender().tell("Success", self());
-  }
-
-  private void syncRoutingTable(RoutingTableData routingTableData) {
-    LOG.debug("Syncing routing table {}", routingTableData);
-
-    Map<RpcRouter.RouteIdentifier<?, ?, ?>, String> newRpcMap = routingTableData.getRpcMap();
-    Set<RpcRouter.RouteIdentifier<?, ?, ?>> routeIds = newRpcMap.keySet();
-    for(RpcRouter.RouteIdentifier<?, ?, ?> routeId : routeIds) {
-      routingTable.addGlobalRoute(routeId, newRpcMap.get(routeId));
-    }
-
-    Map<RpcRouter.RouteIdentifier<?, ?, ?>, LinkedHashSet<String>> newRoutedRpcMap =
-        routingTableData.getRoutedRpcMap();
-    routeIds = newRoutedRpcMap.keySet();
-
-    for(RpcRouter.RouteIdentifier<?, ?, ?> routeId : routeIds) {
-      Set<String> routeAddresses = newRoutedRpcMap.get(routeId);
-      for(String routeAddress : routeAddresses) {
-        routingTable.addRoutedRpc(routeId, routeAddress);
-      }
-    }
-  }
-
-  private ActorSelection getRandomRegistryActor() {
-    ClusterEvent.CurrentClusterState clusterState = clusterWrapper.getState();
-    ActorSelection actor = null;
-    Set<Member> members = JavaConversions.asJavaSet(clusterState.members());
-    int memberSize = members.size();
-    // Don't select yourself
-    if(memberSize > 1) {
-      Address currentNodeAddress = clusterWrapper.getAddress();
-      int index = new Random().nextInt(memberSize);
-      int i = 0;
-      // keeping previous member, in case when random index member is same as current actor
-      // and current actor member is last in set
-      Member previousMember = null;
-      for(Member member : members){
-        if(i == index-1) {
-          previousMember = member;
-        }
-        if(i == index) {
-          if(!currentNodeAddress.equals(member.address())) {
-            actor = this.context().actorSelection(member.address() + ActorConstants.RPC_REGISTRY_PATH);
-            break;
-          } else if(index < memberSize-1){ // pick the next element in the set
-            index++;
-          }
-        }
-        i++;
-      }
-      if(actor == null && previousMember != null) {
-        actor = this.context().actorSelection(previousMember.address() + ActorConstants.RPC_REGISTRY_PATH);
-      }
-    }
-    return actor;
-  }
-
-  private class SendRoutingTable implements Runnable {
-
-    @Override
-    public void run() {
-      RoutingTableData routingTableData =
-          new RoutingTableData(routingTable.getGlobalRpcMap(), routingTable.getRoutedRpcMap());
-      LOG.debug("Sending routing table for sync {}", routingTableData);
-      ActorSelection actor = getRandomRegistryActor();
-      if(actor != null) {
-        actor.tell(routingTableData, self());
-      }
-    }
-  }
-}
index 8f60eabf5f98431bdb05229856b4828c20b4f0ad..b7b2216a08b0293fccc733836355ed8e4bd5767a 100644 (file)
@@ -9,7 +9,6 @@
 package org.opendaylight.controller.remote.rpc.utils;
 
 import akka.actor.ActorRef;
-import akka.actor.ActorSelection;
 import akka.util.Timeout;
 import scala.concurrent.Await;
 import scala.concurrent.Future;
@@ -36,27 +35,13 @@ public class ActorUtil {
    * @param awaitDuration
    * @return The response of the operation
    */
-  public static Object executeLocalOperation(ActorRef actor, Object message,
-                                      FiniteDuration askDuration, FiniteDuration awaitDuration) throws Exception{
+  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);
   }
 
-  /**
-   * Execute an operation on a remote actor and wait for it's response
-   * @param actor
-   * @param message
-   * @param askDuration
-   * @param awaitDuration
-   * @return
-   */
-  public static Object executeRemoteOperation(ActorSelection actor, Object message,
-                                              FiniteDuration askDuration, FiniteDuration awaitDuration) throws Exception{
-    Future<Object> future =
-        ask(actor, message, new Timeout(askDuration));
-      return Await.result(future, awaitDuration);
-  }
 
 }
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/LatestEntryRoutingLogic.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/LatestEntryRoutingLogic.java
new file mode 100644 (file)
index 0000000..f01baf0
--- /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 org.opendaylight.controller.remote.rpc.utils;
+
+import akka.actor.ActorRef;
+import akka.japi.Pair;
+import com.google.common.base.Preconditions;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * This class will return First Entry
+ */
+public class LatestEntryRoutingLogic implements RoutingLogic{
+
+  private SortedSet<Pair<ActorRef, Long>> actorRefSet;
+
+  public LatestEntryRoutingLogic(Collection<Pair<ActorRef, Long>> entries) {
+    Preconditions.checkNotNull(entries, "Entries should not be null");
+    Preconditions.checkArgument(!entries.isEmpty(), "Entries collection should not be empty");
+
+    actorRefSet = new TreeSet<>(new LatestEntryComparator());
+    actorRefSet.addAll(entries);
+  }
+
+  @Override
+  public ActorRef select() {
+    return actorRefSet.last().first();
+  }
+
+
+  private class LatestEntryComparator implements Comparator<Pair<ActorRef, Long>> {
+
+    @Override
+    public int compare(Pair<ActorRef, Long> o1, Pair<ActorRef, Long> o2) {
+      if(o1 == null && o2 == null) {
+        return 0;
+      }
+      if(o1 == null && o2 != null) {
+        return -1;
+      }
+      if(o1 != null && o2 == null) {
+        return 1;
+      }
+
+      return o1.second().compareTo(o2.second());
+
+    }
+
+  }
+}
+
+
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/RoutingLogic.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/RoutingLogic.java
new file mode 100644 (file)
index 0000000..4de7194
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.remote.rpc.utils;
+
+import akka.actor.ActorRef;
+
+/**
+ * This Interface is added to abstract out the way rpc execution could be
+ * routed, if more than one node in cluster is capable of executing the rpc.
+ *
+ * We can pick node randomly, round robin manner or based on last updated time etc.
+ */
+
+public interface RoutingLogic {
+
+  ActorRef select();
+}
index daac89c4c8adaef39047034138a8318e639f54c8..711ae1c48b75c794bad3cb93de12e397632bcbfd 100644 (file)
@@ -53,7 +53,6 @@ odl-cluster-rpc {
 
     cluster {
       seed-nodes = ["akka.tcp://opendaylight-cluster-rpc@127.0.0.1:2551"]
-
       auto-down-unreachable-after = 10s
     }
   }
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/ActorSystemFactoryTest.java b/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/ActorSystemFactoryTest.java
new file mode 100644 (file)
index 0000000..ed5fa6d
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.remote.rpc;
+
+
+import akka.actor.ActorSystem;
+import junit.framework.Assert;
+import org.junit.After;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ActorSystemFactoryTest {
+  ActorSystem system = null;
+
+  @Test
+  public void testActorSystemCreation(){
+    BundleContext context = mock(BundleContext.class);
+    when(context.getBundle()).thenReturn(mock(Bundle.class));
+    ActorSystemFactory.createInstance(context);
+    system = ActorSystemFactory.getInstance();
+    Assert.assertNotNull(system);
+    // Check illegal state exception
+
+    try {
+      ActorSystemFactory.createInstance(context);
+      fail("Illegal State exception should be thrown, while creating actor system second time");
+    } catch (IllegalStateException e) {
+    }
+  }
+
+  @After
+  public void cleanup() throws InterruptedException {
+    if(system != null) {
+      system.shutdown();
+    }
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/RemoteRpcProviderTest.java b/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/RemoteRpcProviderTest.java
new file mode 100644 (file)
index 0000000..17ad237
--- /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.remote.rpc;
+
+
+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.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+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;
+import static org.mockito.Mockito.when;
+
+public class RemoteRpcProviderTest {
+
+  static ActorSystem system;
+
+
+  @BeforeClass
+  public static void setup() throws InterruptedException {
+    system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("odl-cluster"));
+  }
+
+  @AfterClass
+  public static void teardown() {
+    JavaTestKit.shutdownActorSystem(system);
+    system = null;
+  }
+
+  @Test
+  public void testRemoteRpcProvider() throws Exception {
+    RemoteRpcProvider rpcProvider = new RemoteRpcProvider(system, mock(RpcProvisionRegistry.class));
+    Broker.ProviderSession session = mock(Broker.ProviderSession.class);
+    SchemaService schemaService = mock(SchemaService.class);
+    when(schemaService.getGlobalContext()). thenReturn(mock(SchemaContext.class));
+    when(session.getService(SchemaService.class)).thenReturn(schemaService);
+    rpcProvider.onSessionInitiated(session);
+    ActorRef actorRef = Await.result(system.actorSelection(ActorConstants.RPC_MANAGER_PATH).resolveOne(Duration.create(1, TimeUnit.SECONDS)),
+        Duration.create(2, TimeUnit.SECONDS));
+    Assert.assertTrue(actorRef.path().toString().contains(ActorConstants.RPC_MANAGER_PATH));
+  }
+
+
+
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/RouteRpcListenerTest.java b/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/RouteRpcListenerTest.java
new file mode 100644 (file)
index 0000000..9b6215a
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.remote.rpc;
+
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.testkit.JavaTestKit;
+import com.typesafe.config.ConfigFactory;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.impl.routing.RoutingUtils;
+import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
+import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+public class RouteRpcListenerTest {
+
+  static ActorSystem system;
+
+
+  @BeforeClass
+  public static void setup() throws InterruptedException {
+    system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("odl-cluster"));
+  }
+
+  @AfterClass
+  public static void teardown() {
+    JavaTestKit.shutdownActorSystem(system);
+    system = null;
+  }
+
+  @Test
+  public void testRouteAdd() throws URISyntaxException, InterruptedException {
+    new JavaTestKit(system) {
+      {
+        // Test announcements
+        JavaTestKit probeReg = new JavaTestKit(system);
+        ActorRef rpcRegistry = probeReg.getRef();
+
+        RoutedRpcListener rpcListener = new RoutedRpcListener(rpcRegistry);
+
+        QName qName = new QName(new URI("actor2"), "actor2");
+        RpcRoutingContext context = RpcRoutingContext.create(qName, qName);
+        YangInstanceIdentifier identifier = YangInstanceIdentifier.create(new YangInstanceIdentifier.NodeIdentifier(qName));
+        rpcListener.onRouteChange(RoutingUtils.announcementChange(context, identifier));
+
+        probeReg.expectMsgClass(RpcRegistry.Messages.AddOrUpdateRoutes.class);
+      }};
+  }
+
+  @Test
+  public void testRouteRemove() throws URISyntaxException, InterruptedException {
+    new JavaTestKit(system) {
+      {
+        // Test announcements
+        JavaTestKit probeReg = new JavaTestKit(system);
+        ActorRef rpcRegistry = probeReg.getRef();
+
+        RoutedRpcListener rpcListener = new RoutedRpcListener(rpcRegistry);
+
+        QName qName = new QName(new URI("actor2"), "actor2");
+        RpcRoutingContext context = RpcRoutingContext.create(qName, qName);
+        YangInstanceIdentifier identifier = YangInstanceIdentifier.create(new YangInstanceIdentifier.NodeIdentifier(qName));
+        rpcListener.onRouteChange(RoutingUtils.removalChange(context, identifier));
+
+        probeReg.expectMsgClass(RpcRegistry.Messages.RemoveRoutes.class);
+      }};
+  }
+}
index 55aa1d6c871d252d0a89ce1772fd078e45cac101..d9a3b6a414f1666dfa3b062cf7faa54c0baed8c0 100644 (file)
@@ -11,23 +11,21 @@ package org.opendaylight.controller.remote.rpc;
 
 import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
+import akka.japi.Pair;
 import akka.testkit.JavaTestKit;
 import com.google.common.util.concurrent.Futures;
+import com.typesafe.config.ConfigFactory;
 import junit.framework.Assert;
 import org.junit.AfterClass;
+import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.Mockito;
-import org.opendaylight.controller.remote.rpc.messages.AddRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.AddRpc;
 import org.opendaylight.controller.remote.rpc.messages.ErrorResponse;
-import org.opendaylight.controller.remote.rpc.messages.InvokeRoutedRpc;
 import org.opendaylight.controller.remote.rpc.messages.InvokeRpc;
 import org.opendaylight.controller.remote.rpc.messages.RpcResponse;
-import org.opendaylight.controller.remote.rpc.registry.ClusterWrapper;
-import org.opendaylight.controller.remote.rpc.registry.RpcRegistryOld;
+import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
 import org.opendaylight.controller.sal.common.util.Rpcs;
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcError;
@@ -35,7 +33,6 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.ModifyAction;
 import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
@@ -43,8 +40,7 @@ import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.List;
 import java.util.concurrent.Future;
 
 import static org.mockito.Mockito.mock;
@@ -52,31 +48,50 @@ import static org.mockito.Mockito.when;
 
 public class RpcBrokerTest {
 
-  static ActorSystem system;
+  static ActorSystem node1;
+  static ActorSystem node2;
+  private ActorRef rpcBroker1;
+  private JavaTestKit probeReg1;
+  private ActorRef rpcBroker2;
+  private JavaTestKit probeReg2;
+  private Broker.ProviderSession brokerSession;
 
 
   @BeforeClass
-  public static void setup() {
-    system = ActorSystem.create();
+  public static void setup() throws InterruptedException {
+    node1 = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("memberA"));
+    node2 = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("memberB"));
   }
 
   @AfterClass
   public static void teardown() {
-    JavaTestKit.shutdownActorSystem(system);
-    system = null;
+    JavaTestKit.shutdownActorSystem(node1);
+    JavaTestKit.shutdownActorSystem(node2);
+    node1 = null;
+    node2 = null;
   }
 
+  @Before
+  public void createActor() {
+    brokerSession = Mockito.mock(Broker.ProviderSession.class);
+    SchemaContext schemaContext = mock(SchemaContext.class);
+    probeReg1 = new JavaTestKit(node1);
+    rpcBroker1 = node1.actorOf(RpcBroker.props(brokerSession, probeReg1.getRef(), schemaContext));
+    probeReg2 = new JavaTestKit(node2);
+    rpcBroker2 = node2.actorOf(RpcBroker.props(brokerSession, probeReg2.getRef(), schemaContext));
+
+  }
   @Test
-  public void testInvokeRpcError() throws URISyntaxException {
-    new JavaTestKit(system) {{
-      ActorRef rpcRegistry = system.actorOf(RpcRegistryOld.props(Mockito.mock(ClusterWrapper.class)));
-      Broker.ProviderSession brokerSession = Mockito.mock(Broker.ProviderSession.class);
-      SchemaContext schemaContext = mock(SchemaContext.class);
-      ActorRef rpcBroker = system.actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext));
+  public void testInvokeRpcError() throws Exception {
+    new JavaTestKit(node1) {{
       QName rpc = new QName(new URI("noactor1"), "noactor1");
       CompositeNode input = new ImmutableCompositeNode(QName.create("ns", "2013-12-09", "no child"), new ArrayList<Node<?>>(), ModifyAction.REPLACE);
-      InvokeRpc invokeMsg = new InvokeRpc(rpc, input);
-      rpcBroker.tell(invokeMsg, getRef());
+
+
+      InvokeRpc invokeMsg = new InvokeRpc(rpc, null, input);
+      rpcBroker1.tell(invokeMsg, getRef());
+      probeReg1.expectMsgClass(RpcRegistry.Messages.FindRouters.class);
+      probeReg1.reply(new RpcRegistry.Messages.FindRoutersReply(new ArrayList<Pair<ActorRef, Long>>()));
 
       Boolean getMsg = new ExpectMsg<Boolean>("ErrorResponse") {
         protected Boolean match(Object in) {
@@ -90,114 +105,36 @@ public class RpcBrokerTest {
       }.get(); // this extracts the received message
 
       Assert.assertTrue(getMsg);
+
     }};
   }
 
+
   /**
    * This test method invokes and executes the remote rpc
    */
 
   @Test
   public void testInvokeRpc() throws URISyntaxException {
-    new JavaTestKit(system) {{
-      ActorRef rpcRegistry = system.actorOf(RpcRegistryOld.props(mock(ClusterWrapper.class)));
-      Broker.ProviderSession brokerSession = mock(Broker.ProviderSession.class);
-      SchemaContext schemaContext = mock(SchemaContext.class);
-      ActorRef rpcBroker = system.actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext));
-      ActorRef rpcBrokerRemote = system.actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext), "actor1");
-      // Add RPC in table
-      QName rpc = new QName(new URI("actor1"), "actor1");
-      RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, rpc, null);
-      final String route = rpcBrokerRemote.path().toString();
-      AddRpc rpcMsg = new AddRpc(routeId, route);
-      rpcRegistry.tell(rpcMsg, getRef());
-      expectMsgEquals(duration("2 second"), "Success");
-
+    new JavaTestKit(node1) {{
+      QName rpc = new QName(new URI("noactor1"), "noactor1");
       // invoke rpc
       CompositeNode input = new ImmutableCompositeNode(QName.create("ns", "2013-12-09", "child1"), new ArrayList<Node<?>>(), ModifyAction.REPLACE);
-      CompositeNode invokeRpcResult = mock(CompositeNode.class);
-      Collection<RpcError> errors = new ArrayList<>();
-      RpcResult<CompositeNode> result = Rpcs.getRpcResult(true, invokeRpcResult, errors);
-      Future<RpcResult<CompositeNode>> rpcResult = Futures.immediateFuture(result);
-      when(brokerSession.rpc(rpc, input)).thenReturn(rpcResult);
-      InvokeRpc invokeMsg = new InvokeRpc(rpc, input);
-      rpcBroker.tell(invokeMsg, getRef());
-
-      //verify response msg
-      Boolean getMsg = new ExpectMsg<Boolean>("RpcResponse") {
-        protected Boolean match(Object in) {
-          if (in instanceof RpcResponse) {
-            return true;
-          } else {
-            throw noMatch();
-          }
-        }
-      }.get(); // this extracts the received message
-
-      Assert.assertTrue(getMsg);
-    }};
-  }
-
-  @Test
-  public void testInvokeRoutedRpcError() throws URISyntaxException {
-    new JavaTestKit(system) {{
-      ActorRef rpcRegistry = system.actorOf(RpcRegistryOld.props(Mockito.mock(ClusterWrapper.class)));
-      Broker.ProviderSession brokerSession = Mockito.mock(Broker.ProviderSession.class);
-      SchemaContext schemaContext = mock(SchemaContext.class);
-      ActorRef rpcBroker = system.actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext));
-      QName rpc = new QName(new URI("actor1"), "actor1");
-      CompositeNode input = new ImmutableCompositeNode(QName.create("ns", "2013-12-09", "child1"), new ArrayList<Node<?>>(), ModifyAction.REPLACE);
-      InvokeRoutedRpc invokeMsg = new InvokeRoutedRpc(rpc, YangInstanceIdentifier.create(new YangInstanceIdentifier.NodeIdentifier(rpc)), input);
-      rpcBroker.tell(invokeMsg, getRef());
+      InvokeRpc invokeMsg = new InvokeRpc(rpc, null, input);
+      rpcBroker1.tell(invokeMsg, getRef());
 
-      Boolean getMsg = new ExpectMsg<Boolean>("ErrorResponse") {
-        protected Boolean match(Object in) {
-          if (in instanceof ErrorResponse) {
-            ErrorResponse reply = (ErrorResponse)in;
-            return "No remote actor found for rpc execution.".equals(reply.getException().getMessage());
-          } else {
-            throw noMatch();
-          }
-        }
-      }.get(); // this extracts the received message
-
-      Assert.assertTrue(getMsg);
-    }};
-  }
+      probeReg1.expectMsgClass(RpcRegistry.Messages.FindRouters.class);
+      List<Pair<ActorRef, Long>> routerList = new ArrayList<Pair<ActorRef, Long>>();
 
-  /**
-   * This test method invokes and executes the remote routed rpc
-   */
+      routerList.add(new Pair<ActorRef, Long>(rpcBroker2, 200L));
 
-  @Test
-  public void testInvokeRoutedRpc() throws URISyntaxException {
-    new JavaTestKit(system) {{
-      ActorRef rpcRegistry = system.actorOf(RpcRegistryOld.props(mock(ClusterWrapper.class)));
-      Broker.ProviderSession brokerSession = mock(Broker.ProviderSession.class);
-      SchemaContext schemaContext = mock(SchemaContext.class);
-      ActorRef rpcBroker = system.actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext));
-      ActorRef rpcBrokerRemote = system.actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext), "actor2");
-      // Add Routed RPC in table
-      QName rpc = new QName(new URI("actor2"), "actor2");
-      YangInstanceIdentifier identifier = YangInstanceIdentifier.create(new YangInstanceIdentifier.NodeIdentifier(rpc));
-      RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, rpc, identifier);
-      final String route = rpcBrokerRemote.path().toString();
-      Set<RpcRouter.RouteIdentifier<?, ?, ?>> routeIds = new HashSet<>();
-      routeIds.add(routeId);
-
-      AddRoutedRpc rpcMsg = new AddRoutedRpc(routeIds, route);
-      rpcRegistry.tell(rpcMsg, getRef());
-      expectMsgEquals(duration("2 second"), "Success");
+      probeReg1.reply(new RpcRegistry.Messages.FindRoutersReply(routerList));
 
-      // invoke rpc
-      CompositeNode input = new ImmutableCompositeNode(QName.create("ns", "2013-12-09", "child1"), new ArrayList<Node<?>>(), ModifyAction.REPLACE);
       CompositeNode invokeRpcResult = mock(CompositeNode.class);
       Collection<RpcError> errors = new ArrayList<>();
       RpcResult<CompositeNode> result = Rpcs.getRpcResult(true, invokeRpcResult, errors);
       Future<RpcResult<CompositeNode>> rpcResult = Futures.immediateFuture(result);
       when(brokerSession.rpc(rpc, input)).thenReturn(rpcResult);
-      InvokeRoutedRpc invokeMsg = new InvokeRoutedRpc(rpc, identifier, input);
-      rpcBroker.tell(invokeMsg, getRef());
 
       //verify response msg
       Boolean getMsg = new ExpectMsg<Boolean>("RpcResponse") {
@@ -213,5 +150,4 @@ public class RpcBrokerTest {
       Assert.assertTrue(getMsg);
     }};
   }
-
 }
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/RpcListenerTest.java b/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/RpcListenerTest.java
new file mode 100644 (file)
index 0000000..7b5a968
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.remote.rpc;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.testkit.JavaTestKit;
+import com.typesafe.config.ConfigFactory;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
+import org.opendaylight.yangtools.yang.common.QName;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+public class RpcListenerTest {
+
+  static ActorSystem system;
+
+
+  @BeforeClass
+  public static void setup() throws InterruptedException {
+    system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("odl-cluster"));
+  }
+
+  @AfterClass
+  public static void teardown() {
+    JavaTestKit.shutdownActorSystem(system);
+    system = null;
+  }
+
+  @Test
+  public void testRpcAdd() throws URISyntaxException {
+    new JavaTestKit(system) {
+      {
+        JavaTestKit probeReg = new JavaTestKit(system);
+        ActorRef rpcRegistry = probeReg.getRef();
+
+        RpcListener rpcListener = new RpcListener(rpcRegistry);
+
+        QName qName = new QName(new URI("actor2"), "actor2");
+
+        rpcListener.onRpcImplementationAdded(qName);
+        probeReg.expectMsgClass(RpcRegistry.Messages.AddOrUpdateRoutes.class);
+      }};
+
+  }
+
+  @Test
+  public void testRpcRemove() throws URISyntaxException {
+    new JavaTestKit(system) {
+      {
+        JavaTestKit probeReg = new JavaTestKit(system);
+        ActorRef rpcRegistry = probeReg.getRef();
+
+        RpcListener rpcListener = new RpcListener(rpcRegistry);
+
+        QName qName = new QName(new URI("actor2"), "actor2");
+
+        rpcListener.onRpcImplementationRemoved(qName);
+        probeReg.expectMsgClass(RpcRegistry.Messages.RemoveRoutes.class);
+      }};
+
+  }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/RoutingTableOldTest.java b/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/RoutingTableOldTest.java
deleted file mode 100644 (file)
index 524a912..0000000
+++ /dev/null
@@ -1,211 +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.remote.rpc.registry;
-
-import junit.framework.Assert;
-import org.junit.Test;
-import org.opendaylight.controller.remote.rpc.RouteIdentifierImpl;
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.opendaylight.yangtools.yang.common.QName;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.HashSet;
-import java.util.Set;
-
-public class RoutingTableOldTest {
-
-  private RoutingTableOld<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable =
-      new RoutingTableOld<>();
-
-  @Test
-  public void addGlobalRouteNullRouteIdTest() {
-    try {
-      routingTable.addGlobalRoute(null, null);
-
-      Assert.fail("Null pointer exception was not thrown.");
-    } catch (Exception e) {
-      Assert.assertEquals(NullPointerException.class.getName(), e.getClass().getName());
-      Assert.assertEquals("addGlobalRoute: routeId cannot be null!", e.getMessage());
-    }
-  }
-
-  @Test
-  public void addGlobalRouteNullRouteTest() {
-    try {
-      QName type = new QName(new URI("actor1"), "actor1");
-      RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, type, null);
-      routingTable.addGlobalRoute(routeId, null);
-
-      Assert.fail("Null pointer exception was not thrown.");
-    } catch (Exception e) {
-      Assert.assertEquals(NullPointerException.class.getName(), e.getClass().getName());
-      Assert.assertEquals("addGlobalRoute: route cannot be null!", e.getMessage());
-    }
-  }
-
-  @Test
-  public void getGlobalRouteNullTest() {
-    try {
-      routingTable.getGlobalRoute(null);
-
-      Assert.fail("Null pointer exception was not thrown.");
-    } catch (Exception e) {
-      Assert.assertEquals(NullPointerException.class.getName(), e.getClass().getName());
-      Assert.assertEquals("getGlobalRoute: routeId cannot be null!", e.getMessage());
-    }
-  }
-
-  @Test
-  public void getGlobalRouteTest() throws URISyntaxException {
-    QName type = new QName(new URI("actor1"), "actor1");
-    RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, type, null);
-    String route = "actor1";
-
-    routingTable.addGlobalRoute(routeId, route);
-
-    String returnedRoute = routingTable.getGlobalRoute(routeId);
-
-    Assert.assertEquals(route, returnedRoute);
-
-  }
-
-  @Test
-  public void removeGlobalRouteTest() throws URISyntaxException {
-    QName type = new QName(new URI("actorRemove"), "actorRemove");
-    RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, type, null);
-    String route = "actorRemove";
-
-    routingTable.addGlobalRoute(routeId, route);
-
-    String returnedRoute = routingTable.getGlobalRoute(routeId);
-
-    Assert.assertEquals(route, returnedRoute);
-
-    routingTable.removeGlobalRoute(routeId);
-
-    String deletedRoute = routingTable.getGlobalRoute(routeId);
-
-    Assert.assertNull(deletedRoute);
-  }
-
-  @Test
-  public void addRoutedRpcNullRouteIdTest() {
-    try {
-      routingTable.addRoutedRpc(null, null);
-
-      Assert.fail("Null pointer exception was not thrown.");
-    } catch (Exception e) {
-      Assert.assertEquals(NullPointerException.class.getName(), e.getClass().getName());
-      Assert.assertEquals("addRoute: routeId cannot be null", e.getMessage());
-    }
-  }
-
-  @Test
-  public void addRoutedRpcNullRouteTest() {
-    try {
-      QName type = new QName(new URI("actor1"), "actor1");
-      RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, type, null);
-
-      routingTable.addRoutedRpc(routeId, null);
-
-      Assert.fail("Null pointer exception was not thrown.");
-    } catch (Exception e) {
-      Assert.assertEquals(NullPointerException.class.getName(), e.getClass().getName());
-      Assert.assertEquals("addRoute: route cannot be null", e.getMessage());
-    }
-  }
-
-  @Test
-  public void getRoutedRpcNullTest() {
-    try {
-      routingTable.getRoutedRpc(null);
-
-      Assert.fail("Null pointer exception was not thrown.");
-    } catch (Exception e) {
-      Assert.assertEquals(NullPointerException.class.getName(), e.getClass().getName());
-      Assert.assertEquals("getRoutes: routeId cannot be null!", e.getMessage());
-    }
-  }
-
-  @Test
-  public void getRoutedRpcTest() throws URISyntaxException {
-    QName type = new QName(new URI("actor1"), "actor1");
-    RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, type, null);
-    String route = "actor1";
-
-    routingTable.addRoutedRpc(routeId, route);
-
-    Set<String> routes = routingTable.getRoutedRpc(routeId);
-
-    Assert.assertEquals(1, routes.size());
-    Assert.assertTrue(routes.contains(route));
-
-  }
-
-  @Test
-  public void getLastRoutedRpcTest() throws URISyntaxException {
-    QName type = new QName(new URI("first1"), "first1");
-    RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, type, null);
-    String route = "first1";
-
-    routingTable.addRoutedRpc(routeId, route);
-
-    String route2 = "second1";
-    routingTable.addRoutedRpc(routeId, route2);
-
-    String latest = routingTable.getLastAddedRoutedRpc(routeId);
-    Assert.assertEquals(route2, latest);
-
-  }
-
-  @Test
-  public void removeRoutedRpcTest() throws URISyntaxException {
-    QName type = new QName(new URI("remove"), "remove");
-    RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, type, null);
-    String route = "remove";
-    routingTable.addRoutedRpc(routeId, route);
-
-    String latest = routingTable.getLastAddedRoutedRpc(routeId);
-    Assert.assertEquals(route, latest);
-
-    routingTable.removeRoute(routeId, route);
-    String removed = routingTable.getLastAddedRoutedRpc(routeId);
-    Assert.assertNull(removed);
-  }
-
-  @Test
-  public void removeRoutedRpcsTest() throws URISyntaxException {
-    QName type = new QName(new URI("remove1"), "remove1");
-    RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, type, null);
-
-    QName type2 = new QName(new URI("remove2"), "remove2");
-    RouteIdentifierImpl routeId2 = new RouteIdentifierImpl(null, type2, null);
-
-    Set<RpcRouter.RouteIdentifier<?, ?, ?>> routeIds = new HashSet<>();
-    routeIds.add(routeId);
-    routeIds.add(routeId2);
-    String route = "remove1";
-
-    routingTable.addRoutedRpcs(routeIds, route);
-    String latest1 = routingTable.getLastAddedRoutedRpc(routeId);
-    Assert.assertEquals(route, latest1);
-
-    String latest2 = routingTable.getLastAddedRoutedRpc(routeId2);
-    Assert.assertEquals(route, latest2);
-
-    routingTable.removeRoutes(routeIds, route);
-    String removed1 = routingTable.getLastAddedRoutedRpc(routeId);
-    Assert.assertNull(removed1);
-
-    String removed2 = routingTable.getLastAddedRoutedRpc(routeId2);
-    Assert.assertNull(removed2);
-  }
-
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistryOldTest.java b/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistryOldTest.java
deleted file mode 100644 (file)
index 0f711b4..0000000
+++ /dev/null
@@ -1,159 +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.remote.rpc.registry;
-
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.testkit.JavaTestKit;
-import junit.framework.Assert;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.opendaylight.controller.remote.rpc.RouteIdentifierImpl;
-import org.opendaylight.controller.remote.rpc.messages.AddRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.AddRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpcReply;
-import org.opendaylight.controller.remote.rpc.messages.GetRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRpcReply;
-import org.opendaylight.controller.remote.rpc.messages.RemoveRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.RemoveRpc;
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.opendaylight.yangtools.yang.common.QName;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.HashSet;
-import java.util.Set;
-
-public class RpcRegistryOldTest {
-
-  static ActorSystem system;
-
-
-  @BeforeClass
-  public static void setup() {
-    system = ActorSystem.create();
-  }
-
-  @AfterClass
-  public static void teardown() {
-    JavaTestKit.shutdownActorSystem(system);
-    system = null;
-  }
-
-  /**
-   This test add, read and remove an entry in global rpc
-   */
-  @Test
-  public void testGlobalRpc() throws URISyntaxException {
-    new JavaTestKit(system) {{
-      ActorRef rpcRegistry = system.actorOf(RpcRegistryOld.props(Mockito.mock(ClusterWrapper.class)));
-      QName type = new QName(new URI("actor1"), "actor1");
-      RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, type, null);
-      final String route = "actor1";
-
-      AddRpc rpcMsg = new AddRpc(routeId, route);
-      rpcRegistry.tell(rpcMsg, getRef());
-      expectMsgEquals(duration("2 second"), "Success");
-
-      GetRpc getRpc = new GetRpc(routeId);
-      rpcRegistry.tell(getRpc, getRef());
-
-      Boolean getMsg = new ExpectMsg<Boolean>("GetRpcReply") {
-        protected Boolean match(Object in) {
-          if (in instanceof GetRpcReply) {
-            GetRpcReply reply = (GetRpcReply)in;
-            return route.equals(reply.getRoutePath());
-          } else {
-            throw noMatch();
-          }
-        }
-      }.get(); // this extracts the received message
-
-      Assert.assertTrue(getMsg);
-
-      RemoveRpc removeMsg = new RemoveRpc(routeId);
-      rpcRegistry.tell(removeMsg, getRef());
-      expectMsgEquals(duration("2 second"), "Success");
-
-      rpcRegistry.tell(getRpc, getRef());
-
-      Boolean getNullMsg = new ExpectMsg<Boolean>("GetRpcReply") {
-        protected Boolean match(Object in) {
-          if (in instanceof GetRpcReply) {
-            GetRpcReply reply = (GetRpcReply)in;
-            return reply.getRoutePath() == null;
-          } else {
-            throw noMatch();
-          }
-        }
-      }.get();
-      Assert.assertTrue(getNullMsg);
-    }};
-
-  }
-
-  /**
-   This test add, read and remove an entry in routed rpc
-   */
-  @Test
-  public void testRoutedRpc() throws URISyntaxException {
-    new JavaTestKit(system) {{
-      ActorRef rpcRegistry = system.actorOf(RpcRegistryOld.props(Mockito.mock(ClusterWrapper.class)));
-      QName type = new QName(new URI("actor1"), "actor1");
-      RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, type, null);
-      final String route = "actor1";
-
-      Set<RpcRouter.RouteIdentifier<?, ?, ?>> routeIds = new HashSet<>();
-      routeIds.add(routeId);
-
-      AddRoutedRpc rpcMsg = new AddRoutedRpc(routeIds, route);
-      rpcRegistry.tell(rpcMsg, getRef());
-      expectMsgEquals(duration("2 second"), "Success");
-
-      GetRoutedRpc getRpc = new GetRoutedRpc(routeId);
-      rpcRegistry.tell(getRpc, getRef());
-
-      Boolean getMsg = new ExpectMsg<Boolean>("GetRoutedRpcReply") {
-        protected Boolean match(Object in) {
-          if (in instanceof GetRoutedRpcReply) {
-            GetRoutedRpcReply reply = (GetRoutedRpcReply)in;
-            return route.equals(reply.getRoutePath());
-          } else {
-            throw noMatch();
-          }
-        }
-      }.get(); // this extracts the received message
-
-      Assert.assertTrue(getMsg);
-
-      RemoveRoutedRpc removeMsg = new RemoveRoutedRpc(routeIds, route);
-      rpcRegistry.tell(removeMsg, getRef());
-      expectMsgEquals(duration("2 second"), "Success");
-
-      rpcRegistry.tell(getRpc, getRef());
-
-      Boolean getNullMsg = new ExpectMsg<Boolean>("GetRoutedRpcReply") {
-        protected Boolean match(Object in) {
-          if (in instanceof GetRoutedRpcReply) {
-            GetRoutedRpcReply reply = (GetRoutedRpcReply)in;
-            return reply.getRoutePath() == null;
-          } else {
-            throw noMatch();
-          }
-        }
-      }.get();
-      Assert.assertTrue(getNullMsg);
-    }};
-
-  }
-
-}
index 7e87da0f99216c706c6935164713adb4e0c58265..fd6664af9e618872eb6f8a656cc7beddb68aa0bc 100644 (file)
@@ -34,7 +34,7 @@ public class BucketStoreTest {
     @BeforeClass
     public static void setup() {
 
-        system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("unit-test"));
+        system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("odl-cluster"));
         system.actorOf(Props.create(TerminationMonitor.class), "termination-monitor");
 
         store = createStore();
index f076c136feb80d0752777988efb711766086721a..bb60ed6eec05c4151dce935d2fc198d82c98577f 100644 (file)
@@ -45,8 +45,7 @@ public class GossiperTest {
 
     @BeforeClass
     public static void setup() throws InterruptedException {
-        Thread.sleep(1000);//give some time for previous test to stop the system. Netty port conflict arises otherwise.
-        system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("unit-test"));
+        system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("odl-cluster"));
         system.actorOf(Props.create(TerminationMonitor.class), "termination-monitor");
 
         gossiper = createGossiper();
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/utils/LatestEntryRoutingLogicTest.java b/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/utils/LatestEntryRoutingLogicTest.java
new file mode 100644 (file)
index 0000000..b21f0f0
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.remote.rpc.utils;
+
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.japi.Pair;
+import akka.testkit.JavaTestKit;
+import akka.testkit.TestProbe;
+import com.typesafe.config.ConfigFactory;
+import junit.framework.Assert;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class LatestEntryRoutingLogicTest {
+
+  static ActorSystem system;
+
+  @BeforeClass
+  public static void setup() throws InterruptedException {
+    system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("odl-cluster"));
+  }
+
+  @AfterClass
+  public static void teardown() {
+    JavaTestKit.shutdownActorSystem(system);
+    system = null;
+  }
+
+  @Test
+  public void testRoutingLogic() {
+    List<Pair<ActorRef, Long>> pairList = new ArrayList<>();
+    TestProbe probe1 = new TestProbe(system);
+    TestProbe probe2 = new TestProbe(system);
+    TestProbe probe3 = new TestProbe(system);
+    ActorRef actor1 = probe1.ref();
+    ActorRef actor2 = probe2.ref();
+    ActorRef actor3 = probe3.ref();
+    pairList.add(new Pair<ActorRef, Long>(actor1, 1000L));
+    pairList.add(new Pair<ActorRef, Long>(actor2, 3000L));
+    pairList.add(new Pair<ActorRef, Long>(actor3, 2000L));
+    RoutingLogic logic = new LatestEntryRoutingLogic(pairList);
+    Assert.assertTrue(logic.select().equals(actor2));
+  }
+}
index 459eb78903b6dc09b0739b49198a71d71f05c2f2..61fab7e0fefccfd26909a8eb81e2af041d624662 100644 (file)
@@ -18,12 +18,12 @@ odl-cluster{
       log-remote-lifecycle-events = off
       netty.tcp {
         hostname = "127.0.0.1"
-        port = 2551
+        port = 2550
       }
     }
 
     cluster {
-      seed-nodes = ["akka.tcp://opendaylight-rpc@127.0.0.1:2551"]
+      seed-nodes = ["akka.tcp://opendaylight-rpc@127.0.0.1:2550"]
 
       auto-down-unreachable-after = 10s
     }
index 8dbc5b50ee5dbd8ac374ef7d1452384442923085..f11e25c046feab69fe3c41f229dfdbadd496e18d 100644 (file)
@@ -9,7 +9,6 @@ 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;
@@ -41,7 +40,6 @@ 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;
@@ -178,39 +176,31 @@ public class BrokerFacade {
     private NormalizedNode<?, ?> readDataViaTransaction(final DOMDataReadTransaction transaction,
             LogicalDatastoreType datastore, YangInstanceIdentifier path) {
         LOG.trace("Read " + datastore.name() + " via Restconf: {}", 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());
+        final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> listenableFuture =
+                                                                 transaction.read(datastore, path);
 
-            }
-            if (optional != null) {
-                if (optional.isPresent()) {
-                    return optional.get();
-                }
-            }
+        try {
+            Optional<NormalizedNode<?, ?>> optional = listenableFuture.checkedGet();
+            return optional.isPresent() ? optional.get() : null;
+        } catch(ReadFailedException e) {
+            throw new RestconfDocumentedException(e.getMessage(), e, e.getErrorList());
         }
-        return null;
     }
 
     private CheckedFuture<Void, TransactionCommitFailedException> postDataViaTransaction(
             final DOMDataReadWriteTransaction rWTransaction, final LogicalDatastoreType datastore,
             final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload, DataNormalizationOperation<?> root) {
-        ListenableFuture<Optional<NormalizedNode<?, ?>>> futureDatastoreData = rWTransaction.read(datastore, path);
+        CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> futureDatastoreData =
+                                                               rWTransaction.read(datastore, path);
         try {
-            final Optional<NormalizedNode<?, ?>> optionalDatastoreData = futureDatastoreData.get();
+            final Optional<NormalizedNode<?, ?>> optionalDatastoreData = futureDatastoreData.checkedGet();
             if (optionalDatastoreData.isPresent() && payload.equals(optionalDatastoreData.get())) {
-                String errMsg = "Post Configuration via Restconf was not executed because data already exists";
-                LOG.trace(errMsg + ":{}", path);
+                LOG.trace("Post Configuration via Restconf was not executed because data already exists :{}", path);
                 throw new RestconfDocumentedException("Data already exists for path: " + path, ErrorType.PROTOCOL,
                         ErrorTag.DATA_EXISTS);
             }
-        } catch (InterruptedException | ExecutionException e) {
-            LOG.trace("It wasn't possible to get data loaded from datastore at path " + path);
+        } catch(ReadFailedException e) {
+            LOG.warn("Error reading from datastore with path: " + path, e);
         }
 
         ensureParentsByMerge(datastore, path, rWTransaction, root);
@@ -251,27 +241,21 @@ public class BrokerFacade {
             try {
                 currentOp = currentOp.getChild(currentArg);
             } catch (DataNormalizationException e) {
-                throw new IllegalArgumentException(
-                        String.format("Invalid child encountered in path %s", normalizedPath), e);
+                throw new RestconfDocumentedException(
+                        String.format("Error normalizing data for path %s", normalizedPath), e);
             }
             currentArguments.add(currentArg);
             YangInstanceIdentifier currentPath = YangInstanceIdentifier.create(currentArguments);
 
-            final Boolean exists;
-
             try {
 
-                CheckedFuture<Boolean, ReadFailedException> future =
-                    rwTx.exists(store, currentPath);
-                exists = future.checkedGet();
+                boolean exists = rwTx.exists(store, currentPath).checkedGet();
+                if (!exists && iterator.hasNext()) {
+                    rwTx.merge(store, currentPath, currentOp.createDefault(currentArg));
+                }
             } catch (ReadFailedException e) {
                 LOG.error("Failed to read pre-existing data from store {} path {}", store, currentPath, e);
-                throw new IllegalStateException("Failed to read pre-existing data", e);
-            }
-
-
-            if (!exists && iterator.hasNext()) {
-                rwTx.merge(store, currentPath, currentOp.createDefault(currentArg));
+                throw new RestconfDocumentedException("Failed to read pre-existing data", e);
             }
         }
     }
index e3e0c3a2bdc49cbf8fca3bb8104e673fa2ea0b2c..2ceef3203c808df7414a43a2292f19d7730f8685 100644 (file)
@@ -10,11 +10,17 @@ package org.opendaylight.controller.sal.restconf.impl;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+import java.util.Collection;
 import java.util.List;
+
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Response.Status;
+
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcError;
 
 /**
  * Unchecked exception to communicate error information, as defined in the ietf restcong draft, to be sent to the
@@ -57,8 +63,8 @@ public class RestconfDocumentedException extends WebApplicationException {
     }
 
     /**
-     * Constructs an instance with an error message and exception cause. The stack trace of the exception is included in
-     * the error info.
+     * Constructs an instance with an error message and exception cause.
+     * The stack trace of the exception is included in the error info.
      *
      * @param message
      *            A string which provides a plain text string describing the error.
@@ -80,12 +86,25 @@ public class RestconfDocumentedException extends WebApplicationException {
     /**
      * Constructs an instance with the given errors.
      */
-    public RestconfDocumentedException(List<RestconfError> errors) {
-        this.errors = ImmutableList.copyOf(errors);
-        Preconditions.checkArgument(!this.errors.isEmpty(), "RestconfError list can't be empty");
+    public RestconfDocumentedException(String message, Throwable cause, List<RestconfError> errors) {
+        super(message, cause);
+        if(!errors.isEmpty()) {
+            this.errors = ImmutableList.copyOf(errors);
+        } else {
+            this.errors = ImmutableList.of(new RestconfError(RestconfError.ErrorType.APPLICATION,
+                    RestconfError.ErrorTag.OPERATION_FAILED, message));
+        }
+
         status = null;
     }
 
+    /**
+     * Constructs an instance with the given RpcErrors.
+     */
+    public RestconfDocumentedException(String message, Throwable cause, Collection<RpcError> rpcErrors) {
+        this(message, cause, convertToRestconfErrors(rpcErrors));
+    }
+
     /**
      * Constructs an instance with an HTTP status and no error information.
      *
@@ -105,6 +124,18 @@ public class RestconfDocumentedException extends WebApplicationException {
         status = null;
     }
 
+    private static List<RestconfError> convertToRestconfErrors(Collection<RpcError> rpcErrors) {
+        List<RestconfError> errorList = Lists.newArrayList();
+        if(rpcErrors != null) {
+            for (RpcError rpcError : rpcErrors) {
+                errorList.add(new RestconfError(rpcError));
+            }
+        }
+
+        return errorList;
+    }
+
+
     public List<RestconfError> getErrors() {
         return errors;
     }
index ed20bd01a5047e4d746858ff4adde4fe7de0c701..544a144987a68a77f9ec14e3c22d77cf1962fae8 100644 (file)
@@ -62,7 +62,7 @@ public class RestconfError {
         RESOURCE_DENIED("resource-denied", 409 /* Conflict */),
         ROLLBACK_FAILED("rollback-failed", 500 /* INTERNAL_SERVER_ERROR */),
         DATA_EXISTS("data-exists", 409 /* Conflict */),
-        DATA_MISSING("data-missing", 409 /* Conflict */),
+        DATA_MISSING("data-missing", 404 /* Resource Not Found */),
         OPERATION_NOT_SUPPORTED("operation-not-supported", 501 /* Not Implemented */),
         OPERATION_FAILED("operation-failed", 500 /* INTERNAL_SERVER_ERROR */),
         PARTIAL_OPERATION("partial-operation", 500 /* INTERNAL_SERVER_ERROR */),
index fac6c80564784759e08aef3db46ebada1dba69fe..b94f6a6166c47f3b1308f7dc4696341fe5ec202b 100644 (file)
@@ -21,7 +21,6 @@ import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
@@ -37,6 +36,8 @@ 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;
+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.common.impl.util.compat.DataNormalizer;
 import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
 import org.opendaylight.controller.sal.rest.api.Draft02;
@@ -52,7 +53,6 @@ import org.opendaylight.controller.sal.streams.websockets.WebSocketServer;
 import org.opendaylight.yangtools.concepts.Codec;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
@@ -609,19 +609,8 @@ public class RestconfImpl implements RestconfService {
     private void checkRpcSuccessAndThrowException(final RpcResult<CompositeNode> rpcResult) {
         if (rpcResult.isSuccessful() == false) {
 
-            Collection<RpcError> rpcErrors = rpcResult.getErrors();
-            if (rpcErrors == null || rpcErrors.isEmpty()) {
-                throw new RestconfDocumentedException(
-                        "The operation was not successful and there were no RPC errors returned", ErrorType.RPC,
-                        ErrorTag.OPERATION_FAILED);
-            }
-
-            List<RestconfError> errorList = Lists.newArrayList();
-            for (RpcError rpcError : rpcErrors) {
-                errorList.add(new RestconfError(rpcError));
-            }
-
-            throw new RestconfDocumentedException(errorList);
+            throw new RestconfDocumentedException("The operation was not successful", null,
+                    rpcResult.getErrors());
         }
     }
 
@@ -729,18 +718,50 @@ public class RestconfImpl implements RestconfService {
                 iiWithData.getSchemaNode());
 
         YangInstanceIdentifier normalizedII;
+        if (mountPoint != null) {
+            normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(
+                    iiWithData.getInstanceIdentifier());
+        } else {
+            normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
+        }
 
-        try {
-            if (mountPoint != null) {
-                normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData
-                        .getInstanceIdentifier());
-                broker.commitConfigurationDataPut(mountPoint, normalizedII, datastoreNormalizedNode).get();
-            } else {
-                normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
-                broker.commitConfigurationDataPut(normalizedII, datastoreNormalizedNode).get();
+        /*
+         * There is a small window where another write transaction could be updating the same data
+         * simultaneously and we get an OptimisticLockFailedException. This error is likely
+         * transient and The WriteTransaction#submit API docs state that a retry will likely
+         * succeed. So we'll try again if that scenario occurs. If it fails a third time then it
+         * probably will never succeed so we'll fail in that case.
+         *
+         * By retrying we're attempting to hide the internal implementation of the data store and
+         * how it handles concurrent updates from the restconf client. The client has instructed us
+         * to put the data and we should make every effort to do so without pushing optimistic lock
+         * failures back to the client and forcing them to handle it via retry (and having to
+         * document the behavior).
+         */
+        int tries = 2;
+        while(true) {
+            try {
+                if (mountPoint != null) {
+                    broker.commitConfigurationDataPut(mountPoint, normalizedII,
+                            datastoreNormalizedNode).checkedGet();
+                } else {
+                    broker.commitConfigurationDataPut(normalizedII,
+                            datastoreNormalizedNode).checkedGet();
+                }
+
+                break;
+            } catch (TransactionCommitFailedException e) {
+                if(e instanceof OptimisticLockFailedException) {
+                    if(--tries <= 0) {
+                        LOG.debug("Got OptimisticLockFailedException on last try - failing");
+                        throw new RestconfDocumentedException(e.getMessage(), e, e.getErrorList());
+                    }
+
+                    LOG.debug("Got OptimisticLockFailedException - trying again");
+                } else {
+                    throw new RestconfDocumentedException(e.getMessage(), e, e.getErrorList());
+                }
             }
-        } catch (Exception e) {
-            throw new RestconfDocumentedException("Error updating data", e);
         }
 
         return Response.status(Status.OK).build();
@@ -852,6 +873,8 @@ public class RestconfImpl implements RestconfService {
                 normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
                 broker.commitConfigurationDataPost(normalizedII, datastoreNormalizedData);
             }
+        } catch(RestconfDocumentedException e) {
+            throw e;
         } catch (Exception e) {
             throw new RestconfDocumentedException("Error creating data", e);
         }
@@ -898,6 +921,8 @@ public class RestconfImpl implements RestconfService {
                 normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
                 broker.commitConfigurationDataPost(normalizedII, datastoreNormalizedData);
             }
+        } catch(RestconfDocumentedException e) {
+            throw e;
         } catch (Exception e) {
             throw new RestconfDocumentedException("Error creating data", e);
         }
@@ -1156,8 +1181,9 @@ public class RestconfImpl implements RestconfService {
 
     private CompositeNode normalizeNode(final Node<?> node, final DataSchemaNode schema, final DOMMountPoint mountPoint) {
         if (schema == null) {
-            QName nodeType = node == null ? null : node.getNodeType();
-            String localName = nodeType == null ? null : nodeType.getLocalName();
+            String localName = node == null ? null :
+                    node instanceof NodeWrapper ? ((NodeWrapper<?>)node).getLocalName() :
+                    node.getNodeType().getLocalName();
 
             throw new RestconfDocumentedException("Data schema node was not found for " + localName,
                     ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
index 500baafab3476cba31ed159ec7b87c7cca66cdd5..2f045ce381ca0572cbeff4ad43147834fb59d2cf 100644 (file)
@@ -146,7 +146,7 @@ public class InvokeRpcMethodTest {
             restconfImpl.invokeRpc("toaster:cancel-toast", "", uriInfo);
             fail("Expected an exception to be thrown.");
         } catch (RestconfDocumentedException e) {
-            verifyRestconfDocumentedException(e, 0, ErrorType.RPC, ErrorTag.OPERATION_FAILED,
+            verifyRestconfDocumentedException(e, 0, ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED,
                     Optional.<String> absent(), Optional.<String> absent());
         }
     }
index 3284546dcbb32806563b2bb8b0959d7a3063a10d..3591bfb22bec85f90ef94215a30fdfbef5705784 100644 (file)
@@ -16,19 +16,23 @@ import static org.mockito.Mockito.when;
 
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.CheckedFuture;
+
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 import java.net.URISyntaxException;
+
 import javax.ws.rs.client.Entity;
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
+
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
 import org.junit.BeforeClass;
 import org.junit.Test;
+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.api.DOMMountPoint;
 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
@@ -158,6 +162,36 @@ public class RestPutOperationTest extends JerseyTest {
         assertEquals(200, put(uri, MediaType.APPLICATION_XML, xmlData3));
     }
 
+    @Test
+    public void putWithOptimisticLockFailedException() throws UnsupportedEncodingException {
+
+        String uri = "/config/ietf-interfaces:interfaces/interface/eth0";
+
+        doThrow(OptimisticLockFailedException.class).
+            when(brokerFacade).commitConfigurationDataPut(
+                any(YangInstanceIdentifier.class), any(NormalizedNode.class));
+
+        assertEquals(500, put(uri, MediaType.APPLICATION_XML, xmlData));
+
+        doThrow(OptimisticLockFailedException.class).doReturn(mock(CheckedFuture.class)).
+            when(brokerFacade).commitConfigurationDataPut(
+                any(YangInstanceIdentifier.class), any(NormalizedNode.class));
+
+        assertEquals(200, put(uri, MediaType.APPLICATION_XML, xmlData));
+    }
+
+    @Test
+    public void putWithTransactionCommitFailedException() throws UnsupportedEncodingException {
+
+        String uri = "/config/ietf-interfaces:interfaces/interface/eth0";
+
+        doThrow(TransactionCommitFailedException.class).
+            when(brokerFacade).commitConfigurationDataPut(
+                any(YangInstanceIdentifier.class), any(NormalizedNode.class));
+
+        assertEquals(500, put(uri, MediaType.APPLICATION_XML, xmlData));
+    }
+
     private int put(String uri, String mediaType, String data) throws UnsupportedEncodingException {
         return target(uri).request(mediaType).put(Entity.entity(data, mediaType)).getStatus();
     }
index b8c0270a61407a8358a741abe2515bc83395ef60..4e9c96ac3e8acef126077d7b932e737caae1e4f3 100644 (file)
@@ -374,7 +374,7 @@ public class RestconfDocumentedExceptionMapperTest extends JerseyTest {
     public void testToJsonResponseWithDataMissingErrorTag() throws Exception {
 
         testJsonResponse(new RestconfDocumentedException("mock error", ErrorType.PROTOCOL, ErrorTag.DATA_MISSING),
-                Status.CONFLICT, ErrorType.PROTOCOL, ErrorTag.DATA_MISSING, "mock error", null, null);
+                Status.NOT_FOUND, ErrorType.PROTOCOL, ErrorTag.DATA_MISSING, "mock error", null, null);
     }
 
     @Test
@@ -412,7 +412,7 @@ public class RestconfDocumentedExceptionMapperTest extends JerseyTest {
 
         List<RestconfError> errorList = Arrays.asList(new RestconfError(ErrorType.APPLICATION, ErrorTag.LOCK_DENIED,
                 "mock error1"), new RestconfError(ErrorType.RPC, ErrorTag.ROLLBACK_FAILED, "mock error2"));
-        stageMockEx(new RestconfDocumentedException(errorList));
+        stageMockEx(new RestconfDocumentedException("mock", null, errorList));
 
         Response resp = target("/operational/foo").request(MediaType.APPLICATION_JSON).get();
 
@@ -594,7 +594,7 @@ public class RestconfDocumentedExceptionMapperTest extends JerseyTest {
     public void testToXMLResponseWithDataMissingErrorTag() throws Exception {
 
         testXMLResponse(new RestconfDocumentedException("mock error", ErrorType.PROTOCOL, ErrorTag.DATA_MISSING),
-                Status.CONFLICT, ErrorType.PROTOCOL, ErrorTag.DATA_MISSING, "mock error", null, null);
+                Status.NOT_FOUND, ErrorType.PROTOCOL, ErrorTag.DATA_MISSING, "mock error", null, null);
     }
 
     @Test
@@ -651,7 +651,7 @@ public class RestconfDocumentedExceptionMapperTest extends JerseyTest {
 
         List<RestconfError> errorList = Arrays.asList(new RestconfError(ErrorType.APPLICATION, ErrorTag.LOCK_DENIED,
                 "mock error1"), new RestconfError(ErrorType.RPC, ErrorTag.ROLLBACK_FAILED, "mock error2"));
-        stageMockEx(new RestconfDocumentedException(errorList));
+        stageMockEx(new RestconfDocumentedException("mock", null, errorList));
 
         Response resp = target("/operational/foo").request(MediaType.APPLICATION_XML).get();
 
index 18311104a41f9761dd5bede15965df9625ea061b..010572de968736fabbda746d3ff5c8b101a5c433 100644 (file)
@@ -90,7 +90,7 @@ public class RestconfErrorTest {
         lookUpMap.put("resource-denied", 409);
         lookUpMap.put("rollback-failed", 500);
         lookUpMap.put("data-exists", 409);
-        lookUpMap.put("data-missing", 409);
+        lookUpMap.put("data-missing", 404);
         lookUpMap.put("operation-not-supported", 501);
         lookUpMap.put("operation-failed", 500);
         lookUpMap.put("partial-operation", 500);
index 388c78eaaf6365c77241c17cae04848680882624..5832e29a139a09ab393cbe3a603f9baec9d1cc14 100644 (file)
@@ -76,9 +76,17 @@ public final class ToasterProviderModule extends
                 dataChangeListenerRegistration.close();
                 rpcRegistration.close();
                 runtimeReg.close();
-                opendaylightToaster.close();
+                closeQuietly(opendaylightToaster);
                 log.info("Toaster provider (instance {}) torn down.", this);
             }
+
+            private void closeQuietly(final AutoCloseable resource) {
+                try {
+                    resource.close();
+                } catch (final Exception e) {
+                    log.debug("Ignoring exception while closing {}", resource, e);
+                }
+            }
         }
 
         AutoCloseable ret = new AutoCloseableToaster();
index b1db280c2472802aed2e97ce525422308eca3b12..cd9738c894554a8e609eac1acb4b9fbd9534eac9 100644 (file)
@@ -32,6 +32,9 @@ final class FlowComparator {
     }
 
     public static boolean flowEquals(Flow statsFlow, Flow storedFlow) {
+        if (statsFlow == null || storedFlow == null) {
+            return false;
+        }
         if (statsFlow.getClass() != storedFlow.getClass()) {
             return false;
         }
@@ -42,19 +45,18 @@ final class FlowComparator {
         } else if(!statsFlow.getContainerName().equals(storedFlow.getContainerName())) {
             return false;
         }
-        if (statsFlow.getMatch()== null) {
-            if (storedFlow.getMatch() != null) {
+        if (storedFlow.getPriority() == null) {
+            if (statsFlow.getPriority() != null && statsFlow.getPriority()!= 0x8000) {
                 return false;
             }
-        } //else if(!statsFlow.getMatch().equals(storedFlow.getMatch())) {
-        else if(!matchEquals(statsFlow.getMatch(), storedFlow.getMatch())) {
+        } else if(!statsFlow.getPriority().equals(storedFlow.getPriority())) {
             return false;
         }
-        if (storedFlow.getPriority() == null) {
-            if (statsFlow.getPriority() != null && statsFlow.getPriority()!= 0x8000) {
+        if (statsFlow.getMatch()== null) {
+            if (storedFlow.getMatch() != null) {
                 return false;
             }
-        } else if(!statsFlow.getPriority().equals(storedFlow.getPriority())) {
+        } else if(!matchEquals(statsFlow.getMatch(), storedFlow.getMatch())) {
             return false;
         }
         if (statsFlow.getTableId() == null) {
index 1a14de6f5d5b9049e4199ce743fc7ba95ad913e3..e92d0bd6251dbf89af9c98b175aa699d8d697994 100644 (file)
@@ -7,14 +7,20 @@
  */
 package org.opendaylight.controller.md.statistics.manager;
 
+import java.math.BigInteger;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Map.Entry;
 
 import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCookieMapping;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.nodes.node.table.FlowCookieMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.nodes.node.table.FlowCookieMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.nodes.node.table.FlowCookieMapKey;
 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;
@@ -29,6 +35,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.O
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapListBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.statistics.FlowStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.GenericStatistics;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -36,12 +43,16 @@ import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Optional;
+
 final class FlowStatsTracker extends AbstractListeningStatsTracker<FlowAndStatisticsMapList, FlowStatsEntry> {
-    private static final Logger logger = LoggerFactory.getLogger(FlowStatsTracker.class);
+    private static final Logger LOG = LoggerFactory.getLogger(FlowStatsTracker.class);
+    private static final String ALIEN_SYSTEM_FLOW_ID = "#UF$TABLE*";
     private final OpendaylightFlowStatisticsService flowStatsService;
     private FlowTableStatsTracker flowTableStats;
     private int unaccountedFlowsCounter = 1;
 
+
     FlowStatsTracker(final OpendaylightFlowStatisticsService flowStatsService, final FlowCapableContext context) {
         super(context);
         this.flowStatsService = flowStatsService;
@@ -66,15 +77,15 @@ final class FlowStatsTracker extends AbstractListeningStatsTracker<FlowAndStatis
 
         FlowStatisticsDataBuilder flowStatisticsData = new FlowStatisticsDataBuilder();
 
-        FlowBuilder flow = new FlowBuilder(map);
-        if(map.getFlowId() != null) {
-            flow.setId(new FlowId(map.getFlowId().getValue()));
+        FlowBuilder flowBuilder = new FlowBuilder(map);
+        if (map.getFlowId() != null) {
+            flowBuilder.setId(new FlowId(map.getFlowId().getValue()));
         }
-        if(map.getFlowId()!= null) {
-            flow.setKey(new FlowKey(new FlowId(map.getKey().getFlowId().getValue())));
+        if (map.getFlowId() != null) {
+            flowBuilder.setKey(new FlowKey(new FlowId(map.getKey().getFlowId().getValue())));
         }
 
-        Flow flowRule = flow.build();
+        Flow flowRule = flowBuilder.build();
 
         FlowAndStatisticsMapListBuilder stats = new FlowAndStatisticsMapListBuilder();
         stats.setByteCount(map.getByteCount());
@@ -92,76 +103,45 @@ final class FlowStatsTracker extends AbstractListeningStatsTracker<FlowAndStatis
 
         flowStatisticsData.setFlowStatistics(flowStatistics.build());
 
-        logger.debug("Flow : {}",flowRule.toString());
-        logger.debug("Statistics to augment : {}",flowStatistics.build().toString());
+        LOG.debug("Flow : {}",flowRule.toString());
+        LOG.debug("Statistics to augment : {}",flowStatistics.build().toString());
 
         InstanceIdentifier<Table> tableRef = getNodeIdentifierBuilder()
-                .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId)).toInstance();
-
-        //TODO: Not a good way to do it, need to figure out better way.
-        //TODO: major issue in any alternate approach is that flow key is incrementally assigned
-        //to the flows stored in data store.
-        // Augment same statistics to all the matching masked flow
-        Table table= (Table)trans.readConfigurationData(tableRef);
-        if(table != null){
-            for(Flow existingFlow : table.getFlow()){
-                logger.debug("Existing flow in data store : {}",existingFlow.toString());
-                if(FlowComparator.flowEquals(flowRule,existingFlow)){
-                    InstanceIdentifier<Flow> flowRef = getNodeIdentifierBuilder()
-                            .augmentation(FlowCapableNode.class)
-                            .child(Table.class, new TableKey(tableId))
-                            .child(Flow.class,existingFlow.getKey()).toInstance();
-                    flow.setKey(existingFlow.getKey());
-                    flow.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
-                    logger.debug("Found matching flow in the datastore, augmenting statistics");
-                    // Update entry with timestamp of latest response
-                    FlowStatsEntry flowStatsEntry = new FlowStatsEntry(tableId,flow.build());
-                    trans.putOperationalData(flowRef, flow.build());
-                    return flowStatsEntry;
-                }
-            }
-        }
-
-        table = (Table)trans.readOperationalData(tableRef);
-        if(table != null){
-            for(Flow existingFlow : table.getFlow()){
-                FlowStatisticsData augmentedflowStatisticsData = existingFlow.getAugmentation(FlowStatisticsData.class);
-                if(augmentedflowStatisticsData != null){
-                    FlowBuilder existingOperationalFlow = new FlowBuilder();
-                    existingOperationalFlow.fieldsFrom(augmentedflowStatisticsData.getFlowStatistics());
-                    logger.debug("Existing unaccounted flow in operational data store : {}",existingFlow.toString());
-                    if(FlowComparator.flowEquals(flowRule,existingOperationalFlow.build())){
-                        InstanceIdentifier<Flow> flowRef = getNodeIdentifierBuilder()
-                                .augmentation(FlowCapableNode.class)
-                                .child(Table.class, new TableKey(tableId))
-                                .child(Flow.class,existingFlow.getKey()).toInstance();
-                        flow.setKey(existingFlow.getKey());
-                        flow.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
-                        logger.debug("Found matching unaccounted flow in the operational datastore, augmenting statistics");
-                        // Update entry with timestamp of latest response
-                        FlowStatsEntry flowStatsEntry = new FlowStatsEntry(tableId,flow.build());
-                        trans.putOperationalData(flowRef, flow.build());
-                        return flowStatsEntry;
-                    }
-                }
+                .augmentation(FlowCapableNode.class)
+                .child(Table.class, new TableKey(tableId)).toInstance();
+
+        final FlowCookie flowCookie = flowRule.getCookie() != null
+                ? flowRule.getCookie() : new FlowCookie(BigInteger.ZERO);
+        final InstanceIdentifier<FlowCookieMap> flowCookieRef = tableRef
+                .augmentation(FlowCookieMapping.class)
+                .child(FlowCookieMap.class, new FlowCookieMapKey(flowCookie));
+
+        FlowCookieMap cookieMap = (FlowCookieMap) trans.readOperationalData(flowCookieRef);
+
+        /* find flowKey in FlowCookieMap from DataStore/OPERATIONAL */
+        Optional<FlowKey> flowKey = this.getExistFlowKey(flowRule, tableRef, trans, cookieMap);
+        if ( ! flowKey.isPresent()) {
+            /* DataStore/CONFIG For every first statistic needs to be created */
+            flowKey = this.getFlowKeyFromExistFlow(flowRule, tableRef, trans);
+            if ( ! flowKey.isPresent()) {
+                /* Alien flow */
+                flowKey = this.makeAlienFlowKey(flowRule);
             }
+            cookieMap = applyNewFlowKey(cookieMap, flowKey, flowCookie);
+            trans.putOperationalData(flowCookieRef, cookieMap);
         }
 
-        String flowKey = "#UF$TABLE*"+Short.toString(tableId)+"*"+Integer.toString(this.unaccountedFlowsCounter);
-        this.unaccountedFlowsCounter++;
-        FlowKey newFlowKey = new FlowKey(new FlowId(flowKey));
-        InstanceIdentifier<Flow> flowRef = getNodeIdentifierBuilder().augmentation(FlowCapableNode.class)
-                    .child(Table.class, new TableKey(tableId))
-                    .child(Flow.class,newFlowKey).toInstance();
-        flow.setKey(newFlowKey);
-        flow.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
-        logger.debug("Flow {} is not present in config data store, augmenting statistics as an unaccounted flow",
-                    flow.build());
+        InstanceIdentifier<Flow> flowRef = getNodeIdentifierBuilder()
+                .augmentation(FlowCapableNode.class)
+                .child(Table.class, new TableKey(tableId))
+                .child(Flow.class, flowKey.get()).toInstance();
+        flowBuilder.setKey(flowKey.get());
+        flowBuilder.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
 
         // Update entry with timestamp of latest response
-        flow.setKey(newFlowKey);
-        FlowStatsEntry flowStatsEntry = new FlowStatsEntry(tableId,flow.build());
-        trans.putOperationalData(flowRef, flow.build());
+        flowBuilder.setKey(flowKey.get());
+        FlowStatsEntry flowStatsEntry = new FlowStatsEntry(tableId, flowBuilder.build());
+        trans.putOperationalData(flowRef, flowBuilder.build());
         return flowStatsEntry;
     }
 
@@ -180,9 +160,9 @@ final class FlowStatsTracker extends AbstractListeningStatsTracker<FlowAndStatis
         // FIXME: it does not make sense to trigger this before sendAllFlowTablesStatisticsRequest()
         //        comes back -- we do not have any tables anyway.
         final Collection<TableKey> tables = flowTableStats.getTables();
-        logger.debug("Node {} supports {} table(s)", this.getNodeRef(), tables.size());
+        LOG.debug("Node {} supports {} table(s)", this.getNodeRef(), tables.size());
         for (final TableKey key : tables) {
-            logger.debug("Send aggregate stats request for flow table {} to node {}", key.getId(), this.getNodeRef());
+            LOG.debug("Send aggregate stats request for flow table {} to node {}", key.getId(), this.getNodeRef());
             this.requestAggregateFlows(key);
         }
 
@@ -224,10 +204,10 @@ final class FlowStatsTracker extends AbstractListeningStatsTracker<FlowAndStatis
         for (Entry<InstanceIdentifier<?>, DataObject> e : change.getCreatedConfigurationData().entrySet()) {
             if (Flow.class.equals(e.getKey().getTargetType())) {
                 final Flow flow = (Flow) e.getValue();
-                logger.debug("Key {} triggered request for flow {}", e.getKey(), flow);
+                LOG.debug("Key {} triggered request for flow {}", e.getKey(), flow);
                 requestFlow(flow);
             } else {
-                logger.debug("Ignoring key {}", e.getKey());
+                LOG.debug("Ignoring key {}", e.getKey());
             }
         }
 
@@ -236,7 +216,7 @@ final class FlowStatsTracker extends AbstractListeningStatsTracker<FlowAndStatis
             if (Flow.class.equals(key.getTargetType())) {
                 @SuppressWarnings("unchecked")
                 final InstanceIdentifier<Flow> flow = (InstanceIdentifier<Flow>)key;
-                logger.debug("Key {} triggered remove of Flow from operational space.", key);
+                LOG.debug("Key {} triggered remove of Flow from operational space.", key);
                 trans.removeOperationalData(flow);
             }
         }
@@ -246,10 +226,79 @@ final class FlowStatsTracker extends AbstractListeningStatsTracker<FlowAndStatis
     @Override
     public void start(final DataBrokerService dbs) {
         if (flowStatsService == null) {
-            logger.debug("No Flow Statistics service, not subscribing to flows on node {}", getNodeIdentifier());
+            LOG.debug("No Flow Statistics service, not subscribing to flows on node {}", getNodeIdentifier());
             return;
         }
 
         super.start(dbs);
     }
+
+    /* Returns Exist FlowKey from exist FlowCookieMap identified by cookie
+     * and by switch flow identification (priority and match)*/
+    private Optional<FlowKey> getExistFlowKey(final Flow flowRule, final InstanceIdentifier<Table> tableRef,
+            final DataModificationTransaction trans, final FlowCookieMap cookieMap) {
+
+        if (cookieMap != null) {
+            for (FlowId flowId : cookieMap.getFlowIds()) {
+                InstanceIdentifier<Flow> flowIdent = tableRef.child(Flow.class, new FlowKey(flowId));
+                if (flowId.getValue().startsWith(ALIEN_SYSTEM_FLOW_ID)) {
+                    LOG.debug("Search for flow in the operational datastore by flowID: {} ", flowIdent);
+                    Flow readedFlow = (Flow) trans.readOperationalData(flowIdent);
+                    if (FlowComparator.flowEquals(flowRule, readedFlow)) {
+                        return Optional.<FlowKey> of(new FlowKey(flowId));
+                    }
+                } else {
+                    LOG.debug("Search for flow in the configuration datastore by flowID: {} ", flowIdent);
+                    Flow readedFlow = (Flow) trans.readConfigurationData(flowIdent);
+                    if (FlowComparator.flowEquals(flowRule, readedFlow)) {
+                        return Optional.<FlowKey> of(new FlowKey(flowId));
+                    }
+                }
+            }
+            LOG.debug("Flow was not found in the datastore. Flow {} ", flowRule);
+        }
+        return Optional.absent();
+    }
+
+    /* Returns FlowKey from existing Flow in DataStore/CONFIGURATIONAL which is identified by cookie
+     * and by switch flow identification (priority and match) */
+    private Optional<FlowKey> getFlowKeyFromExistFlow(final Flow flowRule, final InstanceIdentifier<Table> tableRef,
+            final DataModificationTransaction trans) {
+
+        /* Try to find it in DataSotre/CONFIG */
+        Table table= (Table)trans.readConfigurationData(tableRef);
+        if(table != null) {
+            for(Flow existingFlow : table.getFlow()) {
+                LOG.debug("Existing flow in data store : {}",existingFlow.toString());
+                if(FlowComparator.flowEquals(flowRule,existingFlow)){
+                    return Optional.<FlowKey> of(new FlowKey(existingFlow.getId()));
+                }
+            }
+        }
+        return Optional.absent();
+    }
+
+    /* Returns FlowKey which doesn't exist in any DataStore for now */
+    private Optional<FlowKey> makeAlienFlowKey(final Flow flowRule) {
+
+        StringBuilder sBuilder = new StringBuilder(ALIEN_SYSTEM_FLOW_ID)
+            .append(flowRule.getTableId()).append("-").append(this.unaccountedFlowsCounter);
+        this.unaccountedFlowsCounter++;
+        final FlowId flowId = new FlowId(sBuilder.toString());
+        return Optional.<FlowKey> of(new FlowKey(flowId));
+    }
+
+    /* Build new whole FlowCookieMap or add new flowKey */
+    private FlowCookieMap applyNewFlowKey(FlowCookieMap flowCookieMap, final Optional<FlowKey> flowKey,
+            final FlowCookie flowCookie) {
+        if (flowCookieMap != null) {
+            flowCookieMap.getFlowIds().add(flowKey.get().getId());
+        } else {
+            final FlowCookieMapBuilder flowCookieMapBuilder = new FlowCookieMapBuilder();
+            flowCookieMapBuilder.setCookie(flowCookie);
+            flowCookieMapBuilder.setFlowIds(Collections.singletonList(flowKey.get().getId()));
+            flowCookieMap = flowCookieMapBuilder.build();
+        }
+        return flowCookieMap;
+    }
 }
index 701911d9a2c307c03ecd48c75bfcd4099ba2490f..e4490eaa3cc2ea9ac2683ff36f6d48787ddded99 100644 (file)
@@ -31,12 +31,12 @@ final class NodeConnectorStatsTracker extends AbstractStatsTracker<NodeConnector
     }
 
     @Override
-    protected void cleanupSingleStat(DataModificationTransaction trans, NodeConnectorStatisticsAndPortNumberMap item) {
+    protected void cleanupSingleStat(final DataModificationTransaction trans, final NodeConnectorStatisticsAndPortNumberMap item) {
         // TODO Auto-generated method stub
     }
 
     @Override
-    protected NodeConnectorStatisticsAndPortNumberMap updateSingleStat(DataModificationTransaction trans, NodeConnectorStatisticsAndPortNumberMap item) {
+    protected NodeConnectorStatisticsAndPortNumberMap updateSingleStat(final DataModificationTransaction trans, final NodeConnectorStatisticsAndPortNumberMap item) {
         FlowCapableNodeConnectorStatisticsBuilder statisticsBuilder
                                         = new FlowCapableNodeConnectorStatisticsBuilder();
         statisticsBuilder.setBytes(item.getBytes());
@@ -57,16 +57,17 @@ final class NodeConnectorStatsTracker extends AbstractStatsTracker<NodeConnector
 
         statisticsDataBuilder.setFlowCapableNodeConnectorStatistics(statisticsBuilder.build());
 
-        InstanceIdentifier<NodeConnector> nodeConnectorRef = getNodeIdentifierBuilder()
-                .child(NodeConnector.class, new NodeConnectorKey(item.getNodeConnectorId())).build();
+        final NodeConnectorKey key = new NodeConnectorKey(item.getNodeConnectorId());
+        final InstanceIdentifier<NodeConnector> nodeConnectorRef = getNodeIdentifier().child(NodeConnector.class, key);
 
         // FIXME: can we bypass this read?
         NodeConnector nodeConnector = (NodeConnector)trans.readOperationalData(nodeConnectorRef);
         if(nodeConnector != null){
             final FlowCapableNodeConnectorStatisticsData stats = statisticsDataBuilder.build();
             logger.debug("Augmenting port statistics {} to port {}",stats,nodeConnectorRef.toString());
-            NodeConnectorBuilder nodeConnectorBuilder = new NodeConnectorBuilder();
-            nodeConnectorBuilder.addAugmentation(FlowCapableNodeConnectorStatisticsData.class, stats);
+            NodeConnectorBuilder nodeConnectorBuilder = new NodeConnectorBuilder()
+                .setKey(key).setId(item.getNodeConnectorId())
+                .addAugmentation(FlowCapableNodeConnectorStatisticsData.class, stats);
             trans.putOperationalData(nodeConnectorRef, nodeConnectorBuilder.build());
         }
 
index 0a3b9f6a6b7c53c193cd3fd523504d4e729df180..556047091c1a779f6af251d9da0e00c50f6c6536 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.md.controller.topology.manager;
 
 import java.util.concurrent.ExecutionException;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -44,16 +45,15 @@ public class FlowCapableTopologyProvider extends AbstractBindingAwareProvider im
         final String name = "flow:1";
         final TopologyKey key = new TopologyKey(new TopologyId(name));
         final InstanceIdentifier<Topology> path = InstanceIdentifier
-                .builder(NetworkTopology.class)
-                .child(Topology.class, key)
-                .build();
+                .create(NetworkTopology.class)
+                .child(Topology.class, key);
 
         final OperationProcessor processor = new OperationProcessor(dataBroker);
         final FlowCapableTopologyExporter listener = new FlowCapableTopologyExporter(processor, path);
         this.listenerRegistration = notificationService.registerNotificationListener(listener);
 
         final ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
-        tx.put(LogicalDatastoreType.OPERATIONAL, path, new TopologyBuilder().setKey(key).build());
+        tx.put(LogicalDatastoreType.OPERATIONAL, path, new TopologyBuilder().setKey(key).build(), true);
         try {
             tx.submit().get();
         } catch (InterruptedException | ExecutionException e) {
index 2f7bd20d615b074a945bf49e2c60c9559c3df7e7..6826b4a09ca6013f57c192ef07fcef3bdd7e7387 100644 (file)
@@ -49,6 +49,7 @@ import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFact
 import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
 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;
@@ -136,7 +137,7 @@ public class NetconfITSecureTest extends AbstractNetconfConfigTest {
     }
 
     public AuthProvider getAuthProvider() throws Exception {
-        AuthProvider mock = mock(AuthProvider.class);
+        AuthProvider mock = mock(AuthProviderImpl.class);
         doReturn(true).when(mock).authenticated(anyString(), anyString());
         doReturn(PEMGenerator.generate().toCharArray()).when(mock).getPEMAsCharArray();
         return mock;
index 5d39dd1eb8adad115e030c0136cbae702d2bde65..92f3861c05351cacf9b93dd38d6771a58141fb9a 100644 (file)
@@ -1,81 +1,16 @@
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * 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.ssh.authentication;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.google.common.annotations.VisibleForTesting;
-import org.opendaylight.controller.sal.authorization.AuthResultEnum;
-import org.opendaylight.controller.usermanager.IUserManager;
-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;
-
-public class AuthProvider {
-    private static final Logger logger = LoggerFactory.getLogger(AuthProvider.class);
-
-    private final String pem;
-    private IUserManager nullableUserManager;
 
-    public AuthProvider(String pemCertificate, final BundleContext bundleContext) {
-        checkNotNull(pemCertificate, "Parameter 'pemCertificate' is null");
-        pem = pemCertificate;
-
-        ServiceTrackerCustomizer<IUserManager, IUserManager> customizer = new ServiceTrackerCustomizer<IUserManager, IUserManager>() {
-            @Override
-            public IUserManager addingService(final ServiceReference<IUserManager> reference) {
-                logger.trace("Service {} 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);
-                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);
-                synchronized (AuthProvider.this) {
-                    nullableUserManager = null;
-                }
-            }
-        };
-        ServiceTracker<IUserManager, IUserManager> listenerTracker = new ServiceTracker<>(bundleContext, IUserManager.class, customizer);
-        listenerTracker.open();
-    }
+package org.opendaylight.controller.netconf.ssh.authentication;
 
-    /**
-     * Authenticate user. This implementation tracks IUserManager and delegates the decision to it. If the service is not
-     * available, IllegalStateException is thrown.
-     */
-    public synchronized boolean authenticated(String username, 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);
-        logger.debug("Authentication result for user '{}' : {}", username, authResult);
-        return authResult.equals(AuthResultEnum.AUTH_ACCEPT) || authResult.equals(AuthResultEnum.AUTH_ACCEPT_LOC);
-    }
+public interface AuthProvider {
 
-    public char[] getPEMAsCharArray() {
-        return pem.toCharArray();
-    }
+    boolean authenticated(String username, String password);
 
-    @VisibleForTesting
-    void setNullableUserManager(IUserManager nullableUserManager) {
-        this.nullableUserManager = nullableUserManager;
-    }
+    char[] getPEMAsCharArray();
 }
diff --git a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProviderImpl.java b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProviderImpl.java
new file mode 100644 (file)
index 0000000..7543d17
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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.ssh.authentication;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.opendaylight.controller.sal.authorization.AuthResultEnum;
+import org.opendaylight.controller.usermanager.IUserManager;
+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;
+
+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;
+
+        ServiceTrackerCustomizer<IUserManager, IUserManager> customizer = new ServiceTrackerCustomizer<IUserManager, IUserManager>() {
+            @Override
+            public IUserManager addingService(final ServiceReference<IUserManager> reference) {
+                logger.trace("Service {} 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);
+                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);
+                synchronized (AuthProviderImpl.this) {
+                    nullableUserManager = null;
+                }
+            }
+        };
+        ServiceTracker<IUserManager, IUserManager> listenerTracker = new ServiceTracker<>(bundleContext, IUserManager.class, customizer);
+        listenerTracker.open();
+    }
+
+    /**
+     * Authenticate user. This implementation tracks IUserManager and delegates the decision to it. If the service is not
+     * available, IllegalStateException is thrown.
+     */
+    @Override
+    public synchronized boolean authenticated(String username, 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);
+        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) {
+        this.nullableUserManager = nullableUserManager;
+    }
+}
index a26843fae17a97621b48221a932eb9b823a6ce83..503e764409e37d848ffeaf444c5e34e529bd6849 100644 (file)
@@ -20,6 +20,7 @@ import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.lang3.StringUtils;
 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;
@@ -72,7 +73,7 @@ public class NetconfSSHActivator implements BundleActivator {
         checkState(StringUtils.isNotBlank(path), "Path to ssh private key is blank. Reconfigure %s", NetconfConfigUtil.getPrivateKeyKey());
         String privateKeyPEMString = PEMGenerator.readOrGeneratePK(new File(path));
 
-        final AuthProvider authProvider = new AuthProvider(privateKeyPEMString, bundleContext);
+        final AuthProvider authProvider = new AuthProviderImpl(privateKeyPEMString, bundleContext);
         EventLoopGroup bossGroup  = new NioEventLoopGroup();
         NetconfSSHServer server = NetconfSSHServer.start(sshSocketAddress.getPort(), localAddress, authProvider, bossGroup);
 
index 488c3701457039a022b1b0caed1a0d14e899641e..61297835a07b684dd009176c6c0e16c0971c2b5e 100644 (file)
@@ -32,6 +32,7 @@ import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.
 import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshHandler;
 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;
@@ -58,7 +59,7 @@ public class SSHTest {
     @Test
     public void test() throws Exception {
         new Thread(new EchoServer(), "EchoServer").start();
-        AuthProvider authProvider = mock(AuthProvider.class);
+        AuthProvider authProvider = mock(AuthProviderImpl.class);
         doReturn(PEMGenerator.generate().toCharArray()).when(authProvider).getPEMAsCharArray();
         doReturn(true).when(authProvider).authenticated(anyString(), anyString());
         NetconfSSHServer netconfSSHServer = NetconfSSHServer.start(10831, NetconfConfigUtil.getNetconfLocalAddress(),
index 5e368bc5669f7ce88318971cb810722e7c7f8d49..75d18566eec79c775d7861d86fd0aaf2ddda2dbb 100644 (file)
@@ -60,7 +60,7 @@ public class SSHServerTest {
         try (InputStream is = getClass().getResourceAsStream("/RSA.pk")) {
             pem = IOUtils.toString(is);
         }
-        AuthProvider ap = new AuthProvider(pem, mockedContext);
+        AuthProviderImpl ap = new AuthProviderImpl(pem, mockedContext);
         ap.setNullableUserManager(um);
         EventLoopGroup bossGroup = new NioEventLoopGroup();
         NetconfSSHServer server = NetconfSSHServer.start(PORT, NetconfConfigUtil.getNetconfLocalAddress(),
diff --git a/opendaylight/netconf/netconf-testtool/pom.xml b/opendaylight/netconf/netconf-testtool/pom.xml
new file mode 100644 (file)
index 0000000..ae0bb76
--- /dev/null
@@ -0,0 +1,143 @@
+<?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>
+    </parent>
+
+    <artifactId>netconf-testtool</artifactId>
+    <name>${project.artifactId}</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>net.sourceforge.argparse4j</groupId>
+            <artifactId>argparse4j</artifactId>
+            <version>0.4.3</version>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netconf-netty-util</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>commons.logback_settings</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-netconf-connector</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netconf-connector-config</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>logback-config</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>mockito-configuration</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>xmlunit</groupId>
+            <artifactId>xmlunit</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>config-util</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netconf-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netconf-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netconf-impl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netconf-mapping-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netconf-monitoring</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netconf-ssh</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netty-config-api</artifactId>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-shade-plugin</artifactId>
+                <configuration></configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                        <phase>package</phase>
+                        <configuration>
+                            <!-- TODO investigate why jar fails without this filter-->
+                            <filters>
+                                <filter>
+                                    <artifact>*:*</artifact>
+                                    <excludes>
+                                        <exclude>META-INF/*.SF</exclude>
+                                        <exclude>META-INF/*.DSA</exclude>
+                                        <exclude>META-INF/*.RSA</exclude>
+                                    </excludes>
+                                </filter>
+                            </filters>
+                            <transformers>
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                                    <mainClass>org.opendaylight.controller.netconf.test.tool.Main</mainClass>
+                                </transformer>
+                            </transformers>
+                            <shadedArtifactAttached>true</shadedArtifactAttached>
+                            <shadedClassifierName>executable</shadedClassifierName>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/AcceptingAuthProvider.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/AcceptingAuthProvider.java
new file mode 100644 (file)
index 0000000..35f2345
--- /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.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;
+
+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();
+    }
+}
diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/Main.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/Main.java
new file mode 100644 (file)
index 0000000..59e9f4c
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * 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.test.tool;
+
+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 com.google.common.io.Files;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.List;
+
+import net.sourceforge.argparse4j.ArgumentParsers;
+import net.sourceforge.argparse4j.annotation.Arg;
+import net.sourceforge.argparse4j.inf.ArgumentParser;
+import net.sourceforge.argparse4j.inf.ArgumentParserException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.CharStreams;
+
+public final class Main {
+
+    // TODO add logback config
+
+    // TODO make exi configurable
+
+    private static final Logger LOG = LoggerFactory.getLogger(Main.class);
+
+    static class Params {
+
+        @Arg(dest = "schemas-dir")
+        public File schemasDir;
+
+        @Arg(dest = "devices-count")
+        public int deviceCount;
+
+        @Arg(dest = "starting-port")
+        public int startingPort;
+
+        @Arg(dest = "generate-configs-dir")
+        public File generateConfigsDir;
+
+        @Arg(dest = "generate-configs-batch-size")
+        public int generateConfigBatchSize;
+
+        @Arg(dest = "ssh")
+        public boolean ssh;
+
+        static ArgumentParser getParser() {
+            final ArgumentParser parser = ArgumentParsers.newArgumentParser("netconf testool");
+            parser.addArgument("--devices-count")
+                    .type(Integer.class)
+                    .setDefault(1)
+                    .type(Integer.class)
+                    .help("Number of simulated netconf devices to spin")
+                    .dest("devices-count");
+
+            parser.addArgument("--schemas-dir")
+                    .type(File.class)
+                    .required(true)
+                    .help("Directory containing yang schemas to describe simulated devices")
+                    .dest("schemas-dir");
+
+            parser.addArgument("--starting-port")
+                    .type(Integer.class)
+                    .setDefault(17830)
+                    .help("First port for simulated device. Each other device will have previous+1 port number")
+                    .dest("starting-port");
+
+            parser.addArgument("--generate-configs-batch-size")
+                    .type(Integer.class)
+                    .setDefault(100)
+                    .help("Number of connector configs per generated file")
+                    .dest("generate-configs-batch-size");
+
+            parser.addArgument("--generate-configs-dir")
+                    .type(File.class)
+                    .help("Directory where initial config files for ODL distribution should be generated")
+                    .dest("generate-configs-dir");
+
+            parser.addArgument("--ssh")
+                    .type(Boolean.class)
+                    .setDefault(true)
+                    .help("Whether to use ssh for transport or just pure tcp")
+                    .dest("ssh");
+
+            return parser;
+        }
+
+        void validate() {
+            checkArgument(deviceCount > 0, "Device count has to be > 0");
+            checkArgument(startingPort > 1024, "Starting port has to be > 1024");
+
+            checkArgument(schemasDir.exists(), "Schemas dir has to exist");
+            checkArgument(schemasDir.isDirectory(), "Schemas dir has to be a directory");
+            checkArgument(schemasDir.canRead(), "Schemas dir has to be readable");
+        }
+    }
+
+    public static void main(final String[] args) {
+        final Params params = parseArgs(args, Params.getParser());
+        params.validate();
+
+        final NetconfDeviceSimulator netconfDeviceSimulator = new NetconfDeviceSimulator();
+        try {
+            final List<Integer> openDevices = netconfDeviceSimulator.start(params);
+            if(params.generateConfigsDir != null) {
+                new ConfigGenerator(params.generateConfigsDir, openDevices).generate(params.ssh, params.generateConfigBatchSize);
+            }
+        } catch (final Exception e) {
+            LOG.error("Unhandled exception", e);
+            netconfDeviceSimulator.close();
+            System.exit(1);
+        }
+
+        // Block main thread
+        synchronized (netconfDeviceSimulator) {
+            try {
+                netconfDeviceSimulator.wait();
+            } catch (final InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+
+    private static Params parseArgs(final String[] args, final ArgumentParser parser) {
+        final Params opt = new Params();
+        try {
+            parser.parseArgs(args, opt);
+            return opt;
+        } catch (final ArgumentParserException e) {
+            parser.handleError(e);
+        }
+
+        System.exit(1);
+        return null;
+    }
+
+    private static class ConfigGenerator {
+        public static final String NETCONF_CONNECTOR_XML = "/initial/99-netconf-connector.xml";
+        public static final String NETCONF_CONNECTOR_NAME = "controller-config";
+        public static final String NETCONF_CONNECTOR_PORT = "1830";
+        public static final String NETCONF_USE_SSH = "false";
+        public static final String SIM_DEVICE_SUFFIX = "-sim-device";
+
+        private final File directory;
+        private final List<Integer> openDevices;
+
+        public ConfigGenerator(final File directory, final List<Integer> openDevices) {
+            this.directory = directory;
+            this.openDevices = openDevices;
+        }
+
+        public void generate(final boolean useSsh, final int batchSize) {
+            if(directory.exists() == false) {
+                checkState(directory.mkdirs(), "Unable to create folder %s" + directory);
+            }
+
+            try(InputStream stream = Main.class.getResourceAsStream(NETCONF_CONNECTOR_XML)) {
+                checkNotNull(stream, "Cannot load %s", NETCONF_CONNECTOR_XML);
+                String configBlueprint = CharStreams.toString(new InputStreamReader(stream, Charsets.UTF_8));
+
+                // TODO make address configurable
+                checkState(configBlueprint.contains(NETCONF_CONNECTOR_NAME));
+                checkState(configBlueprint.contains(NETCONF_CONNECTOR_PORT));
+                checkState(configBlueprint.contains(NETCONF_USE_SSH));
+                configBlueprint = configBlueprint.replace(NETCONF_CONNECTOR_NAME, "%s");
+                configBlueprint = configBlueprint.replace(NETCONF_CONNECTOR_PORT, "%s");
+                configBlueprint = configBlueprint.replace(NETCONF_USE_SSH, "%s");
+
+                final String before = configBlueprint.substring(0, configBlueprint.indexOf("<module>"));
+                final String middleBlueprint = configBlueprint.substring(configBlueprint.indexOf("<module>"), configBlueprint.indexOf("</module>") + "</module>".length());
+                final String after = configBlueprint.substring(configBlueprint.indexOf("</module>") + "</module>".length());
+
+                int connectorCount = 0;
+                Integer batchStart = null;
+                StringBuilder b = new StringBuilder();
+                b.append(before);
+
+                for (final Integer openDevice : openDevices) {
+                    if(batchStart == null) {
+                        batchStart = openDevice;
+                    }
+
+                    final String name = String.valueOf(openDevice) + SIM_DEVICE_SUFFIX;
+                    final String configContent = String.format(middleBlueprint, name, String.valueOf(openDevice), String.valueOf(!useSsh));
+                    b.append(configContent);
+                    connectorCount++;
+                    if(connectorCount == batchSize) {
+                        b.append(after);
+                        Files.write(b.toString(), new File(directory, String.format("simulated-devices_%d-%d.xml", batchStart, openDevice)), Charsets.UTF_8);
+                        connectorCount = 0;
+                        b = new StringBuilder();
+                        b.append(before);
+                        batchStart = null;
+                    }
+                }
+
+                // Write remaining
+                if(connectorCount != 0) {
+                    b.append(after);
+                    Files.write(b.toString(), new File(directory, String.format("simulated-devices_%d-%d.xml", batchStart, openDevices.get(openDevices.size() - 1))), Charsets.UTF_8);
+                }
+
+                LOG.info("Config files generated in {}", directory);
+            } catch (final IOException e) {
+                throw new RuntimeException("Unable to generate config files", e);
+            }
+        }
+    }
+}
diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/ModuleBuilderCapability.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/ModuleBuilderCapability.java
new file mode 100644 (file)
index 0000000..1a68f55
--- /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.netconf.test.tool;
+
+import com.google.common.base.Optional;
+import java.util.Date;
+import java.util.List;
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+import org.opendaylight.controller.netconf.mapping.api.Capability;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder;
+
+final class ModuleBuilderCapability implements Capability {
+    private static final Date NO_REVISION = new Date(0);
+    private final ModuleBuilder input;
+    private final Optional<String> content;
+
+    public ModuleBuilderCapability(final ModuleBuilder input, final String inputStream) {
+        this.input = input;
+        this.content = Optional.of(inputStream);
+    }
+
+    @Override
+    public String getCapabilityUri() {
+        // FIXME capabilities in Netconf-impl need to check for NO REVISION
+        final String withoutRevision = getModuleNamespace().get() + "?module=" + getModuleName().get();
+        return hasRevision() ? withoutRevision + "&revision=" + Util.writeDate(input.getRevision()) : withoutRevision;
+    }
+
+    @Override
+    public Optional<String> getModuleNamespace() {
+        return Optional.of(input.getNamespace().toString());
+    }
+
+    @Override
+    public Optional<String> getModuleName() {
+        return Optional.of(input.getName());
+    }
+
+    @Override
+    public Optional<String> getRevision() {
+        return Optional.of(hasRevision() ? QName.formattedRevision(input.getRevision()) : "");
+    }
+
+    private boolean hasRevision() {
+        return !input.getRevision().equals(NO_REVISION);
+    }
+
+    @Override
+    public Optional<String> getCapabilitySchema() {
+        return content;
+    }
+
+    @Override
+    public Optional<List<String>> getLocation() {
+        return Optional.absent();
+    }
+}
diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java
new file mode 100644 (file)
index 0000000..b21c02a
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * 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.test.tool;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.common.io.CharStreams;
+import com.google.common.util.concurrent.CheckedFuture;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.local.LocalAddress;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.HashedWheelTimer;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.management.ManagementFactory;
+import java.net.Inet4Address;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.net.UnknownHostException;
+import java.util.AbstractMap;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.concurrent.ExecutionException;
+import org.antlr.v4.runtime.ParserRuleContext;
+import org.antlr.v4.runtime.tree.ParseTreeWalker;
+import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession;
+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.SessionMonitoringService;
+import org.opendaylight.controller.netconf.mapping.api.Capability;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider;
+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.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceListener;
+import org.opendaylight.yangtools.yang.model.repo.util.FilesystemSchemaSourceCache;
+import org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils;
+import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserListenerImpl;
+import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
+import org.opendaylight.yangtools.yang.parser.util.ASTSchemaSource;
+import org.opendaylight.yangtools.yang.parser.util.TextToASTTransformer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetconfDeviceSimulator implements Closeable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfDeviceSimulator.class);
+
+    public static final int CONNECTION_TIMEOUT_MILLIS = 20000;
+
+    private final NioEventLoopGroup nettyThreadgroup;
+    private final HashedWheelTimer hashedWheelTimer;
+    private final List<Channel> devicesChannels = Lists.newArrayList();
+
+    public NetconfDeviceSimulator() {
+        this(new NioEventLoopGroup(), new HashedWheelTimer());
+    }
+
+    public NetconfDeviceSimulator(final NioEventLoopGroup eventExecutors, final HashedWheelTimer hashedWheelTimer) {
+        this.nettyThreadgroup = eventExecutors;
+        this.hashedWheelTimer = hashedWheelTimer;
+    }
+
+    private NetconfServerDispatcher createDispatcher(final Map<ModuleBuilder, String> moduleBuilders) {
+
+        final Set<Capability> capabilities = Sets.newHashSet(Collections2.transform(moduleBuilders.keySet(), new Function<ModuleBuilder, Capability>() {
+            @Override
+            public Capability apply(final ModuleBuilder input) {
+                return new ModuleBuilderCapability(input, moduleBuilders.get(input));
+            }
+        }));
+
+        final SessionIdProvider idProvider = new SessionIdProvider();
+
+        final SimulatedOperationProvider simulatedOperationProvider = new SimulatedOperationProvider(idProvider, capabilities);
+        final NetconfMonitoringOperationService monitoringService = new NetconfMonitoringOperationService(new NetconfMonitoringServiceImpl(simulatedOperationProvider));
+        simulatedOperationProvider.addService(monitoringService);
+
+        final DefaultCommitNotificationProducer commitNotifier = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
+
+        final NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
+                hashedWheelTimer, simulatedOperationProvider, idProvider, CONNECTION_TIMEOUT_MILLIS, commitNotifier, new LoggingMonitoringService());
+
+        final NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(
+                serverNegotiatorFactory);
+        return new NetconfServerDispatcher(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup);
+    }
+
+    private Map<ModuleBuilder, String> toModuleBuilders(final Map<SourceIdentifier, Map.Entry<ASTSchemaSource, YangTextSchemaSource>> sources) {
+            final Map<SourceIdentifier, ParserRuleContext> asts = Maps.transformValues(sources,  new Function<Map.Entry<ASTSchemaSource, YangTextSchemaSource>, ParserRuleContext>() {
+                @Override
+                public ParserRuleContext apply(final Map.Entry<ASTSchemaSource, YangTextSchemaSource> input) {
+                    return input.getKey().getAST();
+                }
+            });
+            final Map<String, TreeMap<Date, URI>> namespaceContext = BuilderUtils.createYangNamespaceContext(
+                    asts.values(), Optional.<SchemaContext>absent());
+
+            final ParseTreeWalker walker = new ParseTreeWalker();
+            final Map<ModuleBuilder, String> sourceToBuilder = new HashMap<>();
+
+            for (final Map.Entry<SourceIdentifier, ParserRuleContext> entry : asts.entrySet()) {
+                final ModuleBuilder moduleBuilder = YangParserListenerImpl.create(namespaceContext, entry.getKey().getName(),
+                        walker, entry.getValue()).getModuleBuilder();
+
+                try(InputStreamReader stream = new InputStreamReader(sources.get(entry.getKey()).getValue().openStream(), Charsets.UTF_8)) {
+                    sourceToBuilder.put(moduleBuilder, CharStreams.toString(stream));
+                } catch (final IOException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+
+            return sourceToBuilder;
+        }
+
+
+    public List<Integer> start(final Main.Params params) {
+        final Map<ModuleBuilder, String> moduleBuilders = parseSchemasToModuleBuilders(params);
+
+        final NetconfServerDispatcher dispatcher = createDispatcher(moduleBuilders);
+
+        int currentPort = params.startingPort;
+
+        final List<Integer> openDevices = Lists.newArrayList();
+        for (int i = 0; i < params.deviceCount; i++) {
+            final InetSocketAddress address = getAddress(currentPort);
+
+            final ChannelFuture server;
+            if(params.ssh) {
+                final LocalAddress tcpLocalAddress = new LocalAddress(address.toString());
+
+                server = dispatcher.createLocalServer(tcpLocalAddress);
+                try {
+                    NetconfSSHServer.start(currentPort, tcpLocalAddress, new AcceptingAuthProvider(), nettyThreadgroup);
+                } catch (final Exception e) {
+                    LOG.warn("Cannot start simulated device on {}, skipping", address, e);
+                    // Close local server and continue
+                    server.cancel(true);
+                    if(server.isDone()) {
+                        server.channel().close();
+                    }
+                    continue;
+                } finally {
+                    currentPort++;
+                }
+
+                try {
+                    server.get();
+                } catch (final InterruptedException e) {
+                    throw new RuntimeException(e);
+                } catch (final ExecutionException e) {
+                    LOG.warn("Cannot start ssh simulated device on {}, skipping", address, e);
+                    continue;
+                }
+
+                LOG.debug("Simulated SSH device started on {}", address);
+
+            } else {
+                server = dispatcher.createServer(address);
+                currentPort++;
+
+                try {
+                    server.get();
+                } catch (final InterruptedException e) {
+                    throw new RuntimeException(e);
+                } catch (final ExecutionException e) {
+                    LOG.warn("Cannot start tcp simulated device on {}, skipping", address, e);
+                    continue;
+                }
+
+                LOG.debug("Simulated TCP device started on {}", address);
+            }
+
+            devicesChannels.add(server.channel());
+            openDevices.add(currentPort - 1);
+
+        }
+
+        if(openDevices.size() == params.deviceCount) {
+            LOG.info("All simulated devices started successfully from port {} to {}", params.startingPort, currentPort);
+        } else {
+            LOG.warn("Not all simulated devices started successfully. Started devices ar on ports {}", openDevices);
+        }
+
+        return openDevices;
+    }
+
+    private Map<ModuleBuilder, String> parseSchemasToModuleBuilders(final Main.Params params) {
+        final SharedSchemaRepository consumer = new SharedSchemaRepository("netconf-simulator");
+        consumer.registerSchemaSourceListener(TextToASTTransformer.create(consumer, consumer));
+
+        final Set<SourceIdentifier> loadedSources = Sets.newHashSet();
+
+        consumer.registerSchemaSourceListener(new SchemaSourceListener() {
+            @Override
+            public void schemaSourceEncountered(final SchemaSourceRepresentation schemaSourceRepresentation) {}
+
+            @Override
+            public void schemaSourceRegistered(final Iterable<PotentialSchemaSource<?>> potentialSchemaSources) {
+                for (final PotentialSchemaSource<?> potentialSchemaSource : potentialSchemaSources) {
+                    loadedSources.add(potentialSchemaSource.getSourceIdentifier());
+                }
+            }
+
+            @Override
+            public void schemaSourceUnregistered(final PotentialSchemaSource<?> potentialSchemaSource) {}
+        });
+
+        final FilesystemSchemaSourceCache<YangTextSchemaSource> cache = new FilesystemSchemaSourceCache<>(consumer, YangTextSchemaSource.class, params.schemasDir);
+        consumer.registerSchemaSourceListener(cache);
+
+        final Map<SourceIdentifier, Map.Entry<ASTSchemaSource, YangTextSchemaSource>> asts = Maps.newHashMap();
+        for (final SourceIdentifier loadedSource : loadedSources) {
+                try {
+                    final CheckedFuture<ASTSchemaSource, SchemaSourceException> ast = consumer.getSchemaSource(loadedSource, ASTSchemaSource.class);
+                    final CheckedFuture<YangTextSchemaSource, SchemaSourceException> text = consumer.getSchemaSource(loadedSource, YangTextSchemaSource.class);
+                    asts.put(loadedSource, new AbstractMap.SimpleEntry<>(ast.get(), text.get()));
+                } catch (final InterruptedException e) {
+                    throw new RuntimeException(e);
+                } catch (final ExecutionException e) {
+                    throw new RuntimeException("Cannot parse schema context", e);
+                }
+        }
+        return toModuleBuilders(asts);
+    }
+
+    private static InetSocketAddress getAddress(final int port) {
+        try {
+            // TODO make address configurable
+            return new InetSocketAddress(Inet4Address.getByName("0.0.0.0"), port);
+        } catch (final UnknownHostException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void close() {
+        for (final Channel deviceCh : devicesChannels) {
+            deviceCh.close();
+        }
+        nettyThreadgroup.shutdownGracefully();
+        // close Everything
+    }
+
+    private static class SimulatedOperationProvider implements NetconfOperationProvider {
+        private final SessionIdProvider idProvider;
+        private final Set<NetconfOperationService> netconfOperationServices;
+
+
+        public SimulatedOperationProvider(final SessionIdProvider idProvider, final Set<Capability> caps) {
+            this.idProvider = idProvider;
+            final SimulatedOperationService simulatedOperationService = new SimulatedOperationService(caps, idProvider.getCurrentSessionId());
+            this.netconfOperationServices = Sets.<NetconfOperationService>newHashSet(simulatedOperationService);
+        }
+
+        @Override
+        public NetconfOperationServiceSnapshot openSnapshot(final String sessionIdForReporting) {
+            return new SimulatedServiceSnapshot(idProvider, netconfOperationServices);
+        }
+
+        public void addService(final NetconfOperationService monitoringService) {
+            netconfOperationServices.add(monitoringService);
+        }
+
+        private static class SimulatedServiceSnapshot implements NetconfOperationServiceSnapshot {
+            private final SessionIdProvider idProvider;
+            private final Set<NetconfOperationService> netconfOperationServices;
+
+            public SimulatedServiceSnapshot(final SessionIdProvider idProvider, final Set<NetconfOperationService> netconfOperationServices) {
+                this.idProvider = idProvider;
+                this.netconfOperationServices = netconfOperationServices;
+            }
+
+            @Override
+            public String getNetconfSessionIdForReporting() {
+                return String.valueOf(idProvider.getCurrentSessionId());
+            }
+
+            @Override
+            public Set<NetconfOperationService> getServices() {
+                return netconfOperationServices;
+            }
+
+            @Override
+            public void close() throws Exception {}
+        }
+
+        static class SimulatedOperationService implements NetconfOperationService {
+            private final Set<Capability> capabilities;
+            private static SimulatedGet sGet;
+
+            public SimulatedOperationService(final Set<Capability> capabilities, final long currentSessionId) {
+                this.capabilities = capabilities;
+                sGet = new SimulatedGet(String.valueOf(currentSessionId));
+            }
+
+            @Override
+            public Set<Capability> getCapabilities() {
+                return capabilities;
+            }
+
+            @Override
+            public Set<NetconfOperation> getNetconfOperations() {
+                return Sets.<NetconfOperation>newHashSet(sGet);
+            }
+
+            @Override
+            public void close() {
+            }
+
+        }
+    }
+
+    private class LoggingMonitoringService implements SessionMonitoringService {
+        @Override
+        public void onSessionUp(final NetconfManagementSession session) {
+            LOG.debug("Session {} established", session);
+        }
+
+        @Override
+        public void onSessionDown(final NetconfManagementSession session) {
+            LOG.debug("Session {} down", session);
+        }
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedGet.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedGet.java
new file mode 100644 (file)
index 0000000..b1938c8
--- /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.netconf.test.tool;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+class SimulatedGet extends AbstractConfigNetconfOperation {
+
+    SimulatedGet(final String netconfSessionIdForReporting) {
+        super(null, netconfSessionIdForReporting);
+    }
+
+    @Override
+    protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement) throws NetconfDocumentedException {
+        return XmlUtil.createElement(document, XmlNetconfConstants.DATA_KEY, Optional.<String>absent());
+    }
+
+    @Override
+    protected String getOperationName() {
+        return XmlNetconfConstants.GET;
+    }
+}
index 4c4ff2fc583a0a1007ccd4b4706054c097eb2d0c..6604834fe42c02b3b3188fd7cd7f85c7b887ff3d 100644 (file)
@@ -59,12 +59,12 @@ public final class SendErrorExceptionUtil {
             final NetconfDocumentedException sendErrorException) {
         try {
             final Element incommingRpc = incommingDocument.getDocumentElement();
-            Preconditions.checkState(incommingRpc.getTagName().equals(XmlNetconfConstants.RPC_KEY), "Missing "
-                    + XmlNetconfConstants.RPC_KEY + " " + "element");
+            Preconditions.checkState(incommingRpc.getTagName().equals(XmlNetconfConstants.RPC_KEY), "Missing %s element",
+                    XmlNetconfConstants.RPC_KEY);
 
             final Element rpcReply = errorDocument.getDocumentElement();
-            Preconditions.checkState(rpcReply.getTagName().equals(XmlNetconfConstants.RPC_REPLY_KEY), "Missing "
-                    + XmlNetconfConstants.RPC_REPLY_KEY + " element");
+            Preconditions.checkState(rpcReply.getTagName().equals(XmlNetconfConstants.RPC_REPLY_KEY), "Missing %s element",
+                    XmlNetconfConstants.RPC_REPLY_KEY);
 
             final NamedNodeMap incomingAttributes = incommingRpc.getAttributes();
             for (int i = 0; i < incomingAttributes.getLength(); i++) {
@@ -97,7 +97,7 @@ public final class SendErrorExceptionUtil {
 
         @Override
         public void operationComplete(final ChannelFuture channelFuture) throws Exception {
-            Preconditions.checkState(channelFuture.isSuccess(), "Unable to send exception {}", sendErrorException,
+            Preconditions.checkState(channelFuture.isSuccess(), "Unable to send exception %s", sendErrorException,
                     channelFuture.cause());
         }
     }
index e55ec697ba560b528353fc8581c406ff58ea4ffd..b1b410a1fcb9971cadcb0e973d2381cbbdf3d04e 100644 (file)
         <module>netconf-it</module>
       </modules>
     </profile>
+
+    <profile>
+        <id>testtool</id>
+        <activation>
+            <activeByDefault>false</activeByDefault>
+        </activation>
+        <modules>
+            <module>netconf-testtool</module>
+      </modules>
+    </profile>
   </profiles>
 </project>
diff --git a/pom.xml b/pom.xml
index e4c51b7839cff2f9af808d3fc78866bd0f599d45..0bfc64f8929c8c90d66edf0a1bf87fc7a3d2d03e 100644 (file)
--- a/pom.xml
+++ b/pom.xml
     <!-- Karaf Distribution -->
     <module>opendaylight/dummy-console</module>
     <module>opendaylight/karaf-branding</module>
+    <module>opendaylight/distribution/opendaylight-karaf-empty</module>
     <module>opendaylight/distribution/opendaylight-karaf</module>
+    <module>opendaylight/distribution/opendaylight-karaf-resources</module>
     <module>features</module>
   </modules>
   <scm>