Merge "BUG-421: Define multipart-transaction-aware"
authorTony Tkacik <ttkacik@cisco.com>
Wed, 19 Feb 2014 14:41:07 +0000 (14:41 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 19 Feb 2014 14:41:07 +0000 (14:41 +0000)
223 files changed:
opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/ARPReply.java
opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/ARPRequest.java
opendaylight/commons/opendaylight/pom.xml
opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractSessionNegotiator.java
opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSessionPromise.java
opendaylight/config/config-manager/pom.xml
opendaylight/config/config-persister-directory-autodetect-adapter/pom.xml
opendaylight/config/config-persister-directory-xml-adapter/pom.xml
opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/ConfigRegistryClientsTest.java
opendaylight/config/netty-event-executor-config/pom.xml
opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java
opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleFactory.java
opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java
opendaylight/config/netty-threadgroup-config/pom.xml
opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModule.java
opendaylight/config/netty-timer-config/pom.xml
opendaylight/config/pom.xml
opendaylight/config/shutdown-impl/src/main/java/org/opendaylight/controller/config/yang/shutdown/impl/ShutdownServiceImpl.java
opendaylight/config/shutdown-impl/src/test/java/org/opendaylight/controller/config/yang/shutdown/impl/ShutdownTest.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntry.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryBuilder.java [new file with mode: 0644]
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/RuntimeBeanEntry.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/TypeProviderWrapper.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/AbstractAttribute.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/TOAttribute.java
opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryTest.java
opendaylight/config/yang-jmx-generator/src/test/resources/config-jmx-it-impl.yang
opendaylight/config/yang-test/pom.xml
opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationContainerService.java
opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationService.java
opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ContainerConfigurationService.java
opendaylight/connectionmanager/implementation/pom.xml
opendaylight/containermanager/implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerManager.java
opendaylight/distribution/opendaylight/pom.xml
opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini
opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/00-netty.xml
opendaylight/forwardingrulesmanager/implementation/pom.xml
opendaylight/md-sal/compatibility/flow-management-compatibility/pom.xml
opendaylight/md-sal/compatibility/inventory-topology-compatibility/pom.xml
opendaylight/md-sal/compatibility/pom.xml
opendaylight/md-sal/compatibility/sal-compatibility/pom.xml
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryMapping.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryMapping.xtend [deleted file]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryNotificationProvider.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeConnectorDataChangeListener.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.xtend [deleted file]
opendaylight/md-sal/forwardingrules-manager/pom.xml
opendaylight/md-sal/inventory-manager/pom.xml
opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.xtend
opendaylight/md-sal/model/model-flow-management/pom.xml
opendaylight/md-sal/model/model-flow-statistics/pom.xml
opendaylight/md-sal/model/model-topology/pom.xml
opendaylight/md-sal/sal-binding-api/pom.xml
opendaylight/md-sal/sal-binding-broker/pom.xml
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/NotificationBrokerImpl.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/MapUtils.xtend
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/SimpleInput.java
opendaylight/md-sal/sal-binding-config/pom.xml
opendaylight/md-sal/sal-binding-dom-it/pom.xml
opendaylight/md-sal/sal-binding-it/pom.xml
opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java
opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/DataServiceTest.java
opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/RoutedServiceTest.java
opendaylight/md-sal/sal-binding-util/pom.xml
opendaylight/md-sal/sal-common-api/pom.xml
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/TransactionStatus.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChange.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeEvent.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeListener.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangePublisher.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataCommitHandler.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataModification.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataModificationTransactionFactory.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataProvider.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataReader.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataStore.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionChain.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionChainFactory.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/MutableRoutingTable.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RoutedRegistration.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RoutingTable.java
opendaylight/md-sal/sal-common-impl/pom.xml
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/RoutingUtils.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/TwoPhaseCommit.java
opendaylight/md-sal/sal-common-util/pom.xml
opendaylight/md-sal/sal-connector-api/pom.xml
opendaylight/md-sal/sal-dom-api/pom.xml
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java
opendaylight/md-sal/sal-dom-broker/pom.xml
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ConsumerContextImpl.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/RpcProvisionRegistryProxy.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/util/YangDataOperations.xtend
opendaylight/md-sal/sal-dom-spi/pom.xml
opendaylight/md-sal/sal-netconf-connector/pom.xml
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTwoPhaseCommitTransaction.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.xtend
opendaylight/md-sal/sal-rest-connector/pom.xml
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/MediaTypesTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestDeleteOperationTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestGetOperationTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestOperationUtils.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestPostOperationTest.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/websockets/test/RestStream.java
opendaylight/md-sal/sal-restconf-broker/pom.xml
opendaylight/md-sal/sal-restconf-broker/src/main/java/org/opendaylight/controller/sal/restconf/broker/event/RemoteDataChangeEvent.java
opendaylight/md-sal/sal-restconf-broker/src/main/java/org/opendaylight/controller/sal/restconf/broker/impl/NotificationServiceImpl.java
opendaylight/md-sal/samples/toaster-consumer/pom.xml
opendaylight/md-sal/samples/toaster-provider/pom.xml
opendaylight/md-sal/statistics-manager/pom.xml
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/AbstractListeningStatsTracker.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/AbstractStatsTracker.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowCapableContext.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowCapableTracker.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowStatsEntry.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowStatsTracker.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowTableStatsTracker.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/GroupDescStatsTracker.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/GroupStatsTracker.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MeterConfigStatsTracker.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MeterStatsTracker.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MultipartMessageManager.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeConnectorStatsTracker.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeStatisticsHandler.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/QueueStatsEntry.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/QueueStatsTracker.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/RPCFailedException.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsListener.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerActivator.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateHandler.java [deleted file]
opendaylight/md-sal/topology-lldp-discovery/pom.xml
opendaylight/md-sal/topology-manager/pom.xml
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/AbstractNetconfSession.java
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfSessionPreferences.java
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/jmx/CommitJMXNotification.java
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/jmx/DefaultCommitOperationMXBean.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/DefaultCommitNotificationProducer.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiator.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/MessageHeaderTest.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/MessageParserTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/MonitoringConstants.java
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/xml/model/MonitoringSession.java
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/xml/model/package-info.java
opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/xml/JaxBSerializerTest.java
opendaylight/netconf/netconf-ssh/pom.xml
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/threads/IOThread.java
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/SocketThread.java
opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/StubUserManager.java
opendaylight/netconf/netconf-util/pom.xml
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractChannelInitializer.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractNetconfSessionNegotiator.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/NetconfUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ChunkedFramingMechanismEncoder.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/EOMFramingMechanismEncoder.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/FramingMechanismHandlerFactory.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfChunkAggregator.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfEOMAggregator.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageAggregator.java with 79% similarity]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfHelloMessageToXMLEncoder.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageChunkDecoder.java [deleted file]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageToXMLEncoder.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfXMLToHelloMessageDecoder.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfXMLToMessageDecoder.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/SshHandler.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/authentication/LoginPassword.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/Invoker.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/SshClient.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/SshClientAdapter.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/SshSession.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/ChannelInputStream.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/ChannelOutputStream.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/VirtualSocket.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessageAdditionalHeader.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageConstants.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageHeader.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/SendErrorExceptionUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XMLNetconfUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfValidator.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageFactoryTest.java
opendaylight/northbound/connectionmanager/pom.xml
opendaylight/northbound/containermanager/pom.xml
opendaylight/northbound/controllermanager/pom.xml
opendaylight/northbound/flowprogrammer/pom.xml
opendaylight/northbound/hosttracker/pom.xml
opendaylight/northbound/java-client/pom.xml
opendaylight/northbound/networkconfiguration/bridgedomain/pom.xml
opendaylight/northbound/statistics/pom.xml
opendaylight/northbound/subnets/pom.xml
opendaylight/northbound/switchmanager/pom.xml
opendaylight/northbound/topology/pom.xml
opendaylight/northbound/usermanager/pom.xml
opendaylight/sal/implementation/pom.xml
opendaylight/samples/northbound/loadbalancer/pom.xml
opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleBroadcastHandlerImpl.java
opendaylight/statisticsmanager/implementation/src/main/java/org/opendaylight/controller/statisticsmanager/internal/StatisticsManager.java
opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java
opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/UserConfig.java
opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebAdmin.java
third-party/ganymed/pom.xml

index e4388c598fb0eec94a0bb6cdb8f070b4f328af2c..a6ee60f65d14b5f47b6f7a6cc2db9331f6847d51 100644 (file)
@@ -18,7 +18,7 @@ import org.opendaylight.controller.sal.utils.HexEncode;
  * ARP Reply event wrapper
  */
 public class ARPReply extends ARPEvent {
-
+    private static final long serialVersionUID = 1L;
     private final NodeConnector port;
     private final byte[] tMac;
     private final byte[] sMac;
index 1b125ddeb20a898e26344e3ee91065f339f6d661..051635ad53f85f5a2344b0f2b23905de958781c1 100644 (file)
@@ -19,6 +19,7 @@ import org.opendaylight.controller.switchmanager.Subnet;
  * specified host
  */
 public class ARPRequest extends ARPEvent {
+    private static final long serialVersionUID = 1L;
     private final Subnet subnet;
     private final HostNodeConnector host;
 
index 93845a356d40c5be253b01c1a30e6c0fcd8080a8..d32be92fc8f1bf40b0c53503781953bb0dc1bf7f 100644 (file)
        <artifactId>ietf-topology</artifactId>
        <version>${ietf-topology.version}</version>
       </dependency>
+      <dependency>
+       <groupId>org.opendaylight.yangtools.model</groupId>
+       <artifactId>ietf-topology-l3-unicast-igp</artifactId>
+       <version>${ietf-topology.version}</version>
+      </dependency>
       <dependency>
        <groupId>org.opendaylight.yangtools.model</groupId>
        <artifactId>opendaylight-l2-types</artifactId>
         <artifactId>concepts</artifactId>
         <version>${yangtools.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>restconf-client-api</artifactId>
+        <version>${yangtools.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>restconf-client-impl</artifactId>
+        <version>${yangtools.version}</version>
+      </dependency>
 
         <!--Netty-->
         <dependency>
           <artifactId>sal-binding-broker-impl</artifactId>
           <version>${mdsal.version}</version>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-binding-broker-impl</artifactId>
+          <version>${mdsal.version}</version>
+          <type>test-jar</type>
+          <scope>test</scope>
+        </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-compatibility</artifactId>
           <artifactId>statistics-manager</artifactId>
           <version>${mdsal.version}</version>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-remote</artifactId>
+          <version>${mdsal.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-restconf-broker</artifactId>
+          <version>${mdsal.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-binding-util</artifactId>
+          <version>${mdsal.version}</version>
+        </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>concepts</artifactId>
           <artifactId>config-persister-impl</artifactId>
           <version>${netconf.version}</version>
         </dependency>
+        <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>ietf-netconf-monitoring</artifactId>
+          <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>ietf-netconf-monitoring-extension</artifactId>
+          <version>${netconf.version}</version>
+        </dependency>
 
          <!-- threadpool -->
           <dependency>
                     <ignore />
                   </action>
                 </pluginExecution>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-enforcer-plugin</artifactId>
+                    <versionRange>${enforcer.version}</versionRange>
+                    <goals>
+                      <goal>enforce</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore />
+                  </action>
+                </pluginExecution>
               </pluginExecutions>
             </lifecycleMappingMetadata>
           </configuration>
index 9f9f811e889f85c20352db331187f008b812bd85..d41e8106c5aec85166b43d72241b7fb600921801 100644 (file)
@@ -8,6 +8,8 @@
 package org.opendaylight.protocol.framework;
 
 import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
 import io.netty.util.concurrent.Promise;
@@ -26,7 +28,7 @@ import com.google.common.base.Preconditions;
  * @param <S> Protocol session type, has to extend ProtocolSession<M>
  */
 public abstract class AbstractSessionNegotiator<M, S extends AbstractProtocolSession<?>> extends ChannelInboundHandlerAdapter implements SessionNegotiator<S> {
-    private final Logger logger = LoggerFactory.getLogger(AbstractSessionNegotiator.class);
+    private final Logger LOG = LoggerFactory.getLogger(AbstractSessionNegotiator.class);
     private final Promise<S> promise;
     protected final Channel channel;
 
@@ -39,42 +41,63 @@ public abstract class AbstractSessionNegotiator<M, S extends AbstractProtocolSes
     protected abstract void handleMessage(M msg) throws Exception;
 
     protected final void negotiationSuccessful(final S session) {
-        logger.debug("Negotiation on channel {} successful with session {}", channel, session);
+        LOG.debug("Negotiation on channel {} successful with session {}", channel, session);
         channel.pipeline().replace(this, "session", session);
         promise.setSuccess(session);
     }
 
     protected final void negotiationFailed(final Throwable cause) {
-        logger.debug("Negotiation on channel {} failed", channel, cause);
+        LOG.debug("Negotiation on channel {} failed", channel, cause);
         channel.close();
         promise.setFailure(cause);
     }
 
+    /**
+     * Send a message to peer and fail negotiation if it does not reach
+     * the peer.
+     *
+     * @param msg Message which should be sent.
+     */
+    protected final void sendMessage(final M msg) {
+        this.channel.writeAndFlush(msg).addListener(
+                new ChannelFutureListener() {
+                    @Override
+                    public void operationComplete(final ChannelFuture f) {
+                        if (!f.isSuccess()) {
+                            LOG.info("Failed to send message {}", msg, f.cause());
+                            negotiationFailed(f.cause());
+                        } else {
+                            LOG.trace("Message {} sent to socket", msg);
+                        }
+                    }
+                });
+    }
+
     @Override
     public final void channelActive(final ChannelHandlerContext ctx) {
-        logger.debug("Starting session negotiation on channel {}", channel);
+        LOG.debug("Starting session negotiation on channel {}", channel);
         try {
             startNegotiation();
         } catch (Exception e) {
-            logger.warn("Unexpected negotiation failure", e);
+            LOG.warn("Unexpected negotiation failure", e);
             negotiationFailed(e);
         }
     }
 
     @Override
     public final void channelRead(final ChannelHandlerContext ctx, final Object msg) {
-        logger.debug("Negotiation read invoked on channel {}", channel);
+        LOG.debug("Negotiation read invoked on channel {}", channel);
         try {
             handleMessage((M)msg);
         } catch (Exception e) {
-            logger.debug("Unexpected error while handling negotiation message {}", msg, e);
+            LOG.debug("Unexpected error while handling negotiation message {}", msg, e);
             negotiationFailed(e);
         }
     }
 
     @Override
     public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) {
-        logger.info("Unexpected error during negotiation", cause);
+        LOG.info("Unexpected error during negotiation", cause);
         negotiationFailed(cause);
     }
 }
index 67cf07cdf698f7d4b8f0da2f4bc7186a3b8fb8b7..a78274cca0ca4f49e3c14ce69e6e6815b7a7e395 100644 (file)
@@ -82,7 +82,8 @@ final class ProtocolSessionPromise<S extends ProtocolSession<?>> extends Default
                         }
 
                         if (!cf.isSuccess()) {
-                            LOG.warn("Attempt to connect to connect to {} failed", ProtocolSessionPromise.this.address, cf.cause());
+                            LOG.debug("Attempt to connect to {} failed", ProtocolSessionPromise.this.address, cf.cause());
+
                             final Future<Void> rf = ProtocolSessionPromise.this.strategy.scheduleReconnect(cf.cause());
                             rf.addListener(new FutureListener<Void>() {
                                 @Override
index f50f7693ad4933565cec219c6980ea712be069b6..52377ae0255e2466865419f15aa640cbd7dc4f70 100644 (file)
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>concepts</artifactId>
-            <version>${yangtools.version}</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-data-impl</artifactId>
-            <version>${yangtools.version}</version>
         </dependency>
     </dependencies>
 
index 301f00f7683082fef884a32535b6cc3936be29b4..92f7e27788884cae7f39ba969f62625a5eecd718 100644 (file)
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>config-persister-directory-adapter</artifactId>
-            <version>${config.version}</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>config-persister-directory-xml-adapter</artifactId>
-            <version>${config.version}</version>
         </dependency>
 
         <dependency>
index 36fa530062482e778e9fafc3dbcef0f29ad05cc5..2c5d2359a0633ab596d3920ac76b8ff29870a97b 100644 (file)
@@ -28,7 +28,6 @@
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>config-persister-file-xml-adapter</artifactId>
-            <version>${config.version}</version>
         </dependency>
 
         <dependency>
index 4c99c7770a4e3701719e9577fb5ccca7991c5924..13043458c0d097d0f6e936343480e77b63ad47be 100644 (file)
@@ -47,7 +47,7 @@ public class ConfigRegistryClientsTest {
     @Test
     public void testLookupRuntimeBeans() throws Exception {
         Set<ObjectName> jmxLookup = lookupRuntimeBeans(jmxRegistryClient);
-        assertEquals(Sets.newHashSet(testingRegistry.run2, testingRegistry.run1, testingRegistry.run3), jmxLookup);
+        assertEquals(Sets.newHashSet(TestingConfigRegistry.run2, TestingConfigRegistry.run1, TestingConfigRegistry.run3), jmxLookup);
     }
 
     private Set<ObjectName> lookupRuntimeBeans(ConfigRegistryClient client)
@@ -67,13 +67,13 @@ public class ConfigRegistryClientsTest {
                 jmxRegistryClient, TestingConfigRegistry.moduleName1,
                 TestingConfigRegistry.instName1);
         assertEquals(1, jmxLookup.size());
-        assertEquals(Sets.newHashSet(testingRegistry.run2), jmxLookup);
+        assertEquals(Sets.newHashSet(TestingConfigRegistry.run2), jmxLookup);
 
         jmxLookup = clientLookupRuntimeBeansWithModuleAndInstance(
                 jmxRegistryClient, TestingConfigRegistry.moduleName2,
                 TestingConfigRegistry.instName2);
         assertEquals(1, jmxLookup.size());
-        assertEquals(Sets.newHashSet(testingRegistry.run3), jmxLookup);
+        assertEquals(Sets.newHashSet(TestingConfigRegistry.run3), jmxLookup);
 
         jmxLookup = clientLookupRuntimeBeansWithModuleAndInstance(
                 jmxRegistryClient, TestingConfigRegistry.moduleName1,
index c1e0ccae31315a0d91438fdca2a18e2c050891f6..88afa1315545df59131bd13b66a5abe8e8957e19 100644 (file)
@@ -24,7 +24,6 @@
       <dependency>
          <groupId>org.opendaylight.controller</groupId>
          <artifactId>netty-config-api</artifactId>
-         <version>${project.version}</version>
       </dependency>
       <dependency>
          <groupId>org.slf4j</groupId>
index 3c52d8c17af7bfadba1d49e42a4d72b0b11459be..2c4c2117840e89f74e98f1e2ef94e27a56f72424 100644 (file)
  */
 package org.opendaylight.controller.config.yang.netty.eventexecutor;
 
-import io.netty.util.concurrent.AbstractEventExecutor;
+import com.google.common.reflect.AbstractInvocationHandler;
+import com.google.common.reflect.Reflection;
 import io.netty.util.concurrent.EventExecutor;
-import io.netty.util.concurrent.EventExecutorGroup;
-import io.netty.util.concurrent.Future;
 import io.netty.util.concurrent.GlobalEventExecutor;
-import io.netty.util.concurrent.ScheduledFuture;
 
-import java.util.concurrent.Callable;
+import java.lang.reflect.Method;
 import java.util.concurrent.TimeUnit;
 
-/**
-*
-*/
 public final class GlobalEventExecutorModule extends
         org.opendaylight.controller.config.yang.netty.eventexecutor.AbstractGlobalEventExecutorModule {
 
@@ -51,91 +46,35 @@ public final class GlobalEventExecutorModule extends
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-        return new GlobalEventExecutorCloseable(GlobalEventExecutor.INSTANCE);
+        final CloseableGlobalEventExecutorMixin closeableGlobalEventExecutorMixin =
+                new CloseableGlobalEventExecutorMixin(GlobalEventExecutor.INSTANCE);
+        return Reflection.newProxy(AutoCloseableEventExecutor.class, new AbstractInvocationHandler() {
+            @Override
+            protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable {
+                if (method.getName().equals("close")) {
+                    closeableGlobalEventExecutorMixin.close();
+                    return null;
+                } else {
+                    return method.invoke(GlobalEventExecutor.INSTANCE, args);
+                }
+            }
+        });
     }
 
-    static final private class GlobalEventExecutorCloseable extends AbstractEventExecutor implements AutoCloseable {
-
-        private EventExecutor executor;
-
-        public GlobalEventExecutorCloseable(EventExecutor executor) {
-            this.executor = executor;
-        }
-
-        @Override
-        public EventExecutorGroup parent() {
-            return this.executor.parent();
-        }
-
-        @Override
-        public boolean inEventLoop(Thread thread) {
-            return this.executor.inEventLoop(thread);
-        }
-
-        @Override
-        public boolean isShuttingDown() {
-            return this.executor.isShuttingDown();
-        }
-
-        @Override
-        public Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) {
-            return this.executor.shutdownGracefully(quietPeriod, timeout, unit);
-        }
-
-        @Override
-        public Future<?> terminationFuture() {
-            return this.executor.terminationFuture();
-        }
-
-        @Override
-        public boolean isShutdown() {
-            return this.executor.isShutdown();
-        }
+    public static interface AutoCloseableEventExecutor extends EventExecutor, AutoCloseable {
 
-        @Override
-        public boolean isTerminated() {
-            return this.executor.isTerminated();
-        }
-
-        @Override
-        public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
-            return this.executor.awaitTermination(timeout, unit);
-        }
-
-        @Override
-        public void execute(Runnable command) {
-            this.executor.execute(command);
-        }
-
-        @Override
-        public void close() throws Exception {
-            shutdownGracefully();
-        }
-
-        @SuppressWarnings("deprecation")
-        @Override
-        public void shutdown() {
-            this.executor.shutdown();
-        }
-
-        @Override
-        public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
-            return this.executor.scheduleWithFixedDelay(command, initialDelay, delay, unit);
-        }
+    }
 
-        @Override
-        public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
-            return this.executor.schedule(command, delay, unit);
-        }
+    public static class CloseableGlobalEventExecutorMixin implements AutoCloseable {
+        private final GlobalEventExecutor eventExecutor;
 
-        @Override
-        public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
-            return this.executor.schedule(callable, delay, unit);
+        public CloseableGlobalEventExecutorMixin(GlobalEventExecutor eventExecutor) {
+            this.eventExecutor = eventExecutor;
         }
 
         @Override
-        public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
-            return this.executor.scheduleAtFixedRate(command, initialDelay, period, unit);
+        public void close() {
+            eventExecutor.shutdownGracefully(0, 1, TimeUnit.SECONDS);
         }
     }
 }
index c03ade8b5fc63aded18e2540360723c639f82d11..1585bbf6de3752c77599a058bdd2b098303e8962 100644 (file)
@@ -7,21 +7,34 @@
  */
 
 /**
-* Generated file
-
-* Generated from: yang module name: netty-event-executor  yang module local name: netty-global-event-executor
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Tue Nov 12 10:44:21 CET 2013
-*
-* Do not modify this file unless it is present under src/main directory
-*/
+ * Generated file
+
+ * Generated from: yang module name: netty-event-executor  yang module local name: netty-global-event-executor
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Tue Nov 12 10:44:21 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
 package org.opendaylight.controller.config.yang.netty.eventexecutor;
 
-/**
-*
-*/
-public class GlobalEventExecutorModuleFactory extends org.opendaylight.controller.config.yang.netty.eventexecutor.AbstractGlobalEventExecutorModuleFactory
-{
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.osgi.framework.BundleContext;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+public class GlobalEventExecutorModuleFactory extends org.opendaylight.controller.config.yang.netty.eventexecutor.AbstractGlobalEventExecutorModuleFactory {
+    public static final String SINGLETON_NAME = "singleton";
+
 
+    @Override
+    public GlobalEventExecutorModule instantiateModule(String instanceName, DependencyResolver dependencyResolver, GlobalEventExecutorModule oldModule, AutoCloseable oldInstance, BundleContext bundleContext) {
+        checkArgument(SINGLETON_NAME.equals(instanceName),"Illegal instance name '" + instanceName + "', only allowed name is " + SINGLETON_NAME);
+        return super.instantiateModule(instanceName, dependencyResolver, oldModule, oldInstance, bundleContext);
+    }
 
+    @Override
+    public GlobalEventExecutorModule instantiateModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
+        checkArgument(SINGLETON_NAME.equals(instanceName),"Illegal instance name '" + instanceName + "', only allowed name is " + SINGLETON_NAME);
+        return super.instantiateModule(instanceName, dependencyResolver, bundleContext);
+    }
 }
index 71c4b192e5ae3c0c64dcb0d1f43770ddf8fb9d89..f29895c6d00c3428c0329b5aae5be1d494b2530f 100644 (file)
@@ -8,9 +8,6 @@
 
 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;
@@ -20,10 +17,16 @@ 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 javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
 public class GlobalEventExecutorModuleTest extends AbstractConfigTest {
 
     private GlobalEventExecutorModuleFactory factory;
-    private final String instanceName = "netty1";
+    private final String instanceName = GlobalEventExecutorModuleFactory.SINGLETON_NAME;
 
     @Before
     public void setUp() {
@@ -37,12 +40,23 @@ public class GlobalEventExecutorModuleTest extends AbstractConfigTest {
         ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
 
         createInstance(transaction, instanceName);
-        createInstance(transaction, instanceName + 2);
+
         transaction.validateConfig();
         CommitStatus status = transaction.commit();
 
-        assertBeanCount(2, factory.getImplementationName());
-        assertStatus(status, 2, 0, 0);
+        assertBeanCount(1, factory.getImplementationName());
+        assertStatus(status, 1, 0, 0);
+    }
+
+    @Test
+    public void testConflictingName() throws Exception {
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        try {
+            createInstance(transaction, instanceName + "x");
+            fail();
+        }catch(IllegalArgumentException e){
+            assertTrue(e.getMessage() + " failure", e.getMessage().contains("only allowed name is singleton"));
+        }
     }
 
     @Test
index 2e7777f91b6e2f4d5badf53bfd30c6f9fd4ef008..172fe7f1fcbb8fbf9dfbca593e67f4a2d0b00e56 100644 (file)
@@ -26,7 +26,6 @@
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>netty-config-api</artifactId>
-            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
index 3d5a3bf4adf00e78ce5537a884eeb3ad9142d42c..06c9ae885d15e13625c42746f13940a944b83271 100644 (file)
@@ -21,6 +21,8 @@ import io.netty.channel.nio.NioEventLoopGroup;
 
 import org.opendaylight.controller.config.api.JmxAttributeValidationException;
 
+import java.util.concurrent.TimeUnit;
+
 /**
 *
 */
@@ -61,7 +63,7 @@ public final class NettyThreadgroupModule extends org.opendaylight.controller.co
 
         @Override
         public void close() throws Exception {
-            shutdownGracefully();
+            shutdownGracefully(0, 1, TimeUnit.SECONDS);
         }
     }
 }
index 1e0c917032135e861ca35be4c95b5a4057dc373e..9d3b5505cefbf8cb5d2d3a5689ea50e03b033fc1 100644 (file)
       <dependency>
          <groupId>org.opendaylight.controller</groupId>
          <artifactId>netty-config-api</artifactId>
-         <version>${project.version}</version>
       </dependency>
       <dependency>
          <groupId>org.opendaylight.controller</groupId>
          <artifactId>threadpool-config-api</artifactId>
-         <version>${project.version}</version>
       </dependency>
       <dependency>
          <groupId>org.slf4j</groupId>
@@ -65,7 +63,6 @@
       <dependency>
          <groupId>org.opendaylight.controller</groupId>
          <artifactId>threadpool-config-impl</artifactId>
-         <version>${project.version}</version>
          <scope>test</scope>
       </dependency>
 
index 80621a4d449b0a2ccdee94ec865a8744f437735d..3474740ca178e659abd6a52e7ad78febb9eab556 100644 (file)
@@ -80,7 +80,6 @@
         <dependency>
             <groupId>ch.qos.logback</groupId>
             <artifactId>logback-classic</artifactId>
-            <version>${logback.version}</version>
             <scope>test</scope>
         </dependency>
     </dependencies>
             </plugins>
         </pluginManagement>
     </build>
-</project>
\ No newline at end of file
+</project>
index 584ea1766e2cd7ebaba141f7f02449473bec88b1..f9622192fec873f3fc01c1396aa4c06ccb8f1624 100644 (file)
@@ -82,6 +82,7 @@ class Impl implements ShutdownService {
 
 class StopSystemBundleThread extends Thread {
     private static final Logger logger = LoggerFactory.getLogger(StopSystemBundleThread.class);
+    public static final String CONFIG_MANAGER_SYMBOLIC_NAME = "org.opendaylight.controller.config-manager";
     private final Bundle systemBundle;
 
     StopSystemBundleThread(Bundle systemBundle) {
@@ -94,6 +95,14 @@ class StopSystemBundleThread extends Thread {
         try {
             // wait so that JMX response is received
             Thread.sleep(1000);
+            // first try to stop config-manager
+            Bundle configManager = findConfigManager();
+            if (configManager != null){
+                logger.debug("Stopping config-manager");
+                configManager.stop();
+                Thread.sleep(1000);
+            }
+            logger.debug("Stopping system bundle");
             systemBundle.stop();
         } catch (BundleException e) {
             logger.warn("Can not stop OSGi server", e);
@@ -101,6 +110,16 @@ class StopSystemBundleThread extends Thread {
             logger.warn("Shutdown process interrupted", e);
         }
     }
+
+    private Bundle findConfigManager() {
+        for(Bundle bundle: systemBundle.getBundleContext().getBundles()){
+            if (CONFIG_MANAGER_SYMBOLIC_NAME.equals(bundle.getSymbolicName())) {
+                return bundle;
+            }
+        }
+        return null;
+    }
+
 }
 
 class CallSystemExitThread extends Thread {
index 5887e98f30daa4816da2bfb1e1215a6385ebc783..d1abe08d52b64453ee038a8a8b053e80ae08c586 100644 (file)
@@ -18,6 +18,7 @@ import org.opendaylight.controller.config.manager.impl.factoriesresolver.ModuleF
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
 import org.osgi.framework.Bundle;
 
+import javax.management.InstanceNotFoundException;
 import javax.management.JMX;
 import javax.management.ObjectName;
 import java.util.Collections;
@@ -26,15 +27,14 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.opendaylight.controller.config.yang.shutdown.impl.ShutdownModuleFactory.NAME;
 
 public class ShutdownTest extends AbstractConfigTest {
     private final ShutdownModuleFactory factory = new ShutdownModuleFactory();
     @Mock
-    private Bundle mockedSysBundle;
+    private Bundle mockedSysBundle, mockedConfigManager;
+
 
     @Before
     public void setUp() throws Exception {
@@ -44,6 +44,13 @@ public class ShutdownTest extends AbstractConfigTest {
         doReturn(mockedSysBundle).when(mockedContext).getBundle(0);
         mockedContext.getBundle(0);
         doNothing().when(mockedSysBundle).stop();
+        doNothing().when(mockedConfigManager).stop();
+        doReturn(mockedContext).when(mockedSysBundle).getBundleContext();
+        doReturn(new Bundle[]{mockedSysBundle, mockedConfigManager}).when(mockedContext).getBundles();
+        doReturn("system bundle").when(mockedSysBundle).getSymbolicName();
+        doReturn(StopSystemBundleThread.CONFIG_MANAGER_SYMBOLIC_NAME).when(mockedConfigManager).getSymbolicName();
+
+
         ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
         // initialize default instance
         transaction.commit();
@@ -80,13 +87,22 @@ public class ShutdownTest extends AbstractConfigTest {
 
     @Test
     public void testWithSecret() throws Exception {
+        String secret = "secret";
+        setSecret(secret);
+        shutdownViaRuntimeJMX(secret);
+    }
+
+    private void setSecret(String secret) throws InstanceNotFoundException {
         ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
         ObjectName on = transaction.lookupConfigBean(NAME, NAME);
         ShutdownModuleMXBean proxy = transaction.newMXBeanProxy(on, ShutdownModuleMXBean.class);
-        String secret = "secret";
         proxy.setSecret(secret);
         transaction.commit();
-        shutdownViaRuntimeJMX(secret);
+    }
+
+    @Test
+    public void testWrongSecret() throws Exception {
+        setSecret("secret");
         try {
             ShutdownRuntimeMXBean runtime = JMX.newMXBeanProxy(platformMBeanServer, runtimeON, ShutdownRuntimeMXBean.class);
             runtime.shutdown("foo", 60000L, null);
@@ -109,12 +125,9 @@ public class ShutdownTest extends AbstractConfigTest {
         assertStopped();
     }
 
-
     private void assertStopped() throws Exception {
-        Thread.sleep(2000); // happens on another thread
+        Thread.sleep(3000); // happens on another thread
+        verify(mockedConfigManager).stop();
         verify(mockedSysBundle).stop();
-        verifyNoMoreInteractions(mockedSysBundle);
-        reset(mockedSysBundle);
-        doNothing().when(mockedSysBundle).stop();
     }
 }
index 5bcc5402afae09edbbe53eb58c3d077fba5fc2ce..0cc950af65d919ddeeef35029e8f45b6bc10157e 100644 (file)
@@ -7,52 +7,16 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.opendaylight.controller.config.yangjmxgenerator.attribute.AbstractDependencyAttribute;
+
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
-import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute;
-import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
-import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
-import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
-import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.FullyQualifiedNameHelper;
-import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.NameConflictException;
-import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.ModuleImport;
-import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.UsesNode;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static java.lang.String.format;
-import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants.createConfigQName;
 
 /**
  * Represents part of yang model that describes a module.
@@ -96,67 +60,34 @@ import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstant
  * </p>
  */
 public class ModuleMXBeanEntry extends AbstractEntry {
-    private static final Logger logger = LoggerFactory
-            .getLogger(ModuleMXBeanEntry.class);
-
-    // TODO: the XPath should be parsed by code generator IMO
-    private static final String MAGIC_STRING = "MAGIC_STRING";
-    private static final String MODULE_CONDITION_XPATH_TEMPLATE = "^/MAGIC_STRING:modules/MAGIC_STRING:module/MAGIC_STRING:type\\s*=\\s*['\"](.+)['\"]$";
-    private static final SchemaPath expectedConfigurationAugmentationSchemaPath = new SchemaPath(
-            Arrays.asList(createConfigQName("modules"),
-                    createConfigQName("module"),
-                    createConfigQName("configuration")), true);
-    private static final SchemaPath expectedStateAugmentationSchemaPath = new SchemaPath(
-            Arrays.asList(createConfigQName("modules"),
-                    createConfigQName("module"), createConfigQName("state")),
-            true);
-
-    private static final Pattern PREFIX_COLON_LOCAL_NAME = Pattern
-            .compile("^(.+):(.+)$");
 
     private static final String MODULE_SUFFIX = "Module";
     private static final String FACTORY_SUFFIX = MODULE_SUFFIX + "Factory";
     private static final String CLASS_NAME_SUFFIX = MODULE_SUFFIX + "MXBean";
     private static final String ABSTRACT_PREFIX = "Abstract";
 
-    /*
-     * threadpool-dynamic from the example above, taken from when condition, not
-     * the case name
-     */
-    private final String globallyUniqueName;
+    private final ModuleMXBeanEntryInitial initial;
 
     private Map<String, AttributeIfc> yangToAttributes;
 
-    private final String nullableDescription, packageName, javaNamePrefix,
-            namespace;
-
     private final Map<String, QName> providedServices;
 
     private Collection<RuntimeBeanEntry> runtimeBeans;
-    private final QName yangModuleQName;
-
-    public ModuleMXBeanEntry(IdentitySchemaNode id,
-            Map<String, AttributeIfc> yangToAttributes, String packageName,
-            Map<String, QName> providedServices2, String javaNamePrefix,
-            String namespace, Collection<RuntimeBeanEntry> runtimeBeans,
-            QName yangModuleQName) {
-        this.globallyUniqueName = id.getQName().getLocalName();
+
+    ModuleMXBeanEntry(ModuleMXBeanEntryInitial initials, Map<String, AttributeIfc> yangToAttributes,
+            Map<String, QName> providedServices2, Collection<RuntimeBeanEntry> runtimeBeans) {
         this.yangToAttributes = yangToAttributes;
-        this.nullableDescription = id.getDescription();
-        this.packageName = packageName;
-        this.javaNamePrefix = checkNotNull(javaNamePrefix);
-        this.namespace = checkNotNull(namespace);
         this.providedServices = Collections.unmodifiableMap(providedServices2);
         this.runtimeBeans = runtimeBeans;
-        this.yangModuleQName = yangModuleQName;
+        this.initial = initials;
     }
 
     public String getMXBeanInterfaceName() {
-        return javaNamePrefix + CLASS_NAME_SUFFIX;
+        return initial.javaNamePrefix + CLASS_NAME_SUFFIX;
     }
 
     public String getStubFactoryName() {
-        return javaNamePrefix + FACTORY_SUFFIX;
+        return initial.javaNamePrefix + FACTORY_SUFFIX;
     }
 
     public String getAbstractFactoryName() {
@@ -164,7 +95,7 @@ public class ModuleMXBeanEntry extends AbstractEntry {
     }
 
     public String getStubModuleName() {
-        return javaNamePrefix + MODULE_SUFFIX;
+        return initial.javaNamePrefix + MODULE_SUFFIX;
     }
 
     public String getAbstractModuleName() {
@@ -172,16 +103,16 @@ public class ModuleMXBeanEntry extends AbstractEntry {
     }
 
     public String getFullyQualifiedName(String typeName) {
-        return FullyQualifiedNameHelper.getFullyQualifiedName(packageName,
+        return FullyQualifiedNameHelper.getFullyQualifiedName(initial.packageName,
                 typeName);
     }
 
     public String getGloballyUniqueName() {
-        return globallyUniqueName;
+        return initial.localName;
     }
 
     public String getPackageName() {
-        return packageName;
+        return initial.packageName;
     }
 
     /**
@@ -202,31 +133,11 @@ public class ModuleMXBeanEntry extends AbstractEntry {
     }
 
     public String getJavaNamePrefix() {
-        return javaNamePrefix;
+        return initial.javaNamePrefix;
     }
 
     public String getNamespace() {
-        return namespace;
-    }
-
-    @VisibleForTesting
-    static Matcher getWhenConditionMatcher(String prefix,
-            RevisionAwareXPath whenConstraint) {
-        String xpathRegex = MODULE_CONDITION_XPATH_TEMPLATE.replace(
-                MAGIC_STRING, prefix);
-        Pattern pattern = Pattern.compile(xpathRegex);
-        return pattern.matcher(whenConstraint.toString());
-    }
-
-    static String getConfigModulePrefixFromImport(Module currentModule) {
-        for (ModuleImport currentImport : currentModule.getImports()) {
-            if (currentImport.getModuleName().equals(
-                    ConfigConstants.CONFIG_MODULE)) {
-                return currentImport.getPrefix();
-            }
-        }
-        throw new IllegalArgumentException("Cannot find import "
-                + ConfigConstants.CONFIG_MODULE + " in " + currentModule);
+        return initial.namespace;
     }
 
     /**
@@ -241,504 +152,93 @@ public class ModuleMXBeanEntry extends AbstractEntry {
             Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
             SchemaContext schemaContext,
             TypeProviderWrapper typeProviderWrapper, String packageName) {
-        Map<String, QName> uniqueGeneratedClassesNames = new HashMap<>();
-        logger.debug("Generating ModuleMXBeans of {} to package {}",
-                currentModule.getNamespace(), packageName);
-        String configModulePrefix;
-        try {
-            configModulePrefix = getConfigModulePrefixFromImport(currentModule);
-        } catch (IllegalArgumentException e) {
-            // this module does not import config module
-            return Collections.emptyMap();
-        }
 
-        // get identities of base config:module-type
-        Map<String, IdentitySchemaNode> moduleIdentities = new HashMap<>();
-
-        for (IdentitySchemaNode id : currentModule.getIdentities()) {
-            if (id.getBaseIdentity() != null
-                    && ConfigConstants.MODULE_TYPE_Q_NAME.equals(id
-                            .getBaseIdentity().getQName())) {
-                String identityLocalName = id.getQName().getLocalName();
-                if (moduleIdentities.containsKey(identityLocalName)) {
-                    throw new IllegalStateException(
-                            "Module name already defined in this module: "
-                                    + identityLocalName);
-                } else {
-                    moduleIdentities.put(identityLocalName, id);
-                    logger.debug("Found identity {}", identityLocalName);
-                }
-                // validation check on unknown schema nodes
-                boolean providedServiceWasSet = false;
-                for (UnknownSchemaNode unknownNode : id.getUnknownSchemaNodes()) {
-                    // TODO: test this
-                    if (ConfigConstants.PROVIDED_SERVICE_EXTENSION_QNAME
-                            .equals(unknownNode.getNodeType())) {
-                        // no op: 0 or more provided identities are allowed
-                    } else if (ConfigConstants.JAVA_NAME_PREFIX_EXTENSION_QNAME
-                            .equals(unknownNode.getNodeType())) {
-                        // 0..1 allowed
-                        checkState(
-                                providedServiceWasSet == false,
-                                format("More than one language extension %s is not allowed here: %s",
-                                        ConfigConstants.JAVA_NAME_PREFIX_EXTENSION_QNAME,
-                                        id));
-                        providedServiceWasSet = true;
-                    } else {
-                        throw new IllegalStateException(
-                                "Unexpected language extension "
-                                        + unknownNode.getNodeType());
-                    }
-                }
-            }
-        }
-        Map<String, ModuleMXBeanEntry> result = new HashMap<>();
-        // each module name should have an augmentation defined
-        Map<String, IdentitySchemaNode> unaugmentedModuleIdentities = new HashMap<>(
-                moduleIdentities);
-        for (AugmentationSchema augmentation : currentModule.getAugmentations()) {
-            Set<DataSchemaNode> childNodes = augmentation.getChildNodes();
-            if (childNodes.size() == 1) {
-                DataSchemaNode when = childNodes.iterator().next();
-                if (when instanceof ChoiceCaseNode) {
-                    ChoiceCaseNode choiceCaseNode = (ChoiceCaseNode) when;
-                    if (choiceCaseNode.getConstraints() == null
-                            || choiceCaseNode.getConstraints()
-                                    .getWhenCondition() == null) {
-                        continue;
-                    }
-                    RevisionAwareXPath xPath = choiceCaseNode.getConstraints()
-                            .getWhenCondition();
-                    Matcher matcher = getWhenConditionMatcher(
-                            configModulePrefix, xPath);
-                    if (matcher.matches() == false) {
-                        continue;
-                    }
-                    String moduleLocalNameFromXPath = matcher.group(1);
-                    IdentitySchemaNode moduleIdentity = moduleIdentities
-                            .get(moduleLocalNameFromXPath);
-                    unaugmentedModuleIdentities
-                            .remove(moduleLocalNameFromXPath);
-                    checkState(moduleIdentity != null, "Cannot find identity "
-                            + moduleLocalNameFromXPath
-                            + " matching augmentation " + augmentation);
-                    Map<String, QName> providedServices = findProvidedServices(
-                            moduleIdentity, currentModule, qNamesToSIEs,
-                            schemaContext);
-
-                    if (moduleIdentity == null) {
-                        throw new IllegalStateException(
-                                "Cannot find identity specified by augmentation xpath constraint: "
-                                        + moduleLocalNameFromXPath + " of "
-                                        + augmentation);
-                    }
-                    String javaNamePrefix = findJavaNamePrefix(moduleIdentity);
-
-                    Map<String, AttributeIfc> yangToAttributes = null;
-                    // runtime-data
-                    Collection<RuntimeBeanEntry> runtimeBeans = null;
-
-                    if (expectedConfigurationAugmentationSchemaPath
-                            .equals(augmentation.getTargetPath())) {
-                        logger.debug("Parsing configuration of {}",
-                                moduleLocalNameFromXPath);
-                        yangToAttributes = fillConfiguration(choiceCaseNode,
-                                currentModule, typeProviderWrapper,
-                                qNamesToSIEs, schemaContext, packageName);
-                        checkUniqueAttributesWithGeneratedClass(
-                                uniqueGeneratedClassesNames, when.getQName(),
-                                yangToAttributes);
-                    } else if (expectedStateAugmentationSchemaPath
-                            .equals(augmentation.getTargetPath())) {
-                        logger.debug("Parsing state of {}",
-                                moduleLocalNameFromXPath);
-                        try {
-                            runtimeBeans = fillRuntimeBeans(choiceCaseNode,
-                                    currentModule, typeProviderWrapper,
-                                    packageName, moduleLocalNameFromXPath,
-                                    javaNamePrefix);
-                        } catch (NameConflictException e) {
-                            throw new NameConflictException(
-                                    e.getConflictingName(), when.getQName(),
-                                    when.getQName());
-                        }
-                        checkUniqueRuntimeBeansGeneratedClasses(
-                                uniqueGeneratedClassesNames, when, runtimeBeans);
-                        Set<RuntimeBeanEntry> runtimeBeanEntryValues = Sets
-                                .newHashSet(runtimeBeans);
-                        for (RuntimeBeanEntry entry : runtimeBeanEntryValues) {
-                            checkUniqueAttributesWithGeneratedClass(
-                                    uniqueGeneratedClassesNames,
-                                    when.getQName(),
-                                    entry.getYangPropertiesToTypesMap());
-                        }
-
-                    } else {
-                        throw new IllegalArgumentException(
-                                "Cannot parse augmentation " + augmentation);
-                    }
-                    if (result.containsKey(moduleLocalNameFromXPath)) {
-                        // either fill runtimeBeans or yangToAttributes
-                        ModuleMXBeanEntry moduleMXBeanEntry = result
-                                .get(moduleLocalNameFromXPath);
-                        if (yangToAttributes != null
-                                && moduleMXBeanEntry.getAttributes() == null) {
-                            moduleMXBeanEntry
-                                    .setYangToAttributes(yangToAttributes);
-                        } else if (runtimeBeans != null
-                                && moduleMXBeanEntry.getRuntimeBeans() == null) {
-                            moduleMXBeanEntry.setRuntimeBeans(runtimeBeans);
-                        }
-                    } else {
-                        // construct ModuleMXBeanEntry
-                        ModuleMXBeanEntry moduleMXBeanEntry = new ModuleMXBeanEntry(
-                                moduleIdentity, yangToAttributes, packageName,
-                                providedServices, javaNamePrefix, currentModule
-                                        .getNamespace().toString(),
-                                runtimeBeans,
-                                ModuleUtil.getQName(currentModule));
-                        moduleMXBeanEntry.setYangModuleName(currentModule
-                                .getName());
-                        moduleMXBeanEntry
-                                .setYangModuleLocalname(moduleLocalNameFromXPath);
-                        result.put(moduleLocalNameFromXPath, moduleMXBeanEntry);
-                    }
-                } // skip if child node is not ChoiceCaseNode
-            } // skip if childNodes != 1
-        }
-        // clean up nulls
-        for (Entry<String, ModuleMXBeanEntry> entry : result.entrySet()) {
-            ModuleMXBeanEntry module = entry.getValue();
-            if (module.getAttributes() == null) {
-                module.setYangToAttributes(Collections
-                        .<String, AttributeIfc> emptyMap());
-            } else if (module.getRuntimeBeans() == null) {
-                module.setRuntimeBeans(Collections
-                        .<RuntimeBeanEntry> emptyList());
-            }
-        }
-        // check attributes name uniqueness
-        for (Entry<String, ModuleMXBeanEntry> entry : result.entrySet()) {
-            checkUniqueRuntimeBeanAttributesName(entry.getValue(),
-                    uniqueGeneratedClassesNames);
-        }
-        if (unaugmentedModuleIdentities.size() > 0) {
-            logger.warn("Augmentation not found for all module identities: {}",
-                    unaugmentedModuleIdentities.keySet());
-        }
+        ModuleMXBeanEntryBuilder builder = new ModuleMXBeanEntryBuilder().setModule(currentModule).setqNamesToSIEs(qNamesToSIEs)
+                .setSchemaContext(schemaContext).setTypeProviderWrapper(typeProviderWrapper)
+                .setPackageName(packageName);
 
-        logger.debug("Number of ModuleMXBeans to be generated: {}",
-                result.size());
-        return result;
+        return builder.build();
     }
 
-    private static void checkUniqueRuntimeBeansGeneratedClasses(
-            Map<String, QName> uniqueGeneratedClassesNames,
-            DataSchemaNode when, Collection<RuntimeBeanEntry> runtimeBeans) {
-        for (RuntimeBeanEntry runtimeBean : runtimeBeans) {
-            final String javaNameOfRuntimeMXBean = runtimeBean
-                    .getJavaNameOfRuntimeMXBean();
-            if (uniqueGeneratedClassesNames
-                    .containsKey(javaNameOfRuntimeMXBean)) {
-                QName firstDefinedQName = uniqueGeneratedClassesNames
-                        .get(javaNameOfRuntimeMXBean);
-                throw new NameConflictException(javaNameOfRuntimeMXBean,
-                        firstDefinedQName, when.getQName());
-            }
-            uniqueGeneratedClassesNames.put(javaNameOfRuntimeMXBean,
-                    when.getQName());
-        }
-    }
-
-    private static void checkUniqueRuntimeBeanAttributesName(
-            ModuleMXBeanEntry mxBeanEntry,
-            Map<String, QName> uniqueGeneratedClassesNames) {
-        for (RuntimeBeanEntry runtimeBeanEntry : mxBeanEntry.getRuntimeBeans()) {
-            for (String runtimeAttName : runtimeBeanEntry
-                    .getYangPropertiesToTypesMap().keySet()) {
-                if (mxBeanEntry.getAttributes().keySet()
-                        .contains(runtimeAttName)) {
-                    QName qName1 = uniqueGeneratedClassesNames
-                            .get(runtimeBeanEntry.getJavaNameOfRuntimeMXBean());
-                    QName qName2 = uniqueGeneratedClassesNames.get(mxBeanEntry
-                            .getGloballyUniqueName());
-                    throw new NameConflictException(runtimeAttName, qName1,
-                            qName2);
-                }
-            }
-        }
-    }
-
-    private static void checkUniqueAttributesWithGeneratedClass(
-            Map<String, QName> uniqueGeneratedClassNames, QName parentQName,
-            Map<String, AttributeIfc> yangToAttributes) {
-        for (Entry<String, AttributeIfc> attr : yangToAttributes.entrySet()) {
-            if (attr.getValue() instanceof TOAttribute) {
-                checkUniqueTOAttr(uniqueGeneratedClassNames, parentQName,
-                        (TOAttribute) attr.getValue());
-            } else if (attr.getValue() instanceof ListAttribute
-                    && ((ListAttribute) attr.getValue()).getInnerAttribute() instanceof TOAttribute) {
-                checkUniqueTOAttr(uniqueGeneratedClassNames, parentQName,
-                        (TOAttribute) ((ListAttribute) attr.getValue())
-                                .getInnerAttribute());
-            }
-        }
+    public Map<String, AttributeIfc> getAttributes() {
+        return yangToAttributes;
     }
 
-    private static void checkUniqueTOAttr(
-            Map<String, QName> uniqueGeneratedClassNames, QName parentQName,
-            TOAttribute attr) {
-        final String upperCaseCammelCase = attr.getUpperCaseCammelCase();
-        if (uniqueGeneratedClassNames.containsKey(upperCaseCammelCase)) {
-            QName firstDefinedQName = uniqueGeneratedClassNames
-                    .get(upperCaseCammelCase);
-            throw new NameConflictException(upperCaseCammelCase,
-                    firstDefinedQName, parentQName);
-        } else {
-            uniqueGeneratedClassNames.put(upperCaseCammelCase, parentQName);
-        }
+    void setYangToAttributes(Map<String, AttributeIfc> newAttributes) {
+        this.yangToAttributes = newAttributes;
     }
 
-    private static Collection<RuntimeBeanEntry> fillRuntimeBeans(
-            ChoiceCaseNode choiceCaseNode, Module currentModule,
-            TypeProviderWrapper typeProviderWrapper, String packageName,
-            String moduleLocalNameFromXPath, String javaNamePrefix) {
-
-        return RuntimeBeanEntry.extractClassNameToRuntimeBeanMap(packageName,
-                choiceCaseNode, moduleLocalNameFromXPath, typeProviderWrapper,
-                javaNamePrefix, currentModule).values();
-
+    public String getNullableDescription() {
+        return initial.description;
     }
 
-    private static Map<String, AttributeIfc> fillConfiguration(
-            ChoiceCaseNode choiceCaseNode, Module currentModule,
-            TypeProviderWrapper typeProviderWrapper,
-            Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
-            SchemaContext schemaContext, String packageName) {
-        Map<String, AttributeIfc> yangToAttributes = new HashMap<>();
-        for (DataSchemaNode attrNode : choiceCaseNode.getChildNodes()) {
-            AttributeIfc attributeValue = getAttributeValue(attrNode,
-                    currentModule, qNamesToSIEs, typeProviderWrapper,
-                    schemaContext, packageName);
-            yangToAttributes.put(attributeValue.getAttributeYangName(),
-                    attributeValue);
-        }
-        return yangToAttributes;
+    public QName getYangModuleQName() {
+        return initial.qName;
     }
 
-    private static Map<String, QName> findProvidedServices(
-            IdentitySchemaNode moduleIdentity, Module currentModule,
-            Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
-            SchemaContext schemaContext) {
-        Map<String, QName> result = new HashMap<>();
-        for (UnknownSchemaNode unknownNode : moduleIdentity
-                .getUnknownSchemaNodes()) {
-            if (ConfigConstants.PROVIDED_SERVICE_EXTENSION_QNAME
-                    .equals(unknownNode.getNodeType())) {
-                String prefixAndIdentityLocalName = unknownNode
-                        .getNodeParameter();
-                ServiceInterfaceEntry sie = findSIE(prefixAndIdentityLocalName,
-                        currentModule, qNamesToSIEs, schemaContext);
-                result.put(sie.getFullyQualifiedName(), sie.getQName());
-            }
-        }
-        return result;
+    @Override
+    public String toString() {
+        return "ModuleMXBeanEntry{" + "globallyUniqueName='"
+                + initial.localName + '\'' + ", packageName='" + initial.packageName
+                + '\'' + '}';
     }
 
-    /**
-     * For input node, find if it contains config:java-name-prefix extension. If
-     * not found, convert local name of node converted to cammel case.
-     */
-    public static String findJavaNamePrefix(SchemaNode schemaNode) {
-        return convertToJavaName(schemaNode, true);
-    }
+    static final class ModuleMXBeanEntryInitial {
 
-    public static String findJavaParameter(SchemaNode schemaNode) {
-        return convertToJavaName(schemaNode, false);
-    }
+        private String localName;
+        private String description;
+        private String packageName;
+        private String javaNamePrefix;
+        private String namespace;
+        private QName qName;
 
-    public static String convertToJavaName(SchemaNode schemaNode,
-            boolean capitalizeFirstLetter) {
-        for (UnknownSchemaNode unknownNode : schemaNode.getUnknownSchemaNodes()) {
-            if (ConfigConstants.JAVA_NAME_PREFIX_EXTENSION_QNAME
-                    .equals(unknownNode.getNodeType())) {
-                String value = unknownNode.getNodeParameter();
-                return convertToJavaName(value, capitalizeFirstLetter);
-            }
+        ModuleMXBeanEntryInitial(String localName, String description, String packageName, String javaNamePrefix, String namespace, QName qName) {
+            this.localName = localName;
+            this.description = description;
+            this.packageName = packageName;
+            this.javaNamePrefix = javaNamePrefix;
+            this.namespace = namespace;
+            this.qName = qName;
         }
-        return convertToJavaName(schemaNode.getQName().getLocalName(),
-                capitalizeFirstLetter);
     }
 
-    public static String convertToJavaName(String localName,
-            boolean capitalizeFirstLetter) {
-        if (capitalizeFirstLetter) {
-            return BindingGeneratorUtil.parseToClassName(localName);
-        } else {
-            return BindingGeneratorUtil.parseToValidParamName(localName);
-        }
-    }
+    static final class ModuleMXBeanEntryInitialBuilder {
+        private String localName;
+        private String description;
+        private String packageName;
+        private String javaNamePrefix;
+        private String namespace;
+        private QName qName;
 
-    private static int getChildNodeSizeWithoutUses(DataNodeContainer csn) {
-        int result = 0;
-        for (DataSchemaNode dsn : csn.getChildNodes()) {
-            if (dsn.isAddedByUses() == false) {
-                result++;
-            }
+        public ModuleMXBeanEntryInitialBuilder setPackageName(String packageName) {
+            this.packageName = packageName;
+            return this;
         }
-        return result;
-    }
 
-    private static AttributeIfc getAttributeValue(DataSchemaNode attrNode,
-            Module currentModule,
-            Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
-            TypeProviderWrapper typeProviderWrapper,
-            SchemaContext schemaContext, String packageName) {
-
-        if (attrNode instanceof LeafSchemaNode) {
-            // simple type
-            LeafSchemaNode leaf = (LeafSchemaNode) attrNode;
-            return new JavaAttribute(leaf, typeProviderWrapper);
-        } else if (attrNode instanceof ContainerSchemaNode) {
-            // reference or TO
-            ContainerSchemaNode containerSchemaNode = (ContainerSchemaNode) attrNode;
-            Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(
-                    containerSchemaNode, attrNode, currentModule, qNamesToSIEs,
-                    schemaContext);
-            if (dependencyAttributeOptional.isPresent()) {
-                return dependencyAttributeOptional.get();
-            } else {
-                return TOAttribute.create(containerSchemaNode,
-                        typeProviderWrapper, packageName);
-            }
-
-        } else if (attrNode instanceof LeafListSchemaNode) {
-            return ListAttribute.create((LeafListSchemaNode) attrNode,
-                    typeProviderWrapper);
-        } else if (attrNode instanceof ListSchemaNode) {
-            ListSchemaNode listSchemaNode = (ListSchemaNode) attrNode;
-            Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(
-                    listSchemaNode, attrNode, currentModule, qNamesToSIEs,
-                    schemaContext);
-            if (dependencyAttributeOptional.isPresent()) {
-                return dependencyAttributeOptional.get();
-            } else {
-                return ListAttribute.create(listSchemaNode,
-                        typeProviderWrapper, packageName);
-            }
-        } else {
-            throw new UnsupportedOperationException(
-                    "Unknown configuration node " + attrNode.toString());
+        public ModuleMXBeanEntryInitialBuilder setJavaNamePrefix(String javaNamePrefix) {
+            this.javaNamePrefix = javaNamePrefix;
+            return this;
         }
-    }
 
-    private static Optional<? extends AbstractDependencyAttribute> extractDependency(
-            DataNodeContainer dataNodeContainer, DataSchemaNode attrNode,
-            Module currentModule,
-            Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
-            SchemaContext schemaContext) {
-        if (dataNodeContainer.getUses().size() == 1
-                && getChildNodeSizeWithoutUses(dataNodeContainer) == 0) {
-            // reference
-            UsesNode usesNode = dataNodeContainer.getUses().iterator().next();
-            checkState(usesNode.getRefines().size() == 1,
-                    "Unexpected 'refine' child node size of "
-                            + dataNodeContainer);
-            LeafSchemaNode refine = (LeafSchemaNode) usesNode.getRefines()
-                    .values().iterator().next();
-            checkState(refine.getUnknownSchemaNodes().size() == 1,
-                    "Unexpected unknown schema node size of " + refine);
-            UnknownSchemaNode requiredIdentity = refine.getUnknownSchemaNodes()
-                    .iterator().next();
-            checkState(
-                    ConfigConstants.REQUIRED_IDENTITY_EXTENSION_QNAME.equals(requiredIdentity
-                            .getNodeType()), "Unexpected language extension "
-                            + requiredIdentity);
-            String prefixAndIdentityLocalName = requiredIdentity
-                    .getNodeParameter();
-            // import should point to a module
-            ServiceInterfaceEntry serviceInterfaceEntry = findSIE(
-                    prefixAndIdentityLocalName, currentModule, qNamesToSIEs,
-                    schemaContext);
-            boolean mandatory = refine.getConstraints().isMandatory();
-            AbstractDependencyAttribute reference;
-            if (dataNodeContainer instanceof ContainerSchemaNode) {
-                reference = new DependencyAttribute(attrNode,
-                        serviceInterfaceEntry, mandatory,
-                        attrNode.getDescription());
-            } else {
-                reference = new ListDependenciesAttribute(attrNode,
-                        serviceInterfaceEntry, mandatory,
-                        attrNode.getDescription());
-            }
-            return Optional.of(reference);
+        public ModuleMXBeanEntryInitialBuilder setNamespace(String namespace) {
+            this.namespace = namespace;
+            return this;
         }
-        return Optional.absent();
-    }
 
-    private static ServiceInterfaceEntry findSIE(
-            String prefixAndIdentityLocalName, Module currentModule,
-            Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
-            SchemaContext schemaContext) {
-
-        Matcher m = PREFIX_COLON_LOCAL_NAME.matcher(prefixAndIdentityLocalName);
-        Module foundModule;
-        String localSIName;
-        if (m.matches()) {
-            // if there is a prefix, look for ModuleImport with this prefix. Get
-            // Module from SchemaContext
-            String prefix = m.group(1);
-            ModuleImport moduleImport = findModuleImport(currentModule, prefix);
-            foundModule = schemaContext.findModuleByName(
-                    moduleImport.getModuleName(), moduleImport.getRevision());
-            checkState(
-                    foundModule != null,
-                    format("Module not found in SchemaContext by %s",
-                            moduleImport));
-            localSIName = m.group(2);
-        } else {
-            foundModule = currentModule; // no prefix => SIE is in currentModule
-            localSIName = prefixAndIdentityLocalName;
+        public ModuleMXBeanEntryInitialBuilder setqName(QName qName) {
+            this.qName = qName;
+            return this;
         }
-        QName siQName = new QName(foundModule.getNamespace(),
-                foundModule.getRevision(), localSIName);
-        ServiceInterfaceEntry sie = qNamesToSIEs.get(siQName);
-        checkState(sie != null, "Cannot find referenced Service Interface by "
-                + prefixAndIdentityLocalName);
-        return sie;
-    }
 
-    private static ModuleImport findModuleImport(Module module, String prefix) {
-        for (ModuleImport moduleImport : module.getImports()) {
-            if (moduleImport.getPrefix().equals(prefix)) {
-                return moduleImport;
-            }
+        public ModuleMXBeanEntry.ModuleMXBeanEntryInitial build() {
+            return new ModuleMXBeanEntry.ModuleMXBeanEntryInitial(localName, description, packageName, javaNamePrefix, namespace, qName);
         }
-        throw new IllegalStateException(format(
-                "Import not found with prefix %s in %s", prefix, module));
-    }
 
-    public Map<String, AttributeIfc> getAttributes() {
-        return yangToAttributes;
-    }
-
-    private void setYangToAttributes(Map<String, AttributeIfc> newAttributes) {
-        this.yangToAttributes = newAttributes;
-
-    }
-
-    public String getNullableDescription() {
-        return nullableDescription;
-    }
-
-    public QName getYangModuleQName() {
-        return yangModuleQName;
-    }
+        public ModuleMXBeanEntryInitialBuilder setIdSchemaNode(IdentitySchemaNode idSchemaNode) {
+            this.localName = idSchemaNode.getQName().getLocalName();
+            this.description = idSchemaNode.getDescription();
+            return this;
+        }
 
-    @Override
-    public String toString() {
-        return "ModuleMXBeanEntry{" + "globallyUniqueName='"
-                + globallyUniqueName + '\'' + ", packageName='" + packageName
-                + '\'' + '}';
     }
 }
diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryBuilder.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryBuilder.java
new file mode 100644 (file)
index 0000000..4a9d551
--- /dev/null
@@ -0,0 +1,523 @@
+/*
+ * 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.yangjmxgenerator;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.AbstractDependencyAttribute;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.NameConflictException;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.ModuleImport;
+import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.UsesNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nullable;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static com.google.common.base.Preconditions.checkState;
+import static java.lang.String.format;
+import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants.createConfigQName;
+
+final class ModuleMXBeanEntryBuilder {
+
+    private Module currentModule;
+    private Map<QName, ServiceInterfaceEntry> qNamesToSIEs;
+    private SchemaContext schemaContext;
+    private TypeProviderWrapper typeProviderWrapper;
+    private String packageName;
+
+    public ModuleMXBeanEntryBuilder setModule(Module module) {
+        this.currentModule = module;
+        return this;
+    }
+
+    public ModuleMXBeanEntryBuilder setqNamesToSIEs(Map<QName, ServiceInterfaceEntry> qNamesToSIEs) {
+        this.qNamesToSIEs = qNamesToSIEs;
+        return this;
+    }
+
+    public ModuleMXBeanEntryBuilder setSchemaContext(SchemaContext schemaContext) {
+        this.schemaContext = schemaContext;
+        return this;
+    }
+
+    public ModuleMXBeanEntryBuilder setTypeProviderWrapper(TypeProviderWrapper typeProviderWrapper) {
+        this.typeProviderWrapper = typeProviderWrapper;
+        return this;
+    }
+
+    public ModuleMXBeanEntryBuilder setPackageName(String packageName) {
+        this.packageName = packageName;
+        return this;
+    }
+
+    private static final Logger logger = LoggerFactory
+            .getLogger(ModuleMXBeanEntryBuilder.class);
+
+    // TODO: the XPath should be parsed by code generator IMO
+    private static final String MAGIC_STRING = "MAGIC_STRING";
+    private static final String MODULE_CONDITION_XPATH_TEMPLATE = "^/MAGIC_STRING:modules/MAGIC_STRING:module/MAGIC_STRING:type\\s*=\\s*['\"](.+)['\"]$";
+    private static final SchemaPath expectedConfigurationAugmentationSchemaPath = new SchemaPath(
+            Arrays.asList(createConfigQName("modules"),
+                    createConfigQName("module"),
+                    createConfigQName("configuration")), true);
+    private static final SchemaPath expectedStateAugmentationSchemaPath = new SchemaPath(
+            Arrays.asList(createConfigQName("modules"),
+                    createConfigQName("module"), createConfigQName("state")),
+            true);
+    private static final Pattern PREFIX_COLON_LOCAL_NAME = Pattern
+            .compile("^(.+):(.+)$");
+
+
+    public Map<String, ModuleMXBeanEntry> build() {
+        logger.debug("Generating ModuleMXBeans of {} to package {}",
+                currentModule.getNamespace(), packageName);
+
+        String configModulePrefix;
+        try {
+            configModulePrefix = getConfigModulePrefixFromImport(currentModule);
+        } catch (IllegalArgumentException e) {
+            // this currentModule does not import config currentModule
+            return Collections.emptyMap();
+        }
+
+        // get identities of base config:currentModule-type
+        Map<String, IdentitySchemaNode> moduleIdentities =  getIdentityMap();
+
+        Map<String, QName> uniqueGeneratedClassesNames = new HashMap<>();
+
+        // each currentModule name should have an augmentation defined
+        Map<String, IdentitySchemaNode> unaugmentedModuleIdentities = new HashMap<>(
+                moduleIdentities);
+
+        Map<String, ModuleMXBeanEntry> result = new HashMap<>();
+
+        for (AugmentationSchema augmentation : currentModule.getAugmentations()) {
+            Set<DataSchemaNode> childNodes = augmentation.getChildNodes();
+            if (areAllChildrenChoiceCaseNodes(childNodes)) {
+                for (ChoiceCaseNode childCase : castChildNodesToChoiceCases(childNodes)) {
+                    // TODO refactor, extract to standalone builder class
+                    processChoiceCaseNode(result, uniqueGeneratedClassesNames, configModulePrefix, moduleIdentities,
+                            unaugmentedModuleIdentities, augmentation, childCase);
+                }
+            } // skip if child nodes are not all cases
+        }
+        // clean up nulls
+        cleanUpNulls(result);
+        // check attributes name uniqueness
+        checkAttributeNamesUniqueness(uniqueGeneratedClassesNames, result);
+        checkUnaugumentedIdentities(unaugmentedModuleIdentities);
+
+        logger.debug("Number of ModuleMXBeans to be generated: {}", result.size());
+
+        return result;
+    }
+
+    private static void cleanUpNulls(Map<String, ModuleMXBeanEntry> result) {
+        for (Map.Entry<String, ModuleMXBeanEntry> entry : result.entrySet()) {
+            ModuleMXBeanEntry module = entry.getValue();
+            if (module.getAttributes() == null) {
+                module.setYangToAttributes(Collections
+                        .<String, AttributeIfc> emptyMap());
+            } else if (module.getRuntimeBeans() == null) {
+                module.setRuntimeBeans(Collections
+                        .<RuntimeBeanEntry> emptyList());
+            }
+        }
+    }
+
+    private static void checkUnaugumentedIdentities(Map<String, IdentitySchemaNode> unaugmentedModuleIdentities) {
+        if (unaugmentedModuleIdentities.size() > 0) {
+            logger.warn("Augmentation not found for all currentModule identities: {}",
+                    unaugmentedModuleIdentities.keySet());
+        }
+    }
+
+    private static void checkAttributeNamesUniqueness(Map<String, QName> uniqueGeneratedClassesNames, Map<String, ModuleMXBeanEntry> result) {
+        for (Map.Entry<String, ModuleMXBeanEntry> entry : result.entrySet()) {
+            checkUniqueRuntimeBeanAttributesName(entry.getValue(),
+                    uniqueGeneratedClassesNames);
+        }
+    }
+
+    private Map<String, IdentitySchemaNode> getIdentityMap() {
+        Map<String, IdentitySchemaNode> moduleIdentities = Maps.newHashMap();
+
+        for (IdentitySchemaNode id : currentModule.getIdentities()) {
+            if (id.getBaseIdentity() != null
+                    && ConfigConstants.MODULE_TYPE_Q_NAME.equals(id.getBaseIdentity().getQName())) {
+                String identityLocalName = id.getQName().getLocalName();
+                if (moduleIdentities.containsKey(identityLocalName)) {
+                    throw new IllegalStateException("Module name already defined in this currentModule: "
+                            + identityLocalName);
+                } else {
+                    moduleIdentities.put(identityLocalName, id);
+                    logger.debug("Found identity {}", identityLocalName);
+                }
+                // validation check on unknown schema nodes
+                boolean providedServiceWasSet = false;
+                for (UnknownSchemaNode unknownNode : id.getUnknownSchemaNodes()) {
+                    // TODO: test this
+                    if (ConfigConstants.PROVIDED_SERVICE_EXTENSION_QNAME.equals(unknownNode.getNodeType())) {
+                        // no op: 0 or more provided identities are allowed
+                    } else if (ConfigConstants.JAVA_NAME_PREFIX_EXTENSION_QNAME.equals(unknownNode.getNodeType())) {
+                        // 0..1 allowed
+                        checkState(
+                                providedServiceWasSet == false,
+                                format("More than one language extension %s is not allowed here: %s",
+                                        ConfigConstants.JAVA_NAME_PREFIX_EXTENSION_QNAME, id));
+                        providedServiceWasSet = true;
+                    } else {
+                        throw new IllegalStateException("Unexpected language extension " + unknownNode.getNodeType());
+                    }
+                }
+            }
+        }
+
+        return moduleIdentities;
+    }
+
+    private Collection<ChoiceCaseNode> castChildNodesToChoiceCases(Set<DataSchemaNode> childNodes) {
+        return Collections2.transform(childNodes, new Function<DataSchemaNode, ChoiceCaseNode>() {
+            @Nullable
+            @Override
+            public ChoiceCaseNode apply(@Nullable DataSchemaNode input) {
+                return (ChoiceCaseNode) input;
+            }
+        });
+    }
+
+    private boolean areAllChildrenChoiceCaseNodes(Set<DataSchemaNode> childNodes) {
+        for (DataSchemaNode childNode : childNodes) {
+            if (childNode instanceof ChoiceCaseNode == false)
+                return false;
+        }
+        return true;
+    }
+
+    private void processChoiceCaseNode(Map<String, ModuleMXBeanEntry> result,
+            Map<String, QName> uniqueGeneratedClassesNames, String configModulePrefix,
+            Map<String, IdentitySchemaNode> moduleIdentities,
+            Map<String, IdentitySchemaNode> unaugmentedModuleIdentities, AugmentationSchema augmentation,
+            DataSchemaNode when) {
+
+        ChoiceCaseNode choiceCaseNode = (ChoiceCaseNode) when;
+        if (choiceCaseNode.getConstraints() == null || choiceCaseNode.getConstraints().getWhenCondition() == null) {
+            return;
+        }
+        RevisionAwareXPath xPath = choiceCaseNode.getConstraints().getWhenCondition();
+        Matcher matcher = getWhenConditionMatcher(configModulePrefix, xPath);
+        if (matcher.matches() == false) {
+            return;
+        }
+        String moduleLocalNameFromXPath = matcher.group(1);
+        IdentitySchemaNode moduleIdentity = moduleIdentities.get(moduleLocalNameFromXPath);
+        unaugmentedModuleIdentities.remove(moduleLocalNameFromXPath);
+        checkState(moduleIdentity != null, "Cannot find identity " + moduleLocalNameFromXPath
+                + " matching augmentation " + augmentation);
+        Map<String, QName> providedServices = findProvidedServices(moduleIdentity, currentModule, qNamesToSIEs,
+                schemaContext);
+
+        if (moduleIdentity == null) {
+            throw new IllegalStateException("Cannot find identity specified by augmentation xpath constraint: "
+                    + moduleLocalNameFromXPath + " of " + augmentation);
+        }
+        String javaNamePrefix = TypeProviderWrapper.findJavaNamePrefix(moduleIdentity);
+
+        Map<String, AttributeIfc> yangToAttributes = null;
+        // runtime-data
+        Collection<RuntimeBeanEntry> runtimeBeans = null;
+
+        if (expectedConfigurationAugmentationSchemaPath.equals(augmentation.getTargetPath())) {
+            logger.debug("Parsing configuration of {}", moduleLocalNameFromXPath);
+            yangToAttributes = fillConfiguration(choiceCaseNode, currentModule, typeProviderWrapper, qNamesToSIEs,
+                    schemaContext, packageName);
+            checkUniqueAttributesWithGeneratedClass(uniqueGeneratedClassesNames, when.getQName(), yangToAttributes);
+        } else if (expectedStateAugmentationSchemaPath.equals(augmentation.getTargetPath())) {
+            logger.debug("Parsing state of {}", moduleLocalNameFromXPath);
+            try {
+                runtimeBeans = fillRuntimeBeans(choiceCaseNode, currentModule, typeProviderWrapper, packageName,
+                        moduleLocalNameFromXPath, javaNamePrefix);
+            } catch (NameConflictException e) {
+                throw new NameConflictException(e.getConflictingName(), when.getQName(), when.getQName());
+            }
+            checkUniqueRuntimeBeansGeneratedClasses(uniqueGeneratedClassesNames, when, runtimeBeans);
+            Set<RuntimeBeanEntry> runtimeBeanEntryValues = Sets.newHashSet(runtimeBeans);
+            for (RuntimeBeanEntry entry : runtimeBeanEntryValues) {
+                checkUniqueAttributesWithGeneratedClass(uniqueGeneratedClassesNames, when.getQName(),
+                        entry.getYangPropertiesToTypesMap());
+            }
+
+        } else {
+            throw new IllegalArgumentException("Cannot parse augmentation " + augmentation);
+        }
+        if (result.containsKey(moduleLocalNameFromXPath)) {
+            // either fill runtimeBeans or yangToAttributes
+            ModuleMXBeanEntry moduleMXBeanEntry = result.get(moduleLocalNameFromXPath);
+            if (yangToAttributes != null && moduleMXBeanEntry.getAttributes() == null) {
+                moduleMXBeanEntry.setYangToAttributes(yangToAttributes);
+            } else if (runtimeBeans != null && moduleMXBeanEntry.getRuntimeBeans() == null) {
+                moduleMXBeanEntry.setRuntimeBeans(runtimeBeans);
+            }
+        } else {
+            ModuleMXBeanEntry.ModuleMXBeanEntryInitial initial = new ModuleMXBeanEntry.ModuleMXBeanEntryInitialBuilder()
+                    .setIdSchemaNode(moduleIdentity).setPackageName(packageName).setJavaNamePrefix(javaNamePrefix)
+                    .setNamespace(currentModule.getNamespace().toString()).setqName(ModuleUtil.getQName(currentModule))
+                    .build();
+
+            // construct ModuleMXBeanEntry
+            ModuleMXBeanEntry moduleMXBeanEntry = new ModuleMXBeanEntry(initial, yangToAttributes, providedServices,
+                    runtimeBeans);
+
+            moduleMXBeanEntry.setYangModuleName(currentModule.getName());
+            moduleMXBeanEntry.setYangModuleLocalname(moduleLocalNameFromXPath);
+            result.put(moduleLocalNameFromXPath, moduleMXBeanEntry);
+        }
+    }
+
+    private void checkUniqueRuntimeBeansGeneratedClasses(Map<String, QName> uniqueGeneratedClassesNames,
+            DataSchemaNode when, Collection<RuntimeBeanEntry> runtimeBeans) {
+        for (RuntimeBeanEntry runtimeBean : runtimeBeans) {
+            final String javaNameOfRuntimeMXBean = runtimeBean.getJavaNameOfRuntimeMXBean();
+            if (uniqueGeneratedClassesNames.containsKey(javaNameOfRuntimeMXBean)) {
+                QName firstDefinedQName = uniqueGeneratedClassesNames.get(javaNameOfRuntimeMXBean);
+                throw new NameConflictException(javaNameOfRuntimeMXBean, firstDefinedQName, when.getQName());
+            }
+            uniqueGeneratedClassesNames.put(javaNameOfRuntimeMXBean, when.getQName());
+        }
+    }
+
+    private static void checkUniqueRuntimeBeanAttributesName(ModuleMXBeanEntry mxBeanEntry,
+            Map<String, QName> uniqueGeneratedClassesNames) {
+        for (RuntimeBeanEntry runtimeBeanEntry : mxBeanEntry.getRuntimeBeans()) {
+            for (String runtimeAttName : runtimeBeanEntry.getYangPropertiesToTypesMap().keySet()) {
+                if (mxBeanEntry.getAttributes().keySet().contains(runtimeAttName)) {
+                    QName qName1 = uniqueGeneratedClassesNames.get(runtimeBeanEntry.getJavaNameOfRuntimeMXBean());
+                    QName qName2 = uniqueGeneratedClassesNames.get(mxBeanEntry.getGloballyUniqueName());
+                    throw new NameConflictException(runtimeAttName, qName1, qName2);
+                }
+            }
+        }
+    }
+
+    private void checkUniqueAttributesWithGeneratedClass(Map<String, QName> uniqueGeneratedClassNames,
+            QName parentQName, Map<String, AttributeIfc> yangToAttributes) {
+        for (Map.Entry<String, AttributeIfc> attr : yangToAttributes.entrySet()) {
+            if (attr.getValue() instanceof TOAttribute) {
+                checkUniqueTOAttr(uniqueGeneratedClassNames, parentQName, (TOAttribute) attr.getValue());
+            } else if (attr.getValue() instanceof ListAttribute
+                    && ((ListAttribute) attr.getValue()).getInnerAttribute() instanceof TOAttribute) {
+                checkUniqueTOAttr(uniqueGeneratedClassNames, parentQName,
+                        (TOAttribute) ((ListAttribute) attr.getValue()).getInnerAttribute());
+            }
+        }
+    }
+
+    private void checkUniqueTOAttr(Map<String, QName> uniqueGeneratedClassNames, QName parentQName, TOAttribute attr) {
+        final String upperCaseCammelCase = attr.getUpperCaseCammelCase();
+        if (uniqueGeneratedClassNames.containsKey(upperCaseCammelCase)) {
+            QName firstDefinedQName = uniqueGeneratedClassNames.get(upperCaseCammelCase);
+            throw new NameConflictException(upperCaseCammelCase, firstDefinedQName, parentQName);
+        } else {
+            uniqueGeneratedClassNames.put(upperCaseCammelCase, parentQName);
+        }
+    }
+
+    private Collection<RuntimeBeanEntry> fillRuntimeBeans(ChoiceCaseNode choiceCaseNode, Module currentModule,
+            TypeProviderWrapper typeProviderWrapper, String packageName, String moduleLocalNameFromXPath,
+            String javaNamePrefix) {
+
+        return RuntimeBeanEntry.extractClassNameToRuntimeBeanMap(packageName, choiceCaseNode, moduleLocalNameFromXPath,
+                typeProviderWrapper, javaNamePrefix, currentModule).values();
+
+    }
+
+    private Map<String, AttributeIfc> fillConfiguration(ChoiceCaseNode choiceCaseNode, Module currentModule,
+            TypeProviderWrapper typeProviderWrapper, Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
+            SchemaContext schemaContext, String packageName) {
+        Map<String, AttributeIfc> yangToAttributes = new HashMap<>();
+        for (DataSchemaNode attrNode : choiceCaseNode.getChildNodes()) {
+            AttributeIfc attributeValue = getAttributeValue(attrNode, currentModule, qNamesToSIEs, typeProviderWrapper,
+                    schemaContext, packageName);
+            yangToAttributes.put(attributeValue.getAttributeYangName(), attributeValue);
+        }
+        return yangToAttributes;
+    }
+
+    private Map<String, QName> findProvidedServices(IdentitySchemaNode moduleIdentity, Module currentModule,
+            Map<QName, ServiceInterfaceEntry> qNamesToSIEs, SchemaContext schemaContext) {
+        Map<String, QName> result = new HashMap<>();
+        for (UnknownSchemaNode unknownNode : moduleIdentity.getUnknownSchemaNodes()) {
+            if (ConfigConstants.PROVIDED_SERVICE_EXTENSION_QNAME.equals(unknownNode.getNodeType())) {
+                String prefixAndIdentityLocalName = unknownNode.getNodeParameter();
+                ServiceInterfaceEntry sie = findSIE(prefixAndIdentityLocalName, currentModule, qNamesToSIEs,
+                        schemaContext);
+                result.put(sie.getFullyQualifiedName(), sie.getQName());
+            }
+        }
+        return result;
+    }
+
+    private AttributeIfc getAttributeValue(DataSchemaNode attrNode, Module currentModule,
+            Map<QName, ServiceInterfaceEntry> qNamesToSIEs, TypeProviderWrapper typeProviderWrapper,
+            SchemaContext schemaContext, String packageName) {
+
+        if (attrNode instanceof LeafSchemaNode) {
+            // simple type
+            LeafSchemaNode leaf = (LeafSchemaNode) attrNode;
+            return new JavaAttribute(leaf, typeProviderWrapper);
+        } else if (attrNode instanceof ContainerSchemaNode) {
+            // reference or TO
+            ContainerSchemaNode containerSchemaNode = (ContainerSchemaNode) attrNode;
+            Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(
+                    containerSchemaNode, attrNode, currentModule, qNamesToSIEs, schemaContext);
+            if (dependencyAttributeOptional.isPresent()) {
+                return dependencyAttributeOptional.get();
+            } else {
+                return TOAttribute.create(containerSchemaNode, typeProviderWrapper, packageName);
+            }
+
+        } else if (attrNode instanceof LeafListSchemaNode) {
+            return ListAttribute.create((LeafListSchemaNode) attrNode, typeProviderWrapper);
+        } else if (attrNode instanceof ListSchemaNode) {
+            ListSchemaNode listSchemaNode = (ListSchemaNode) attrNode;
+            Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(
+                    listSchemaNode, attrNode, currentModule, qNamesToSIEs, schemaContext);
+            if (dependencyAttributeOptional.isPresent()) {
+                return dependencyAttributeOptional.get();
+            } else {
+                return ListAttribute.create(listSchemaNode, typeProviderWrapper, packageName);
+            }
+        } else {
+            throw new UnsupportedOperationException("Unknown configuration node " + attrNode.toString());
+        }
+    }
+
+    private Optional<? extends AbstractDependencyAttribute> extractDependency(DataNodeContainer dataNodeContainer,
+            DataSchemaNode attrNode, Module currentModule, Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
+            SchemaContext schemaContext) {
+        if (dataNodeContainer.getUses().size() == 1 && getChildNodeSizeWithoutUses(dataNodeContainer) == 0) {
+            // reference
+            UsesNode usesNode = dataNodeContainer.getUses().iterator().next();
+            checkState(usesNode.getRefines().size() == 1, "Unexpected 'refine' child node size of " + dataNodeContainer);
+            LeafSchemaNode refine = (LeafSchemaNode) usesNode.getRefines().values().iterator().next();
+            checkState(refine.getUnknownSchemaNodes().size() == 1, "Unexpected unknown schema node size of " + refine);
+            UnknownSchemaNode requiredIdentity = refine.getUnknownSchemaNodes().iterator().next();
+            checkState(ConfigConstants.REQUIRED_IDENTITY_EXTENSION_QNAME.equals(requiredIdentity.getNodeType()),
+                    "Unexpected language extension " + requiredIdentity);
+            String prefixAndIdentityLocalName = requiredIdentity.getNodeParameter();
+            // import should point to a module
+            ServiceInterfaceEntry serviceInterfaceEntry = findSIE(prefixAndIdentityLocalName, currentModule,
+                    qNamesToSIEs, schemaContext);
+            boolean mandatory = refine.getConstraints().isMandatory();
+            AbstractDependencyAttribute reference;
+            if (dataNodeContainer instanceof ContainerSchemaNode) {
+                reference = new DependencyAttribute(attrNode, serviceInterfaceEntry, mandatory,
+                        attrNode.getDescription());
+            } else {
+                reference = new ListDependenciesAttribute(attrNode, serviceInterfaceEntry, mandatory,
+                        attrNode.getDescription());
+            }
+            return Optional.of(reference);
+        }
+        return Optional.absent();
+    }
+
+    private int getChildNodeSizeWithoutUses(DataNodeContainer csn) {
+        int result = 0;
+        for (DataSchemaNode dsn : csn.getChildNodes()) {
+            if (dsn.isAddedByUses() == false) {
+                result++;
+            }
+        }
+        return result;
+    }
+
+    private ServiceInterfaceEntry findSIE(String prefixAndIdentityLocalName, Module currentModule,
+            Map<QName, ServiceInterfaceEntry> qNamesToSIEs, SchemaContext schemaContext) {
+
+        Matcher m = PREFIX_COLON_LOCAL_NAME.matcher(prefixAndIdentityLocalName);
+        Module foundModule;
+        String localSIName;
+        if (m.matches()) {
+            // if there is a prefix, look for ModuleImport with this prefix. Get
+            // Module from SchemaContext
+            String prefix = m.group(1);
+            ModuleImport moduleImport = findModuleImport(currentModule, prefix);
+            foundModule = schemaContext.findModuleByName(moduleImport.getModuleName(), moduleImport.getRevision());
+            checkState(foundModule != null, format("Module not found in SchemaContext by %s", moduleImport));
+            localSIName = m.group(2);
+        } else {
+            foundModule = currentModule; // no prefix => SIE is in currentModule
+            localSIName = prefixAndIdentityLocalName;
+        }
+        QName siQName = new QName(foundModule.getNamespace(), foundModule.getRevision(), localSIName);
+        ServiceInterfaceEntry sie = qNamesToSIEs.get(siQName);
+        checkState(sie != null, "Cannot find referenced Service Interface by " + prefixAndIdentityLocalName);
+        return sie;
+    }
+
+    private ModuleImport findModuleImport(Module module, String prefix) {
+        for (ModuleImport moduleImport : module.getImports()) {
+            if (moduleImport.getPrefix().equals(prefix)) {
+                return moduleImport;
+            }
+        }
+        throw new IllegalStateException(format("Import not found with prefix %s in %s", prefix, module));
+    }
+
+    @VisibleForTesting
+    static Matcher getWhenConditionMatcher(String prefix, RevisionAwareXPath whenConstraint) {
+        String xpathRegex = MODULE_CONDITION_XPATH_TEMPLATE.replace(MAGIC_STRING, prefix);
+        Pattern pattern = Pattern.compile(xpathRegex);
+        return pattern.matcher(whenConstraint.toString());
+    }
+
+    String getConfigModulePrefixFromImport(Module currentModule) {
+        for (ModuleImport currentImport : currentModule.getImports()) {
+            if (currentImport.getModuleName().equals(ConfigConstants.CONFIG_MODULE)) {
+                return currentImport.getPrefix();
+            }
+        }
+        throw new IllegalArgumentException("Cannot find import " + ConfigConstants.CONFIG_MODULE + " in "
+                + currentModule);
+    }
+
+}
index 4831545b39f82b024f7a7ac21a3794029fb2a8b0..cd14458b0fe6b44b76bb1e58513628f27ad8a80c 100644 (file)
@@ -272,7 +272,7 @@ public class RuntimeBeanEntry {
                 }
                 // convert RpcDefinition to Rpc
                 for (RpcDefinition rpcDefinition : rpcDefinitions) {
-                    String name = ModuleMXBeanEntry
+                    String name = TypeProviderWrapper
                             .findJavaParameter(rpcDefinition);
                     AttributeIfc returnType;
                     if (rpcDefinition.getOutput() == null
@@ -376,7 +376,7 @@ public class RuntimeBeanEntry {
                     "More than one key is not supported in " + listSchemaNode);
         }
 
-        String javaNamePrefix = ModuleMXBeanEntry
+        String javaNamePrefix = TypeProviderWrapper
                 .findJavaNamePrefix(listSchemaNode);
 
         RuntimeBeanEntry rbFromAttributes = new RuntimeBeanEntry(packageName,
index c43fead0fcd0f5aa7e281768e2da0020bf149918..3c8c8aa2f4190af52f4484e1bda534c73d74eabb 100644 (file)
@@ -7,12 +7,14 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator;
 
+import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
 import org.opendaylight.yangtools.sal.binding.generator.spi.TypeProvider;
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 
 public class TypeProviderWrapper {
     private final TypeProvider typeProvider;
@@ -21,6 +23,40 @@ public class TypeProviderWrapper {
         this.typeProvider = typeProvider;
     }
 
+    /**
+     * For input node, find if it contains config:java-name-prefix extension. If
+     * not found, convert local name of node converted to cammel case.
+     */
+    public static String findJavaNamePrefix(SchemaNode schemaNode) {
+        return convertToJavaName(schemaNode, true);
+    }
+
+    public static String findJavaParameter(SchemaNode schemaNode) {
+        return convertToJavaName(schemaNode, false);
+    }
+
+    public static String convertToJavaName(SchemaNode schemaNode,
+                                           boolean capitalizeFirstLetter) {
+        for (UnknownSchemaNode unknownNode : schemaNode.getUnknownSchemaNodes()) {
+            if (ConfigConstants.JAVA_NAME_PREFIX_EXTENSION_QNAME
+                    .equals(unknownNode.getNodeType())) {
+                String value = unknownNode.getNodeParameter();
+                return convertToJavaName(value, capitalizeFirstLetter);
+            }
+        }
+        return convertToJavaName(schemaNode.getQName().getLocalName(),
+                capitalizeFirstLetter);
+    }
+
+    public static String convertToJavaName(String localName,
+                                           boolean capitalizeFirstLetter) {
+        if (capitalizeFirstLetter) {
+            return BindingGeneratorUtil.parseToClassName(localName);
+        } else {
+            return BindingGeneratorUtil.parseToValidParamName(localName);
+        }
+    }
+
     public Type getType(LeafSchemaNode leaf) {
         TypeDefinition<?> type = leaf.getType();
         return getType(leaf, type);
index ba2edc4e31d867f1304a0108400cd41e2b7b43de..edfb4c59afe2c223685adeb487172ea85640a574 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator.attribute;
 
-import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
+import org.opendaylight.controller.config.yangjmxgenerator.TypeProviderWrapper;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 
 public abstract class AbstractAttribute implements AttributeIfc {
@@ -22,8 +22,8 @@ public abstract class AbstractAttribute implements AttributeIfc {
     AbstractAttribute(DataSchemaNode attrNode) {
         this.attributeYangName = getLocalName(attrNode);
         this.node = attrNode;
-        this.upperCaseCammelCase = ModuleMXBeanEntry.findJavaNamePrefix(node);
-        this.lowerCaseCammelCase = ModuleMXBeanEntry.findJavaParameter(node);
+        this.upperCaseCammelCase = TypeProviderWrapper.findJavaNamePrefix(node);
+        this.lowerCaseCammelCase = TypeProviderWrapper.findJavaParameter(node);
     }
 
     @Override
index 6a540b50b21dab04433dcb349eb905a9a2cd303b..84300cb81d1000571e5fb52070ebefa91c3c33e4 100644 (file)
@@ -11,7 +11,6 @@ import com.google.common.base.Function;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
-import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.TypeProviderWrapper;
 import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
@@ -121,7 +120,7 @@ public class TOAttribute extends AbstractAttribute implements TypedAttribute {
                 .entrySet()) {
 
             capitalizedPropertiesToTypesMap.put(
-                    ModuleMXBeanEntry.convertToJavaName(entry.getKey(), true),
+                    TypeProviderWrapper.convertToJavaName(entry.getKey(), true),
                     entry.getValue());
         }
         return capitalizedPropertiesToTypesMap;
@@ -133,7 +132,7 @@ public class TOAttribute extends AbstractAttribute implements TypedAttribute {
                 .entrySet()) {
 
             jmxPropertiesToTypesMap.put(
-                    ModuleMXBeanEntry.convertToJavaName(entry.getKey(), false),
+                    TypeProviderWrapper.convertToJavaName(entry.getKey(), false),
                     entry.getValue());
         }
         return jmxPropertiesToTypesMap;
index 9ea34ca2b8ed990c56c6c14988733e09d88e3995..8ca2bb5bc98247198a405fe8cb75bd42561f642e 100644 (file)
@@ -113,6 +113,9 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest {
                         , PACKAGE_NAME);
         Map<String, AttributeIfc> attributes = namesToMBEs.get("impl-netconf")
                 .getAttributes();
+
+        assertCorrectAttributesSize(namesToMBEs, attributes);
+
         //
         DependencyAttribute threadFactoryAttribute = (DependencyAttribute) attributes
                 .get("thread-factory");
@@ -132,6 +135,16 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest {
         assertThat(threadFactoryAttribute.getType().getName(), is("ObjectName"));
     }
 
+    private void assertCorrectAttributesSize(Map<String, ModuleMXBeanEntry> namesToMBEs, Map<String, AttributeIfc> attributes) {
+        assertEquals(14, attributes.size());
+        assertEquals(1, namesToMBEs.get("impl-netconf").getRuntimeBeans().size());
+        assertEquals(2, namesToMBEs.get("impl-netconf").getRuntimeBeans().iterator().next().getAttributes().size());
+
+        assertEquals(4, namesToMBEs.get("impl").getAttributes().size());
+        assertEquals(1, namesToMBEs.get("impl").getRuntimeBeans().size());
+        assertEquals(1, namesToMBEs.get("impl").getRuntimeBeans().iterator().next().getAttributes().size());
+    }
+
     protected RuntimeBeanEntry findFirstByYangName(
             Collection<RuntimeBeanEntry> runtimeBeans, String yangName) {
         for (RuntimeBeanEntry rb : runtimeBeans) {
@@ -155,7 +168,7 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest {
     private void assertMatches(String prefix, String input) {
         RevisionAwareXPath whenConstraint = mock(RevisionAwareXPath.class);
         doReturn(input).when(whenConstraint).toString();
-        Matcher output = ModuleMXBeanEntry.getWhenConditionMatcher(prefix,
+        Matcher output = ModuleMXBeanEntryBuilder.getWhenConditionMatcher(prefix,
                 whenConstraint);
         assertTrue(output.matches());
         assertEquals("threadpool-dynamic", output.group(1));
index 97078e033a9d7df46a4d28c2e129b20ccf98ef13..16085efbba2cf334692498f37d6f872ba5d51c0e 100644 (file)
@@ -8,8 +8,6 @@ module config-jmx-it-impl {
     import ietf-inet-types { prefix inet; revision-date 2010-09-24;}
     import config-threads { prefix th; revision-date 2013-04-09; }
 
-
-
     description
         "Testing IMPL";
 
@@ -67,19 +65,7 @@ module config-jmx-it-impl {
             }
 
         }
-    }
-
-    augment "/config:modules/config:module/config:state" {
-        case impl {
-            when "/config:modules/config:module/config:type = 'impl'";
-            // root runtime bean
-            leaf created-sessions {
-                type uint32;
-            }
-        }
-    }
 
-    augment "/config:modules/config:module/config:configuration" {
         case impl-netconf {
             when "/config:modules/config:module/config:type = 'impl-netconf'";
 
@@ -205,6 +191,14 @@ module config-jmx-it-impl {
     }
 
     augment "/config:modules/config:module/config:state" {
+        case impl {
+            when "/config:modules/config:module/config:type = 'impl'";
+            // root runtime bean
+            leaf created-sessions {
+                type uint32;
+            }
+        }
+
         case impl-netconf {
             when "/config:modules/config:module/config:type = 'impl-netconf'";
             // root runtime bean
@@ -212,6 +206,11 @@ module config-jmx-it-impl {
                 type uint32;
             }
 
+            leaf created-sessions-2 {
+                type uint32;
+            }
+
         }
     }
+
 }
index 9c6e98e57115f4026e3901ee70b0cc5ae1d4083c..9037ff0c0f4dd9e23835b8d91e62e0ebdf811223 100644 (file)
             <plugin>
                 <groupId>org.opendaylight.yangtools</groupId>
                 <artifactId>yang-maven-plugin</artifactId>
-                <version>${yangtools.version}</version>
                 <executions>
                     <execution>
                         <id>config</id>
index 2123f6b9eb9c1004d6dcc2dd34cf26726168c153..ee571b83e1c9c4e919eb688f0f965ab633219b21 100644 (file)
@@ -13,4 +13,12 @@ package org.opendaylight.controller.configuration;
  * Container configuration service
  */
 public interface IConfigurationContainerService extends IConfigurationServiceCommon {
+
+    /**
+     * Bundle will call this function to ask ContainerConfigurationService to provide the
+     * directory location of container
+     *
+     * @return The path to active container directory
+     */
+    String getConfigurationRoot();
 }
index e4d55d11fb39e126d2dbb99f0ceb0cb6672d7069..4c0f3a2da5f08b409e6c751e9e8828359ce7e850 100644 (file)
@@ -9,6 +9,7 @@
 
 package org.opendaylight.controller.configuration.internal;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.EnumSet;
@@ -25,6 +26,7 @@ import org.opendaylight.controller.clustering.services.IClusterServices;
 import org.opendaylight.controller.configuration.ConfigurationEvent;
 import org.opendaylight.controller.configuration.ConfigurationObject;
 import org.opendaylight.controller.configuration.IConfigurationAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
 import org.opendaylight.controller.configuration.IConfigurationService;
 import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.IObjectReader;
@@ -46,7 +48,7 @@ public class ConfigurationService implements IConfigurationService, ICacheUpdate
     private static final Logger logger = LoggerFactory
             .getLogger(ConfigurationService.class);
     public static final String SAVE_EVENT_CACHE = "config.event.save";
-    private static final Object ROOT = GlobalConstants.STARTUPHOME.toString();
+    private static final String ROOT = GlobalConstants.STARTUPHOME.toString();
     private IClusterGlobalServices clusterServices;
     private ConcurrentMap <ConfigurationEvent, String> configEvent;
     private Set<IConfigurationAware> configurationAwareList = Collections
@@ -105,21 +107,66 @@ public class ConfigurationService implements IConfigurationService, ICacheUpdate
         return saveConfigurationsInternal();
     }
 
+
+    private List<String> getContainerDirectoryList() {
+        List<String> containerList = new ArrayList<String>();
+        for (IConfigurationAware configurationAware : this.configurationAwareList) {
+            if (configurationAware instanceof IConfigurationContainerService) {
+                String containerFilePath = ((ContainerConfigurationService)configurationAware).getConfigurationRoot();
+                containerList.add(containerFilePath);
+            }
+        }
+        return containerList;
+    }
+
+    private void createContainerDirectory(IConfigurationAware configurationAware) {
+        String containerFilePath = ((ContainerConfigurationService) configurationAware).getConfigurationRoot();
+        if (!new File(containerFilePath).exists()) {
+            boolean created = new File(containerFilePath).mkdir();
+            if (!created) {
+               logger.error("Failed to create startup config directory: {}", containerFilePath);
+            }
+        }
+    }
+
+    private void clearStaleContainerDirectories() {
+        List<String> activeContainers = getContainerDirectoryList();
+        for (File file : new File(ROOT).listFiles()) {
+            if (file.isDirectory() && !activeContainers.contains(file.toPath() + File.separator)) {
+                logger.trace("Removing directory for container {}", file.getName());
+                for (File innerFile : file.listFiles()) {
+                      innerFile.delete();
+                }
+                boolean removed = file.delete();
+                if (!removed) {
+                   logger.warn("Failed to remove stale directory: {}", file.getName());
+                }
+            }
+        }
+    }
+
+
     private Status saveConfigurationsInternal() {
         boolean success = true;
         for (IConfigurationAware configurationAware : configurationAwareList) {
+            if (configurationAware instanceof IConfigurationContainerService) {
+                // Create directory for new containers
+                createContainerDirectory(configurationAware);
+            }
             Status status = configurationAware.saveConfiguration();
             if (!status.isSuccess()) {
                 success = false;
-                logger.warn("Failed to save config for {}",
-                        configurationAware.getClass().getName());
+                logger.warn("Failed to save config for {}", configurationAware.getClass().getName());
             }
         }
+        // Remove startup directories of containers that were removed from
+        // the configuration but not saved
+        clearStaleContainerDirectories();
+
         if (success) {
             return new Status(StatusCode.SUCCESS);
         } else {
-            return new Status(StatusCode.INTERNALERROR,
-                    "Failed to Save All Configurations");
+            return new Status(StatusCode.INTERNALERROR, "Failed to Save All Configurations");
         }
     }
 
index 9c1d391daa7b8e80eec73ce454e30a6b768efe4d..3e067254edb721cd6e5b7adb109c1e96badbadb2 100644 (file)
@@ -9,7 +9,6 @@
 
 package org.opendaylight.controller.configuration.internal;
 
-import java.io.File;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Dictionary;
@@ -52,14 +51,10 @@ public class ContainerConfigurationService implements IConfigurationContainerSer
     private static final Logger logger = LoggerFactory.getLogger(ContainerConfigurationService.class);
     private IClusterContainerServices clusterServices;
     private ConcurrentMap <ConfigurationEvent, String> containerConfigEvent;
-    /*
-     * Collection containing the configuration objects.
-     * This is configuration world: container names (also the map key)
-     * are maintained as they were configured by user, same case
-     */
+    // Directory which contains the startup files for this container
+    private String root;
     private Set<IConfigurationContainerAware> configurationAwareList = Collections
             .synchronizedSet(new HashSet<IConfigurationContainerAware>());
-    private String root;
     private ObjectReader objReader;
     private ObjectWriter objWriter;
 
@@ -93,14 +88,9 @@ public class ContainerConfigurationService implements IConfigurationContainerSer
 
     void init(Component c) {
         Dictionary<?, ?> props = c.getServiceProperties();
-        String containerName = (props != null) ? (String) props.get("containerName") : GlobalConstants.DEFAULT.toString();
-        root = String.format("%s%s/", GlobalConstants.STARTUPHOME.toString(), containerName);
-        if (!new File(root).exists()) {
-            boolean created = new File(root).mkdir();
-            if (!created) {
-                logger.error("Failed to create startup config directory for container {}", containerName);
-            }
-        }
+        String containerName = (props != null) ? (String) props.get("containerName") :
+            GlobalConstants.DEFAULT.toString();
+        root =  String.format("%s%s/", GlobalConstants.STARTUPHOME.toString(), containerName);
     }
 
     public void start() {
@@ -119,17 +109,18 @@ public class ContainerConfigurationService implements IConfigurationContainerSer
      * Function called by the dependency manager before Container is Stopped and Destroyed.
      */
     public void containerStop() {
-        // Remove container directory along with its startup files
-        File[] files = new File(root).listFiles();
-        for (File file : files) {
-            file.delete();
-        }
-        new File(root).delete();
+        // Do nothing
+    }
+
+    @Override
+    public String getConfigurationRoot() {
+        return root;
     }
 
     @Override
     public Status saveConfiguration() {
         boolean success = true;
+
         for (IConfigurationContainerAware configurationAware : configurationAwareList) {
             logger.trace("Save Config triggered for {}", configurationAware.getClass().getSimpleName());
 
index 7de43962cfd4a21b83d05e46fccb03bd71a2623b..3bd7ea1386fb0753d3f374188fb6dce0b7f86e85 100644 (file)
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>clustering.services</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>connectionmanager</artifactId>
-      <version>0.1.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.7.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal.connection</artifactId>
-      <version>0.1.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>equinoxSDK381</groupId>
index ad897fd6899b01a2645aee018198fd0b8742129a..0fee183b67b8c1be06725b310c4111fbf3f9f8a8 100644 (file)
@@ -9,7 +9,6 @@
 
 package org.opendaylight.controller.containermanager.internal;
 
-import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -751,26 +750,6 @@ public class ContainerManager extends Authorization<String> implements IContaine
         return status;
     }
 
-    private void removeComponentsStartUpfiles(String containerName) {
-        String startupLocation = String.format("./%s", GlobalConstants.STARTUPHOME.toString());
-        String containerPrint = String.format("_%s.", containerName.toLowerCase(Locale.ENGLISH));
-
-        File directory = new File(startupLocation);
-        String[] fileList = directory.list();
-
-        logger.trace("Deleting startup configuration files for container {}", containerName);
-        if (fileList != null) {
-            for (String fileName : fileList) {
-                if (fileName.contains(containerPrint)) {
-                    String fullPath = String.format("%s/%s", startupLocation, fileName);
-                    File file = new File(fullPath);
-                    boolean done = file.delete();
-                    logger.trace("{} {}", (done ? "Deleted: " : "Failed to delete: "), fileName);
-                }
-            }
-        }
-    }
-
     /**
      * Create and initialize default all resource group and create association
      * with default well known users and profiles, if not already learnt from
@@ -1013,19 +992,6 @@ public class ContainerManager extends Authorization<String> implements IContaine
         notifyContainerModeChange(delete, notifyLocal);
         // Notify listeners
         notifyContainerAwareListeners(container, delete);
-
-        /*
-         * This is a quick fix until configuration service becomes the
-         * centralized configuration management place. Here container manager
-         * will remove the startup files for all the bundles that are present in
-         * the container being deleted. Do the cleanup here in Container manger
-         * as do not want to put this temporary code in Configuration manager
-         * yet which is ODL.
-         */
-        if (delete) {
-            // TODO: remove when Config Mgr takes over
-            removeComponentsStartUpfiles(containerName);
-        }
     }
 
     private void notifyContainerEntryChangeInternal(String containerName, List<NodeConnector> ncList, UpdateType update, boolean notifyLocal) {
index fca4936c7f13a62a095b95fcc2dbe5b26a7c196b..79b9ccea832a26a5b295ef469d768f77717a0583 100644 (file)
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-common</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-common-util</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-netconf-connector</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-core-api</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-broker-impl</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
-          <dependency>
-              <groupId>org.opendaylight.controller</groupId>
-              <artifactId>sal-remote</artifactId>
-              <version>${mdsal.version}</version>
-          </dependency>
         <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-restconf-broker</artifactId>
-            <version>${mdsal.version}</version>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-remote</artifactId>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-restconf-broker</artifactId>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-core-spi</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-common-api</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-common-impl</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-binding-api</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-binding-config</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-binding-broker-impl</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-compatibility</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-connector-api</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-rest-connector</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller.model</groupId>
           <artifactId>model-inventory</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller.model</groupId>
           <artifactId>model-flow-base</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller.model</groupId>
           <artifactId>model-flow-service</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller.model</groupId>
           <artifactId>model-flow-statistics</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller.model</groupId>
           <artifactId>model-flow-management</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller.md</groupId>
           <artifactId>inventory-manager</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller.md</groupId>
           <artifactId>forwardingrules-manager</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller.md</groupId>
           <artifactId>topology-lldp-discovery</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller.md</groupId>
           <artifactId>topology-manager</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
-            <groupId>org.opendaylight.controller.model</groupId>
-            <artifactId>model-topology</artifactId>
-            <version>1.1-SNAPSHOT</version>
+          <groupId>org.opendaylight.controller.model</groupId>
+          <artifactId>model-topology</artifactId>
+          <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
          <groupId>org.opendaylight.yangtools.model</groupId>
          <artifactId>ietf-topology</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-binding-util</artifactId>
-            <version>1.1-SNAPSHOT</version>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-binding-util</artifactId>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller.md</groupId>
           <artifactId>statistics-manager</artifactId>
-          <version>${mdsal.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>concepts</artifactId>
-          <version>${concepts.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
         <dependency>
           <groupId>org.opendaylight.yangtools</groupId>
           <artifactId>concepts</artifactId>
-          <version>${yangtools.version}</version>
         </dependency>
-          <dependency>
-              <groupId>org.opendaylight.yangtools</groupId>
-              <artifactId>restconf-client-api</artifactId>
-              <version>${yangtools.version}</version>
-          </dependency>
-          <dependency>
-              <groupId>org.opendaylight.yangtools</groupId>
-              <artifactId>restconf-client-impl</artifactId>
-              <version>${yangtools.version}</version>
-          </dependency>
+        <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>restconf-client-api</artifactId>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>restconf-client-impl</artifactId>
+        </dependency>
 
         <!-- config-->
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>config-api</artifactId>
-          <version>${config.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>config-manager</artifactId>
-          <version>${config.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>yang-jmx-generator</artifactId>
-          <version>${config.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>yang-store-api</artifactId>
-          <version>${config.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>yang-store-impl</artifactId>
-          <version>${config.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>logback-config</artifactId>
-          <version>${config.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>config-persister-api</artifactId>
-          <version>${config.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>config-persister-file-adapter</artifactId>
-          <version>${config.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>config-persister-file-xml-adapter</artifactId>
-          <version>${config.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>config-persister-directory-adapter</artifactId>
-          <version>${config.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>config-persister-directory-xml-adapter</artifactId>
-          <version>${config.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>config-persister-directory-autodetect-adapter</artifactId>
-          <version>${config.version}</version>
         </dependency>
 
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>shutdown-api</artifactId>
-          <version>${config.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>shutdown-impl</artifactId>
-          <version>${config.version}</version>
         </dependency>
 
        <!-- Netconf -->
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>netconf-api</artifactId>
-          <version>${netconf.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>netconf-impl</artifactId>
-          <version>${netconf.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>netconf-util</artifactId>
-          <version>${netconf.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>netconf-client</artifactId>
-          <version>${netconf.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>netconf-mapping-api</artifactId>
-          <version>${netconf.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>netconf-ssh</artifactId>
-          <version>${netconf.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>config-netconf-connector</artifactId>
-          <version>${netconf.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>netconf-monitoring</artifactId>
-          <version>${netconf.version}</version>
         </dependency>
         <dependency>
           <groupId>${project.groupId}</groupId>
           <artifactId>ietf-netconf-monitoring</artifactId>
-          <version>${netconf.version}</version>
         </dependency>
         <dependency>
           <groupId>${project.groupId}</groupId>
           <artifactId>ietf-netconf-monitoring-extension</artifactId>
-          <version>${netconf.version}</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>config-persister-impl</artifactId>
-          <version>${netconf.version}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.servicemix.bundles</groupId>
           <dependency>
               <groupId>org.opendaylight.controller</groupId>
               <artifactId>threadpool-config-api</artifactId>
-              <version>${config.version}</version>
           </dependency>
           <dependency>
               <groupId>org.opendaylight.controller</groupId>
               <artifactId>netty-config-api</artifactId>
-              <version>${config.version}</version>
           </dependency>
           <dependency>
               <groupId>org.opendaylight.controller</groupId>
               <artifactId>threadpool-config-impl</artifactId>
-              <version>${config.version}</version>
           </dependency>
           <dependency>
               <groupId>org.opendaylight.controller</groupId>
               <artifactId>netty-threadgroup-config</artifactId>
-              <version>${config.version}</version>
           </dependency>
           <dependency>
               <groupId>org.opendaylight.controller</groupId>
               <artifactId>netty-event-executor-config</artifactId>
-              <version>${config.version}</version>
           </dependency>
           <dependency>
               <groupId>org.opendaylight.controller</groupId>
               <artifactId>netty-timer-config</artifactId>
-              <version>${config.version}</version>
           </dependency>
 
-
           <!-- toaster example I'm pretty sure we should trim -->
          <dependency>
           <groupId>org.opendaylight.controller.samples</groupId>
          <dependency>
           <groupId>org.opendaylight.yangtools</groupId>
           <artifactId>yang-binding</artifactId>
-          <version>${yangtools.version}</version>
          </dependency>
          <dependency>
           <groupId>org.opendaylight.yangtools</groupId>
          <dependency>
           <groupId>org.opendaylight.yangtools</groupId>
           <artifactId>yang-model-util</artifactId>
-          <version>${yangtools.version}</version>
          </dependency>
          <dependency>
           <groupId>org.opendaylight.yangtools</groupId>
index 1ddfe1c7f354d23162353e2dbaa046c8ea281c7d..99f8df358eaab4075aebecfd69e7349e79c5755d 100644 (file)
@@ -83,6 +83,7 @@ connection.scheme = ANY_CONTROLLER_ONE_MASTER
 
 # Embedded Tomcat configuration File
 org.eclipse.gemini.web.tomcat.config.path=configuration/tomcat-server.xml
+org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
 
 # Open Flow related system parameters
 # TCP port on which the controller is listening (default 6633)
index 9ba590820a04a1dfdcb403b3168ce6f336186c13..2365c700f9fe085c762b6e91cbe8396522487acc 100644 (file)
@@ -23,7 +23,7 @@
                 </module>
                 <module>
                     <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor">netty:netty-global-event-executor</type>
-                    <name>global-event-executor</name>
+                    <name>singleton</name>
                 </module>
             </modules>
             
@@ -43,7 +43,7 @@
                     <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-event-executor</type>
                     <instance>
                         <name>global-event-executor</name>
-                        <provider>/modules/module[type='netty-global-event-executor'][name='global-event-executor']</provider>
+                        <provider>/modules/module[type='netty-global-event-executor'][name='singleton']</provider>
                     </instance>
                 </service>
                 <service>
index 8db8a0b8fdb635769d8f1132ceb11fb56841ff1e..f7bbdc14aad9d36a402a62e35bb134a776abaa75 100644 (file)
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>configuration</artifactId>
-      <version>0.4.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>clustering.services</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.7.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal.connection</artifactId>
-      <version>0.1.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>forwardingrulesmanager</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>equinoxSDK381</groupId>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>connectionmanager</artifactId>
-      <version>0.1.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>containermanager</artifactId>
-      <version>0.5.2-SNAPSHOT</version>
     </dependency>
   </dependencies>
 </project>
index 41db8af590888ef46e220cc64a1b5fa52b370a3c..fc0ef32954db4df6396de30ad529cd6669b9ea4a 100644 (file)
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-common-util</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-binding-api</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-flow-management</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>forwardingrulesmanager</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-compatibility</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
 
   </dependencies>
index 46f1c4f57bc866c6bd05da749eb6e01a04ccf456..b7e193b59d76e0938ed1537b829422adc54f3d5b 100644 (file)
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common-util</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-api</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>switchmanager</artifactId>
-            <version>0.7.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>topologymanager</artifactId>
-            <version>0.4.2-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
             <artifactId>model-flow-management</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-util</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>forwardingrulesmanager</artifactId>
-            <version>0.5.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-compatibility</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
     </dependencies>
 </project>
index 606cf212e5f1a4ba408f5c76b489c5d40249b043..c5c5cd32c55da42f1c3beac4e369247a97e92dd4 100644 (file)
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal</artifactId>
-            <version>0.7.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
             <artifactId>model-flow-service</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common-util</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-api</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>com.google.guava</groupId>
index daef08949a8cdafc5099d24d96069647ea14d08a..6914ef3c43596359937ff2be900b6b01f26a3491 100644 (file)
@@ -18,7 +18,6 @@
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-flow-statistics</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-binding-util</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>clustering.services</artifactId>
-        <version>0.5.1-SNAPSHOT</version>
     </dependency>
   </dependencies>
   <packaging>bundle</packaging>
index a6fc4b0a23b609e30452bda7f8879b26ee436d06..a59c2c1636514dba415dc933774ec4c6d16353cf 100644 (file)
@@ -251,6 +251,7 @@ package class SalCompatibilityProvider implements BindingAwareProvider {
         topology.dataService = session.getSALService(DataProviderService)
         tpProvider.dataService = session.getSALService(DataProviderService)
 
+        inventory.start();
 
         tpProvider.start();
 
index fac12ee10d642f3acb0cad9057c699e10d9446fd..8a0874ee3123da1d919db48a5d32e476afb839fc 100644 (file)
@@ -199,9 +199,11 @@ class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowLi
     }
 
     private def Future<RpcResult<TransactionStatus>> internalModifyFlowAsync(Node node, Flow oldFlow, Flow newFlow, long rid) {
-        val flowId = getCache().remove(oldFlow);
+        var flowId = getCache().remove(oldFlow);
         if(flowId == null){
-            throw new IllegalArgumentException("oldFlow is unknown");
+            LOG.error("oldFlow not found in cache : " + oldFlow.hashCode);
+            flowId = UUID.randomUUID();
+            getCache().put(oldFlow, flowId);
         }
 
         getCache().put(newFlow, flowId);
@@ -212,7 +214,9 @@ class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowLi
     private def Future<RpcResult<TransactionStatus>> internalRemoveFlowAsync(Node node, Flow adflow, long rid){
         val flowId = getCache().remove(adflow);
         if(flowId == null){
-            throw new IllegalArgumentException("adflow is unknown");
+            //throw new IllegalArgumentException("adflow not found in cache : " + adflow.hashCode);
+            LOG.error("adflow not found in cache : " + adflow.hashCode);
+            return null;
         }
         val flow = adflow.toMDFlow(flowId.toString());
         val modification = this._dataBrokerService.beginTransaction();
@@ -227,6 +231,10 @@ class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowLi
     }
 
     private def toFutureStatus(Future<RpcResult<TransactionStatus>> future){
+        if(future == null){
+            return toStatus(true);
+        }
+
         try {
             val result = future.get();
             return toStatus(result);
index 60e43247c2810383f49b05a24699d14c1c1f355b..0c211fd0aa432547071654bda94233d69e2496c0 100644 (file)
@@ -11,6 +11,9 @@ import java.util.ArrayList
 import java.util.Collections
 import java.util.List
 import java.util.Set
+import java.util.ArrayList;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.Lock;
 import java.util.concurrent.CopyOnWriteArrayList;
 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService
@@ -76,17 +79,18 @@ import static extension org.opendaylight.controller.sal.compatibility.NodeMappin
 import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
 import java.util.concurrent.ConcurrentHashMap
 import java.util.Map
+import java.util.HashMap
 
 class InventoryAndReadAdapter implements IPluginInReadService,
-                                                                                        IPluginInInventoryService,
-                                                                                        OpendaylightInventoryListener,
-                                                                                        OpendaylightFlowStatisticsListener,
-                                                                                        OpendaylightFlowTableStatisticsListener,
-                                                                                        OpendaylightPortStatisticsListener {
+                                             IPluginInInventoryService,
+                                             OpendaylightInventoryListener,
+                                             OpendaylightFlowStatisticsListener,
+                                             OpendaylightFlowTableStatisticsListener,
+                                             OpendaylightPortStatisticsListener {
 
     private static val LOG = LoggerFactory.getLogger(InventoryAndReadAdapter);
 
-       private static val OPENFLOWV10_TABLE_ID = new Integer(0).shortValue;
+    private static val OPENFLOWV10_TABLE_ID = new Integer(0).shortValue;
     @Property
     DataBrokerService dataService;
 
@@ -111,21 +115,34 @@ class InventoryAndReadAdapter implements IPluginInReadService,
     @Property
     List<IPluginOutInventoryService> inventoryPublisher = new CopyOnWriteArrayList<IPluginOutInventoryService>();
 
-       def setInventoryPublisher(IPluginOutInventoryService listener){
+    private final InventoryNotificationProvider inventoryNotificationProvider = new InventoryNotificationProvider();
+
+    private final Map<InstanceIdentifier.PathArgument, List<InstanceIdentifier.PathArgument>> nodeToNodeConnectorsMap = new ConcurrentHashMap<InstanceIdentifier.PathArgument, List<InstanceIdentifier.PathArgument>>();
+
+    private final Lock nodeToNodeConnectorsLock = new ReentrantLock();
+
+
+    def start(){
+        inventoryNotificationProvider.dataProviderService = dataProviderService;
+        inventoryNotificationProvider.inventoryPublisher = inventoryPublisher;
+        // inventoryNotificationProvider.start();
+    }
+
+    def setInventoryPublisher(IPluginOutInventoryService listener){
         inventoryPublisher.add(listener);
-       }
+    }
 
-       def unsetInventoryPublisher(IPluginOutInventoryService listener){
+    def unsetInventoryPublisher(IPluginOutInventoryService listener){
         inventoryPublisher.remove(listener);
-       }
+    }
 
     def setReadPublisher(IPluginOutReadService listener) {
-       statisticsPublisher.add(listener);
+        statisticsPublisher.add(listener);
     }
     
     def unsetReadPublisher (IPluginOutReadService listener) {
-       if( listener != null)
-               statisticsPublisher.remove(listener);
+        if( listener != null)
+            statisticsPublisher.remove(listener);
     }
 
     protected def startChange() {
@@ -140,33 +157,33 @@ class InventoryAndReadAdapter implements IPluginInReadService,
     override readAllFlow(Node node, boolean cached) {
 
         val output = new ArrayList<FlowOnNode>();
-               val tableRef = InstanceIdentifier.builder(Nodes)
-                                                                               .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
-                                                       .augmentation(FlowCapableNode).child(Table, new TableKey(OPENFLOWV10_TABLE_ID)).toInstance();
-               
-               val it = this.startChange();
-               
-               val table= it.readConfigurationData(tableRef) as Table;
-               
-               if(table != null){
-                       LOG.trace("Number of flows installed in table 0 of node {} : {}",node,table.flow.size);
-                       
-                       for(flow : table.flow){
-                               
-                               val adsalFlow = ToSalConversionsUtils.toFlow(flow,node);
-                               val statsFromDataStore = flow.getAugmentation(FlowStatisticsData);
-                               
-                               if(statsFromDataStore != null){
-                                       val it = new FlowOnNode(adsalFlow);
-                                       byteCount =  statsFromDataStore.flowStatistics.byteCount.value.longValue;
-                                       packetCount = statsFromDataStore.flowStatistics.packetCount.value.longValue;
-                                       durationSeconds = statsFromDataStore.flowStatistics.duration.second.value.intValue;
-                                       durationNanoseconds = statsFromDataStore.flowStatistics.duration.nanosecond.value.intValue;
-                                       
-                                       output.add(it);
-                               }
-                       }
-               }
+        val tableRef = InstanceIdentifier.builder(Nodes)
+                                        .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
+                                        .augmentation(FlowCapableNode).child(Table, new TableKey(OPENFLOWV10_TABLE_ID)).toInstance();
+        
+        val it = this.startChange();
+        
+        val table= it.readConfigurationData(tableRef) as Table;
+        
+        if(table != null){
+            LOG.trace("Number of flows installed in table 0 of node {} : {}",node,table.flow.size);
+            
+            for(flow : table.flow){
+                
+                val adsalFlow = ToSalConversionsUtils.toFlow(flow,node);
+                val statsFromDataStore = flow.getAugmentation(FlowStatisticsData);
+                
+                if(statsFromDataStore != null){
+                    val it = new FlowOnNode(adsalFlow);
+                    byteCount =  statsFromDataStore.flowStatistics.byteCount.value.longValue;
+                    packetCount = statsFromDataStore.flowStatistics.packetCount.value.longValue;
+                    durationSeconds = statsFromDataStore.flowStatistics.duration.second.value.intValue;
+                    durationNanoseconds = statsFromDataStore.flowStatistics.duration.nanosecond.value.intValue;
+                    
+                    output.add(it);
+                }
+            }
+        }
         
         //TODO (main): Shell we send request to the switch? It will make async request to the switch.
         // Once plugin receive response, it will let adaptor know through onFlowStatisticsUpdate()
@@ -180,35 +197,35 @@ class InventoryAndReadAdapter implements IPluginInReadService,
     }
 
     override readAllNodeConnector(Node node, boolean cached) {
-       
-       val ret = new ArrayList<NodeConnectorStatistics>();
-               val nodeRef = InstanceIdentifier.builder(Nodes)
-                                                                       .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
-                                                                       .toInstance();
-               
-               val provider = this.startChange();
-               
-               val dsNode= provider.readConfigurationData(nodeRef) as org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-               
-               if(dsNode != null){
-                       
-                       for (dsNodeConnector : dsNode.nodeConnector){
-                               val nodeConnectorRef = InstanceIdentifier.builder(Nodes)
-                                                                       .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
-                                                                       .child(NodeConnector, dsNodeConnector.key)
-                                                                       .toInstance();
-                               
-                               val nodeConnectorFromDS = provider.readConfigurationData(nodeConnectorRef) as NodeConnector;
-                               
-                               if(nodeConnectorFromDS != null){
-                                       val nodeConnectorStatsFromDs = nodeConnectorFromDS.getAugmentation(FlowCapableNodeConnectorStatisticsData) as FlowCapableNodeConnectorStatistics;
-                                       
-                                       ret.add(toNodeConnectorStatistics(nodeConnectorStatsFromDs.flowCapableNodeConnectorStatistics,dsNode.id,dsNodeConnector.id));
-                               }
-                       }
-               }
-
-               //TODO: Refer TODO (main)
+        
+        val ret = new ArrayList<NodeConnectorStatistics>();
+        val nodeRef = InstanceIdentifier.builder(Nodes)
+                                    .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
+                                    .toInstance();
+        
+        val provider = this.startChange();
+        
+        val dsNode= provider.readConfigurationData(nodeRef) as org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+        
+         if(dsNode != null){
+             
+             for (dsNodeConnector : dsNode.nodeConnector){
+                val nodeConnectorRef = InstanceIdentifier.builder(Nodes)
+                                    .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
+                                    .child(NodeConnector, dsNodeConnector.key)
+                                    .toInstance();
+                 
+                 val nodeConnectorFromDS = provider.readConfigurationData(nodeConnectorRef) as NodeConnector;
+                 
+                 if(nodeConnectorFromDS != null){
+                     val nodeConnectorStatsFromDs = nodeConnectorFromDS.getAugmentation(FlowCapableNodeConnectorStatisticsData) as FlowCapableNodeConnectorStatistics;
+                     
+                    ret.add(toNodeConnectorStatistics(nodeConnectorStatsFromDs.flowCapableNodeConnectorStatistics,dsNode.id,dsNodeConnector.id));
+                 }
+             }
+         }
+
+        //TODO: Refer TODO (main)
         val input = new GetAllNodeConnectorsStatisticsInputBuilder();
         input.setNode(node.toNodeRef);
         nodeConnectorStatisticsService.getAllNodeConnectorsStatistics(input.build());
@@ -216,23 +233,23 @@ class InventoryAndReadAdapter implements IPluginInReadService,
     }
 
     override readAllNodeTable(Node node, boolean cached) {
-       val ret = new ArrayList<NodeTableStatistics>();
-       
-               val dsFlowCapableNode= readFlowCapableNode(node.toNodeRef)
-               
-               if(dsFlowCapableNode != null){
-                       
-                       for (table : dsFlowCapableNode.table){
-                               
-                               val tableStats = table.getAugmentation(FlowTableStatisticsData);
-                               
-                               if(tableStats != null){
-                                       ret.add(toNodeTableStatistics(tableStats.flowTableStatistics,table.id,node));
-                               }
-                       }
-               }
-
-               //TODO: Refer TODO (main)
+        val ret = new ArrayList<NodeTableStatistics>();
+        
+        val dsFlowCapableNode= readFlowCapableNode(node.toNodeRef)
+        
+         if(dsFlowCapableNode != null){
+             
+             for (table : dsFlowCapableNode.table){
+                 
+                 val tableStats = table.getAugmentation(FlowTableStatisticsData);
+                 
+                 if(tableStats != null){
+                     ret.add(toNodeTableStatistics(tableStats.flowTableStatistics,table.id,node));
+                 }
+             }
+         }
+
+        //TODO: Refer TODO (main)
         val input = new GetFlowTablesStatisticsInputBuilder();
         input.setNode(node.toNodeRef);
         flowTableStatisticsService.getFlowTablesStatistics(input.build);
@@ -241,39 +258,39 @@ class InventoryAndReadAdapter implements IPluginInReadService,
 
     override readDescription(Node node, boolean cached) {
         return toNodeDescription(node.toNodeRef);
-       }
+    }
 
     override readFlow(Node node, Flow targetFlow, boolean cached) {
-               var FlowOnNode ret= null;
-               
-               val tableRef = InstanceIdentifier.builder(Nodes)
-                                                                               .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
-                                                       .augmentation(FlowCapableNode).child(Table, new TableKey(OPENFLOWV10_TABLE_ID)).toInstance();
-               
-               val it = this.startChange();
-               
-               val table= it.readConfigurationData(tableRef) as Table;
-               
-               if(table != null){
-                       LOG.trace("Number of flows installed in table 0 of node {} : {}",node,table.flow.size);
-                       
-                       for(mdsalFlow : table.flow){
-                               if(FromSalConversionsUtils.flowEquals(mdsalFlow, MDFlowMapping.toMDSalflow(targetFlow))){
-                                       val statsFromDataStore = mdsalFlow.getAugmentation(FlowStatisticsData);
-                                       
-                                       if(statsFromDataStore != null){
-                                               LOG.debug("Found matching flow in the data store flow table ");
-                                               val it = new FlowOnNode(targetFlow);
-                                               byteCount =  statsFromDataStore.flowStatistics.byteCount.value.longValue;
-                                               packetCount = statsFromDataStore.flowStatistics.packetCount.value.longValue;
-                                               durationSeconds = statsFromDataStore.flowStatistics.duration.second.value.intValue;
-                                               durationNanoseconds = statsFromDataStore.flowStatistics.duration.nanosecond.value.intValue;
-                                               
-                                               ret = it;
-                                       }
-                               }                       
-                       }
-               }
+        var FlowOnNode ret= null;
+        
+        val tableRef = InstanceIdentifier.builder(Nodes)
+                                        .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
+                                        .augmentation(FlowCapableNode).child(Table, new TableKey(OPENFLOWV10_TABLE_ID)).toInstance();
+        
+        val it = this.startChange();
+        
+        val table= it.readConfigurationData(tableRef) as Table;
+        
+        if(table != null){
+            LOG.trace("Number of flows installed in table 0 of node {} : {}",node,table.flow.size);
+            
+            for(mdsalFlow : table.flow){
+                if(FromSalConversionsUtils.flowEquals(mdsalFlow, MDFlowMapping.toMDSalflow(targetFlow))){
+                    val statsFromDataStore = mdsalFlow.getAugmentation(FlowStatisticsData);
+                    
+                    if(statsFromDataStore != null){
+                        LOG.debug("Found matching flow in the data store flow table ");
+                        val it = new FlowOnNode(targetFlow);
+                        byteCount =  statsFromDataStore.flowStatistics.byteCount.value.longValue;
+                        packetCount = statsFromDataStore.flowStatistics.packetCount.value.longValue;
+                        durationSeconds = statsFromDataStore.flowStatistics.duration.second.value.intValue;
+                        durationNanoseconds = statsFromDataStore.flowStatistics.duration.nanosecond.value.intValue;
+                        
+                        ret = it;
+                    }
+                }            
+            }
+        }
         
         //TODO: Refer TODO (main)
         val input = new GetFlowStatisticsFromFlowTableInputBuilder;
@@ -282,30 +299,30 @@ class InventoryAndReadAdapter implements IPluginInReadService,
         flowStatisticsService.getFlowStatisticsFromFlowTable(input.build)
         
         return ret;
-       
+        
     }
 
     override readNodeConnector(org.opendaylight.controller.sal.core.NodeConnector connector, boolean cached) {
-       var NodeConnectorStatistics  nodeConnectorStatistics = null;
-       
-               val nodeConnectorRef = InstanceIdentifier.builder(Nodes)
-                                                                       .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(connector.node))
-                                                                       .child(NodeConnector, InventoryMapping.toNodeConnectorKey(connector))
-                                                                       .toInstance();
-               val provider = this.startChange();
-                               
-               val nodeConnectorFromDS = provider.readConfigurationData(nodeConnectorRef) as NodeConnector;
-                               
-               if(nodeConnectorFromDS != null){
-                       val nodeConnectorStatsFromDs = nodeConnectorFromDS.getAugmentation(FlowCapableNodeConnectorStatisticsData) as FlowCapableNodeConnectorStatistics;
-                       if(nodeConnectorStatsFromDs != null) {
-                               nodeConnectorStatistics = toNodeConnectorStatistics(nodeConnectorStatsFromDs.flowCapableNodeConnectorStatistics,
-                                                                                                                                               InventoryMapping.toNodeKey(connector.node).id,
-                                                                                                                                               InventoryMapping.toNodeConnectorKey(connector).id);
-                       }
-               }
-
-               //TODO: Refer TODO (main)
+        var NodeConnectorStatistics  nodeConnectorStatistics = null;
+    
+        val nodeConnectorRef = InstanceIdentifier.builder(Nodes)
+                                    .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(connector.node))
+                                    .child(NodeConnector, InventoryMapping.toNodeConnectorKey(connector))
+                                    .toInstance();
+         val provider = this.startChange();
+                 
+         val nodeConnectorFromDS = provider.readConfigurationData(nodeConnectorRef) as NodeConnector;
+                 
+         if(nodeConnectorFromDS != null){
+            val nodeConnectorStatsFromDs = nodeConnectorFromDS.getAugmentation(FlowCapableNodeConnectorStatisticsData) as FlowCapableNodeConnectorStatistics;
+            if(nodeConnectorStatsFromDs != null) {
+                nodeConnectorStatistics = toNodeConnectorStatistics(nodeConnectorStatsFromDs.flowCapableNodeConnectorStatistics,
+                                                                        InventoryMapping.toNodeKey(connector.node).id,
+                                                                        InventoryMapping.toNodeConnectorKey(connector).id);
+            }
+        }
+
+        //TODO: Refer TODO (main)
         val input = new GetNodeConnectorStatisticsInputBuilder();
         input.setNode(connector.node.toNodeRef);
         input.setNodeConnectorId(InventoryMapping.toNodeConnectorKey(connector).id);
@@ -314,25 +331,25 @@ class InventoryAndReadAdapter implements IPluginInReadService,
     }
 
     override readNodeTable(NodeTable nodeTable, boolean cached) {
-       var NodeTableStatistics nodeStats = null
-       
-       val tableRef = InstanceIdentifier.builder(Nodes)
-                                                                               .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(nodeTable.node))
-                                                       .augmentation(FlowCapableNode).child(Table, new TableKey(nodeTable.ID as Short)).toInstance();
-               
-               val it = this.startChange();
-               
-               val table= it.readConfigurationData(tableRef) as Table;
-               
-               if(table != null){
-                       val tableStats = table.getAugmentation(FlowTableStatisticsData);
-                               
-                       if(tableStats != null){
-                               nodeStats =  toNodeTableStatistics(tableStats.flowTableStatistics,table.id,nodeTable.node);
-                       }
-               }
-
-               //TODO: Refer TODO (main)
+        var NodeTableStatistics nodeStats = null
+        
+        val tableRef = InstanceIdentifier.builder(Nodes)
+                                        .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(nodeTable.node))
+                                        .augmentation(FlowCapableNode).child(Table, new TableKey(nodeTable.ID as Short)).toInstance();
+        
+        val it = this.startChange();
+        
+        val table= it.readConfigurationData(tableRef) as Table;
+        
+        if(table != null){
+            val tableStats = table.getAugmentation(FlowTableStatisticsData);
+                 
+             if(tableStats != null){
+                 nodeStats =  toNodeTableStatistics(tableStats.flowTableStatistics,table.id,nodeTable.node);
+            }
+        }
+
+        //TODO: Refer TODO (main)
         val input = new GetFlowTablesStatisticsInputBuilder();
         input.setNode(nodeTable.node.toNodeRef);
         flowTableStatisticsService.getFlowTablesStatistics(input.build);
@@ -341,19 +358,22 @@ class InventoryAndReadAdapter implements IPluginInReadService,
     }
 
     override onNodeConnectorRemoved(NodeConnectorRemoved update) {
-        // NOOP
+        // Never received
     }
 
     override onNodeRemoved(NodeRemoved notification) {
         val properties = Collections.<org.opendaylight.controller.sal.core.Property>emptySet();
 
+        removeNodeConnectors(notification.nodeRef.value);
+
         publishNodeUpdate(notification.nodeRef.toADNode, UpdateType.REMOVED, properties);
     }
 
     override onNodeConnectorUpdated(NodeConnectorUpdated update) {
         var updateType = UpdateType.CHANGED;
-        if ( this._dataService.readOperationalData(update.nodeConnectorRef.value as InstanceIdentifier<? extends DataObject>) == null ){
+        if(!isKnownNodeConnector(update.nodeConnectorRef.value)){
             updateType = UpdateType.ADDED;
+            recordNodeConnector(update.nodeConnectorRef.value);
         }
 
         var nodeConnector = update.nodeConnectorRef.toADNodeConnector
@@ -369,16 +389,16 @@ class InventoryAndReadAdapter implements IPluginInReadService,
             updateType = UpdateType.ADDED;
         }
         publishNodeUpdate(notification.nodeRef.toADNode, updateType, notification.toADNodeProperties);
-        
-               //Notify the listeners of IPluginOutReadService
-        
+
+        //Notify the listeners of IPluginOutReadService
+
         for (statsPublisher : statisticsPublisher){
-                       val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
+            val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
             val description = notification.nodeRef.toNodeDescription
             if(description != null) {
-                         statsPublisher.descriptionStatisticsUpdated(nodeRef.toADNode,description);
-                       }
-               }
+              statsPublisher.descriptionStatisticsUpdated(nodeRef.toADNode,description);
+            }
+        }
     }
 
     override getNodeProps() {
@@ -461,50 +481,50 @@ class InventoryAndReadAdapter implements IPluginInReadService,
 
     private def toNodeConnectorStatistics(
         org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.NodeConnectorStatistics nodeConnectorStatistics, NodeId nodeId, NodeConnectorId nodeConnectorId) {
-               
-                       val it = new NodeConnectorStatistics();
-                       
-                       receivePacketCount = nodeConnectorStatistics.packets.received.longValue;
-                       transmitPacketCount = nodeConnectorStatistics.packets.transmitted.longValue;
-                       
-                       receiveByteCount = nodeConnectorStatistics.bytes.received.longValue;
-                       transmitByteCount = nodeConnectorStatistics.bytes.transmitted.longValue;
-                       
-                       receiveDropCount = nodeConnectorStatistics.receiveDrops.longValue;
-                       transmitDropCount = nodeConnectorStatistics.transmitDrops.longValue;
-                       
-                       receiveErrorCount = nodeConnectorStatistics.receiveErrors.longValue;
-                       transmitErrorCount = nodeConnectorStatistics.transmitErrors.longValue;
-                       
-                       receiveFrameErrorCount = nodeConnectorStatistics.receiveFrameError.longValue;
-                       receiveOverRunErrorCount = nodeConnectorStatistics.receiveOverRunError.longValue;
-                       receiveCRCErrorCount = nodeConnectorStatistics.receiveCrcError.longValue;
-                       collisionCount = nodeConnectorStatistics.collisionCount.longValue;
-                       
-                       val nodeConnectorRef = InstanceIdentifier.builder(Nodes)
-                                                               .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(nodeId))
-                                                               .child(NodeConnector,new NodeConnectorKey(nodeConnectorId)).toInstance;
-                       
-                       nodeConnector = NodeMapping.toADNodeConnector(new NodeConnectorRef(nodeConnectorRef));
-                       
-                       return it;
-    }
-
-       private def toNodeTableStatistics(
-               FlowTableStatistics tableStats,
-               Short tableId,Node node){
-               var it = new NodeTableStatistics();
-               
-               activeCount = tableStats.activeFlows.value.intValue;
-               lookupCount = tableStats.packetsLookedUp.value.intValue;
-               matchedCount = tableStats.packetsMatched.value.intValue;
-               name = tableId.toString;
-               nodeTable = new NodeTable(NodeMapping.MD_SAL_TYPE,tableId,node);
-               return it;
-       }
-       
-       private def toNodeDescription(NodeRef nodeRef){
-               val capableNode = readFlowCapableNode(nodeRef);
+            
+            val it = new NodeConnectorStatistics();
+            
+            receivePacketCount = nodeConnectorStatistics.packets.received.longValue;
+            transmitPacketCount = nodeConnectorStatistics.packets.transmitted.longValue;
+            
+            receiveByteCount = nodeConnectorStatistics.bytes.received.longValue;
+            transmitByteCount = nodeConnectorStatistics.bytes.transmitted.longValue;
+            
+            receiveDropCount = nodeConnectorStatistics.receiveDrops.longValue;
+            transmitDropCount = nodeConnectorStatistics.transmitDrops.longValue;
+            
+            receiveErrorCount = nodeConnectorStatistics.receiveErrors.longValue;
+            transmitErrorCount = nodeConnectorStatistics.transmitErrors.longValue;
+            
+            receiveFrameErrorCount = nodeConnectorStatistics.receiveFrameError.longValue;
+            receiveOverRunErrorCount = nodeConnectorStatistics.receiveOverRunError.longValue;
+            receiveCRCErrorCount = nodeConnectorStatistics.receiveCrcError.longValue;
+            collisionCount = nodeConnectorStatistics.collisionCount.longValue;
+            
+            val nodeConnectorRef = InstanceIdentifier.builder(Nodes)
+                                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(nodeId))
+                                .child(NodeConnector,new NodeConnectorKey(nodeConnectorId)).toInstance;
+            
+            nodeConnector = NodeMapping.toADNodeConnector(new NodeConnectorRef(nodeConnectorRef));
+            
+            return it;
+    }
+
+    private def toNodeTableStatistics(
+        FlowTableStatistics tableStats,
+        Short tableId,Node node){
+        var it = new NodeTableStatistics();
+        
+        activeCount = tableStats.activeFlows.value.intValue;
+        lookupCount = tableStats.packetsLookedUp.value.intValue;
+        matchedCount = tableStats.packetsMatched.value.intValue;
+        name = tableId.toString;
+        nodeTable = new NodeTable(NodeMapping.MD_SAL_TYPE,tableId,node);
+        return it;
+    }
+    
+    private def toNodeDescription(NodeRef nodeRef){
+        val capableNode = readFlowCapableNode(nodeRef);
         if(capableNode !=null) {
             val it = new NodeDescription()
             manufacturer = capableNode.manufacturer
@@ -515,101 +535,148 @@ class InventoryAndReadAdapter implements IPluginInReadService,
             return it;
          }
          return null;
-       }
+    }
     
     
     def Edge toADEdge(Link link) {
         new Edge(link.source.toADNodeConnector,link.destination.toADNodeConnector)
     }
-       
-       /*
-        * OpendaylightFlowStatisticsListener interface implementation
-        */
-       override onAggregateFlowStatisticsUpdate(AggregateFlowStatisticsUpdate notification) {
+    
+    /*
+     * OpendaylightFlowStatisticsListener interface implementation
+     */
+    override onAggregateFlowStatisticsUpdate(AggregateFlowStatisticsUpdate notification) {
         //Ignoring this notification as there does not seem to be a way to bubble this up to AD-SAL
-       }
-       
-       override onFlowsStatisticsUpdate(FlowsStatisticsUpdate notification) {
-               
-               val adsalFlowsStatistics = new ArrayList<FlowOnNode>();
-               val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
-               
-               for(flowStats : notification.flowAndStatisticsMapList){
-                       if(flowStats.tableId == 0)
-                               adsalFlowsStatistics.add(toFlowOnNode(flowStats,nodeRef.toADNode));
-               }
-               
-               for (statsPublisher : statisticsPublisher){
-                       statsPublisher.nodeFlowStatisticsUpdated(nodeRef.toADNode,adsalFlowsStatistics);
-               }
-               
-       }
-       /*
-        * OpendaylightFlowTableStatisticsListener interface implementation
-        */     
-       override onFlowTableStatisticsUpdate(FlowTableStatisticsUpdate notification) {
-               var adsalFlowTableStatistics = new ArrayList<NodeTableStatistics>();
-               
-               for(stats : notification.flowTableAndStatisticsMap){
-                       if (stats.tableId.value == 0){
-                               val it = new NodeTableStatistics();
-                               activeCount = stats.activeFlows.value.intValue;
-                               lookupCount = stats.packetsLookedUp.value.longValue;
-                               matchedCount = stats.packetsMatched.value.longValue;
-                               
-                               adsalFlowTableStatistics.add(it);
-                       }
-               }
-               for (statsPublisher : statisticsPublisher){
-                       val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
-                       statsPublisher.nodeTableStatisticsUpdated(nodeRef.toADNode,adsalFlowTableStatistics);
-               }
-       }
-       
-       /*
-        * OpendaylightPortStatisticsUpdate interface implementation
-        */
-       override onNodeConnectorStatisticsUpdate(NodeConnectorStatisticsUpdate notification) {
-               
-               val adsalPortStatistics  = new ArrayList<NodeConnectorStatistics>();
-               
-               for(nodeConnectorStatistics : notification.nodeConnectorStatisticsAndPortNumberMap){
-                       adsalPortStatistics.add(toNodeConnectorStatistics(nodeConnectorStatistics,notification.id,nodeConnectorStatistics.nodeConnectorId));
-               }
-               
-               for (statsPublisher : statisticsPublisher){
-                       val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
-                       statsPublisher.nodeConnectorStatisticsUpdated(nodeRef.toADNode,adsalPortStatistics);
-               }
-               
-       }
-       
-       private static def toFlowOnNode (FlowAndStatisticsMapList flowAndStatsMap,Node node){
-               
-               val it = new FlowOnNode(ToSalConversionsUtils.toFlow(flowAndStatsMap,node));
-               
-               byteCount = flowAndStatsMap.byteCount.value.longValue;
-               packetCount = flowAndStatsMap.packetCount.value.longValue;
-               durationSeconds = flowAndStatsMap.duration.second.value.intValue;
-               durationNanoseconds = flowAndStatsMap.duration.nanosecond.value.intValue;
-               
-               return it;
-       }
-
-       override  getConfiguredNotConnectedNodes() {
+    }
+    
+    override onFlowsStatisticsUpdate(FlowsStatisticsUpdate notification) {
+        
+        val adsalFlowsStatistics = new ArrayList<FlowOnNode>();
+        val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
+        
+        for(flowStats : notification.flowAndStatisticsMapList){
+            if(flowStats.tableId == 0)
+                adsalFlowsStatistics.add(toFlowOnNode(flowStats,nodeRef.toADNode));
+        }
+        
+        for (statsPublisher : statisticsPublisher){
+            statsPublisher.nodeFlowStatisticsUpdated(nodeRef.toADNode,adsalFlowsStatistics);
+        }
+        
+    }
+    /*
+     * OpendaylightFlowTableStatisticsListener interface implementation
+     */    
+    override onFlowTableStatisticsUpdate(FlowTableStatisticsUpdate notification) {
+        var adsalFlowTableStatistics = new ArrayList<NodeTableStatistics>();
+        
+        for(stats : notification.flowTableAndStatisticsMap){
+            if (stats.tableId.value == 0){
+                val it = new NodeTableStatistics();
+                activeCount = stats.activeFlows.value.intValue;
+                lookupCount = stats.packetsLookedUp.value.longValue;
+                matchedCount = stats.packetsMatched.value.longValue;
+                
+                adsalFlowTableStatistics.add(it);
+            }
+        }
+        for (statsPublisher : statisticsPublisher){
+            val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
+            statsPublisher.nodeTableStatisticsUpdated(nodeRef.toADNode,adsalFlowTableStatistics);
+        }
+    }
+    
+    /*
+     * OpendaylightPortStatisticsUpdate interface implementation
+     */
+    override onNodeConnectorStatisticsUpdate(NodeConnectorStatisticsUpdate notification) {
+        
+        val adsalPortStatistics  = new ArrayList<NodeConnectorStatistics>();
+        
+        for(nodeConnectorStatistics : notification.nodeConnectorStatisticsAndPortNumberMap){
+            adsalPortStatistics.add(toNodeConnectorStatistics(nodeConnectorStatistics,notification.id,nodeConnectorStatistics.nodeConnectorId));
+        }
+        
+        for (statsPublisher : statisticsPublisher){
+            val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
+            statsPublisher.nodeConnectorStatisticsUpdated(nodeRef.toADNode,adsalPortStatistics);
+        }
+        
+    }
+    
+    private static def toFlowOnNode (FlowAndStatisticsMapList flowAndStatsMap,Node node){
+        
+        val it = new FlowOnNode(ToSalConversionsUtils.toFlow(flowAndStatsMap,node));
+        
+        byteCount = flowAndStatsMap.byteCount.value.longValue;
+        packetCount = flowAndStatsMap.packetCount.value.longValue;
+        durationSeconds = flowAndStatsMap.duration.second.value.intValue;
+        durationNanoseconds = flowAndStatsMap.duration.nanosecond.value.intValue;
+        
+        return it;
+    }
+
+    override  getConfiguredNotConnectedNodes() {
         return Collections.emptySet();
-       }
+    }
+
+
+    private def publishNodeUpdate(Node node, UpdateType updateType, Set<org.opendaylight.controller.sal.core.Property> properties){
+        for( publisher : inventoryPublisher){
+            publisher.updateNode(node, updateType, properties);
+        }
+    }
+
+    private def publishNodeConnectorUpdate(org.opendaylight.controller.sal.core.NodeConnector nodeConnector, UpdateType updateType, Set<org.opendaylight.controller.sal.core.Property> properties){
+        for( publisher : inventoryPublisher){
+            publisher.updateNodeConnector(nodeConnector, updateType, properties);
+        }
+    }
+
+    private def isKnownNodeConnector(InstanceIdentifier<? extends Object> nodeConnectorIdentifier){
+        if(nodeConnectorIdentifier.path.size() < 3) {
+            return false;
+        }
 
+        val nodePath = nodeConnectorIdentifier.path.get(1);
+        val nodeConnectorPath = nodeConnectorIdentifier.getPath().get(2);
 
-       private def publishNodeUpdate(Node node, UpdateType updateType, Set<org.opendaylight.controller.sal.core.Property> properties){
-           for( publisher : inventoryPublisher){
-               publisher.updateNode(node, updateType, properties);
-           }
-       }
+        val nodeConnectors = nodeToNodeConnectorsMap.get(nodePath);
 
-       private def publishNodeConnectorUpdate(org.opendaylight.controller.sal.core.NodeConnector nodeConnector, UpdateType updateType, Set<org.opendaylight.controller.sal.core.Property> properties){
-           for( publisher : inventoryPublisher){
-               publisher.updateNodeConnector(nodeConnector, updateType, properties);
-           }
-       }
+        if(nodeConnectors == null){
+            return false;
+        }
+        return nodeConnectors.contains(nodeConnectorPath);
+    }
+
+
+    private def recordNodeConnector(InstanceIdentifier<? extends Object> nodeConnectorIdentifier){
+        if(nodeConnectorIdentifier.path.size() < 3) {
+            return false;
+        }
+
+        val nodePath = nodeConnectorIdentifier.path.get(1);
+        val nodeConnectorPath = nodeConnectorIdentifier.getPath().get(2);
+
+        nodeToNodeConnectorsLock.lock();
+
+        try {
+            var nodeConnectors = nodeToNodeConnectorsMap.get(nodePath);
+
+            if(nodeConnectors == null){
+                nodeConnectors = new ArrayList<InstanceIdentifier.PathArgument>();
+                nodeToNodeConnectorsMap.put(nodePath, nodeConnectors);
+            }
+
+            nodeConnectors.add(nodeConnectorPath);
+        } finally {
+            nodeToNodeConnectorsLock.unlock();
+        }
+    }
+
+    private def removeNodeConnectors(InstanceIdentifier<? extends Object> nodeIdentifier){
+        val nodePath = nodeIdentifier.path.get(1);
+
+        nodeToNodeConnectorsMap.remove(nodePath);
+    }
 }
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryMapping.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryMapping.java
new file mode 100644 (file)
index 0000000..2dce505
--- /dev/null
@@ -0,0 +1,105 @@
+/**
+ * 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.sal.compatibility;
+
+import org.eclipse.xtend2.lib.StringConcatenation;
+import org.eclipse.xtext.xbase.lib.Conversions;
+import org.eclipse.xtext.xbase.lib.IterableExtensions;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+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.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+
+import java.util.List;
+
+@SuppressWarnings("all")
+public class InventoryMapping {
+  public static NodeConnector toAdNodeConnector(final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector> identifier) {
+    final List<PathArgument> path = identifier.getPath();
+    final PathArgument lastPathArgument = IterableExtensions.<PathArgument>last(path);
+    final NodeConnectorKey tpKey = ((IdentifiableItem<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector,NodeConnectorKey>) lastPathArgument).getKey();
+    return InventoryMapping.nodeConnectorFromId(tpKey.getId().getValue());
+  }
+  
+  public static Node toAdNode(final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> identifier) {
+    final List<PathArgument> path = identifier.getPath();
+    final PathArgument lastPathArgument = IterableExtensions.<PathArgument>last(path);
+    final NodeKey tpKey = ((IdentifiableItem<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,NodeKey>) lastPathArgument).getKey();
+    return InventoryMapping.nodeFromNodeId(tpKey.getId().getValue());
+  }
+  
+  public static NodeRef toNodeRef(final Node node) {
+    final NodeId nodeId = new NodeId(InventoryMapping.toNodeId(node));
+    final NodeKey nodeKey = new NodeKey(nodeId);
+    final InstanceIdentifierBuilder<? extends Object> builder = InstanceIdentifier.builder();
+    final InstanceIdentifierBuilder<Nodes> nodes = builder.<Nodes>node(Nodes.class);
+    final InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> child =
+            nodes.<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, NodeKey>child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, nodeKey);
+    final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> path = child.toInstance();
+    return new NodeRef(path);
+  }
+  
+  public static NodeKey toNodeKey(final Node node) {
+    final NodeId nodeId = new NodeId(InventoryMapping.toNodeId(node));
+    return new NodeKey(nodeId);
+  }
+  
+  public static NodeConnectorKey toNodeConnectorKey(final NodeConnector nc) {
+    final NodeConnectorId nodeConnectorId = new NodeConnectorId(InventoryMapping.toNodeConnectorId(nc));
+    return new NodeConnectorKey(nodeConnectorId);
+  }
+  
+  public static String toNodeId(final Node node) {
+    final StringConcatenation builder = new StringConcatenation();
+    builder.append("ad-sal:");
+    builder.append(node.getType(), "");
+    builder.append("::");
+    builder.append(node.getNodeIDString(), "");
+    return builder.toString();
+  }
+  
+  public static String toNodeConnectorId(final NodeConnector nc) {
+    final StringConcatenation builder = new StringConcatenation();
+    builder.append(InventoryMapping.toNodeId(nc.getNode()), "");
+    builder.append("::");
+    builder.append(nc.getNodeConnectorIDString(), "");
+    return builder.toString();
+  }
+  
+  public static Node nodeFromNodeId(final String nodeId) {
+    final String[] split = nodeId.split("::");
+    return InventoryMapping.nodeFromString(split);
+  }
+  
+  public static NodeConnector nodeConnectorFromId(final String invId) {
+    final String[] split = invId.split("::");
+    return InventoryMapping.nodeConnectorFromString(split);
+  }
+  
+  private static NodeConnector nodeConnectorFromString(final String[] string) {
+    final List<String> subList = ((List<String>)Conversions.doWrapArray(string)).subList(0, 1);
+    final Node node = InventoryMapping.nodeFromString(((String[])Conversions.unwrapArray(subList, String.class)));
+    final String index3 = string[2];
+    return NodeConnector.fromStringNoNode(index3, node);
+  }
+  
+  private static Node nodeFromString(final String[] strings) {
+      String index0 = strings[0];
+      final String type = index0.substring(6);
+      String id = strings[1];
+      return Node.fromString(type, id);
+  }
+}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryMapping.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryMapping.xtend
deleted file mode 100644 (file)
index 0ea9918..0000000
+++ /dev/null
@@ -1,77 +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.sal.compatibility
-
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
-
-class InventoryMapping {
-
-    static def org.opendaylight.controller.sal.core.NodeConnector toAdNodeConnector(
-        InstanceIdentifier<NodeConnector> identifier) {
-        val tpKey = (identifier.path.last as IdentifiableItem<NodeConnector,NodeConnectorKey>).key;
-        return nodeConnectorFromId(tpKey.id.value);
-    }
-
-    static def org.opendaylight.controller.sal.core.Node toAdNode(InstanceIdentifier<Node> identifier) {
-        val tpKey = (identifier.path.last as IdentifiableItem<Node,NodeKey>).key;
-        return nodeFromNodeId(tpKey.id.value);
-    }
-    
-    
-     static def NodeRef toNodeRef(org.opendaylight.controller.sal.core.Node node) {
-        val nodeId = new NodeKey(new NodeId(node.toNodeId))
-        val path = InstanceIdentifier.builder().node(Nodes).child(Node,nodeId).toInstance;
-        return new NodeRef(path);
-    }
-
-    static def NodeKey toNodeKey(org.opendaylight.controller.sal.core.Node node) {
-        val nodeId = new NodeId(node.toNodeId)
-        return new NodeKey(nodeId);
-    }
-
-    static def NodeConnectorKey toNodeConnectorKey(org.opendaylight.controller.sal.core.NodeConnector nc) {
-        val nodeId = new NodeConnectorId(nc.toNodeConnectorId)
-        return new NodeConnectorKey(nodeId);
-    }
-
-    static def String toNodeId(org.opendaylight.controller.sal.core.Node node) {
-        '''ad-sal:«node.type»::«node.nodeIDString»'''
-    }
-
-    static def String toNodeConnectorId(org.opendaylight.controller.sal.core.NodeConnector nc) {
-        '''«nc.node.toNodeId»::«nc.nodeConnectorIDString»'''
-    }
-
-    static def org.opendaylight.controller.sal.core.Node nodeFromNodeId(String nodeId) {
-        return nodeFromString(nodeId.split("::"))
-    }
-
-    static def nodeConnectorFromId(String invId) {
-        return nodeConnectorFromString(invId.split("::"));
-    }
-
-    private static def org.opendaylight.controller.sal.core.NodeConnector nodeConnectorFromString(String[] string) {
-        val node = nodeFromString(string.subList(0, 1));
-        return org.opendaylight.controller.sal.core.NodeConnector.fromStringNoNode(string.get(2), node);
-    }
-
-    private static def org.opendaylight.controller.sal.core.Node nodeFromString(String[] strings) {
-        val type = strings.get(0).substring(6);
-        org.opendaylight.controller.sal.core.Node.fromString(type, strings.get(1))
-    }
-
-}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryNotificationProvider.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryNotificationProvider.java
new file mode 100644 (file)
index 0000000..6a9db37
--- /dev/null
@@ -0,0 +1,59 @@
+package org.opendaylight.controller.sal.compatibility;
+
+import java.util.List;
+
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class InventoryNotificationProvider implements AutoCloseable{
+
+    private ListenerRegistration<DataChangeListener> nodeConnectorDataChangeListenerRegistration;
+
+    private NodeConnectorDataChangeListener nodeConnectorDataChangeListener;
+
+    private DataProviderService dataProviderService;
+
+    private List<IPluginOutInventoryService> inventoryPublisher;
+
+    private final static Logger LOG = LoggerFactory.getLogger(NodeConnectorDataChangeListener.class);
+
+    public void start(){
+
+        LOG.info("InventoryNotificationProvider started");
+
+        if(dataProviderService != null
+                && inventoryPublisher!= null){
+
+            if(nodeConnectorDataChangeListener == null){
+                InstanceIdentifier<NodeConnector> nodeConnectorPath = InstanceIdentifier.builder(Nodes.class).child(Node.class).child(NodeConnector.class).build();
+                nodeConnectorDataChangeListener = new NodeConnectorDataChangeListener();
+                nodeConnectorDataChangeListener.setInventoryPublisher(inventoryPublisher);
+                nodeConnectorDataChangeListenerRegistration = dataProviderService.registerDataChangeListener(nodeConnectorPath, nodeConnectorDataChangeListener);
+            }
+
+        }
+    }
+
+    @Override
+    public void close() throws Exception {
+        if(nodeConnectorDataChangeListenerRegistration != null){
+            nodeConnectorDataChangeListenerRegistration.close();
+        }
+    }
+
+    public void setDataProviderService(DataProviderService dataProviderService) {
+        this.dataProviderService = dataProviderService;
+    }
+
+    public void setInventoryPublisher(List<IPluginOutInventoryService> inventoryPublisher) {
+        this.inventoryPublisher = inventoryPublisher;
+    }
+}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeConnectorDataChangeListener.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeConnectorDataChangeListener.java
new file mode 100644 (file)
index 0000000..eebba74
--- /dev/null
@@ -0,0 +1,77 @@
+package org.opendaylight.controller.sal.compatibility;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.core.Property;
+import org.opendaylight.controller.sal.core.UpdateType;
+import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+// org.opendaylight.controller.sal.compatibility.NodeConnectorDataChangeListener
+public class NodeConnectorDataChangeListener implements DataChangeListener{
+    private final static Logger LOG = LoggerFactory.getLogger(NodeConnectorDataChangeListener.class);
+
+    private List<IPluginOutInventoryService> inventoryPublisher;
+
+    public List<IPluginOutInventoryService> getInventoryPublisher() {
+      return this.inventoryPublisher;
+    }
+
+    public void setInventoryPublisher(final List<IPluginOutInventoryService> inventoryPublisher) {
+      this.inventoryPublisher = inventoryPublisher;
+    }
+
+    @Override
+    public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        final Map<InstanceIdentifier<?>,DataObject> createdOperationalData = change.getCreatedOperationalData();
+        final Map<InstanceIdentifier<?>,DataObject> updatedOperationalData = change.getUpdatedOperationalData();
+
+        final Set<Map.Entry<InstanceIdentifier<?>,DataObject>> createdEntries = createdOperationalData.entrySet();
+        final Set<Map.Entry<InstanceIdentifier<?>,DataObject>> updatedEntries = new HashSet<>();
+
+        updatedEntries.addAll(updatedOperationalData.entrySet());
+        updatedEntries.removeAll(createdEntries);
+
+        for(final Map.Entry<InstanceIdentifier<?>,DataObject> entry : createdEntries){
+            publishNodeConnectorUpdate(entry, UpdateType.ADDED);
+        }
+
+        for(final Map.Entry<InstanceIdentifier<?>,DataObject> entry : updatedEntries){
+            publishNodeConnectorUpdate(entry, UpdateType.CHANGED);
+        }
+    }
+
+    private void publishNodeConnectorUpdate(final Map.Entry<InstanceIdentifier<?>,DataObject> entry, final UpdateType updateType) {
+        if (entry.getKey().getTargetType().equals(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector.class)) {
+            NodeConnectorRef nodeConnectorRef = new NodeConnectorRef(entry.getKey());
+            NodeConnector nodeConnector = null;
+            try {
+                nodeConnector = NodeMapping.toADNodeConnector(nodeConnectorRef);
+            } catch (ConstructionException e) {
+                e.printStackTrace();
+            }
+            HashSet<Property> _aDNodeConnectorProperties = NodeMapping.toADNodeConnectorProperties((org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector) entry.getValue());
+            this.publishNodeConnectorUpdate(nodeConnector, updateType, _aDNodeConnectorProperties);
+        }
+    }
+
+    private void publishNodeConnectorUpdate(final NodeConnector nodeConnector, final UpdateType updateType, final Set<Property> properties) {
+      LOG.debug("Publishing NodeConnector " + updateType.toString() + " nodeConnector Id = " + nodeConnector.getNodeConnectorIdAsString());
+
+      List<IPluginOutInventoryService> _inventoryPublisher = getInventoryPublisher();
+      for (final IPluginOutInventoryService publisher : _inventoryPublisher) {
+        publisher.updateNodeConnector(nodeConnector, updateType, properties);
+      }
+    }
+}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java
new file mode 100644 (file)
index 0000000..0486f34
--- /dev/null
@@ -0,0 +1,396 @@
+/**
+ * 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.compatibility;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import org.eclipse.xtext.xbase.lib.Exceptions;
+import org.opendaylight.controller.sal.common.util.Arguments;
+import org.opendaylight.controller.sal.core.AdvertisedBandwidth;
+import org.opendaylight.controller.sal.core.Bandwidth;
+import org.opendaylight.controller.sal.core.Buffers;
+import org.opendaylight.controller.sal.core.Capabilities;
+import org.opendaylight.controller.sal.core.Config;
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.core.MacAddress;
+import org.opendaylight.controller.sal.core.Name;
+import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType;
+import org.opendaylight.controller.sal.core.PeerBandwidth;
+import org.opendaylight.controller.sal.core.Property;
+import org.opendaylight.controller.sal.core.SupportedBandwidth;
+import org.opendaylight.controller.sal.core.Tables;
+import org.opendaylight.controller.sal.core.TimeStamp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FeatureCapability;
+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.FlowFeatureCapabilityArpMatchIp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityFlowStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityIpReasm;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityPortStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityQueueStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityStp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityTableStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.flow.node.SwitchFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.State;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
+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.NodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+
+@SuppressWarnings("all")
+public class NodeMapping {
+  public final static String MD_SAL_TYPE = "MD_SAL";
+  
+  private final static Class<Node> NODE_CLASS = Node.class;
+  
+  private final static Class<NodeConnector> NODECONNECTOR_CLASS = NodeConnector.class;
+  
+  private NodeMapping() {
+    throw new UnsupportedOperationException("Utility class. Instantiation is not allowed.");
+  }
+  
+  public static org.opendaylight.controller.sal.core.Node toADNode(final InstanceIdentifier<? extends Object> node) throws ConstructionException {
+    NodeId nodeId = NodeMapping.toNodeId(node);
+    return NodeMapping.toADNode(nodeId);
+  }
+  
+  public static org.opendaylight.controller.sal.core.Node toADNode(final NodeId id) {
+    try {
+      String aDNodeId = NodeMapping.toADNodeId(id);
+      return  new org.opendaylight.controller.sal.core.Node(NodeMapping.MD_SAL_TYPE, aDNodeId);
+    } catch (Throwable e) {
+      throw Exceptions.sneakyThrow(e);
+    }
+  }
+  
+  public static NodeId toNodeId(final InstanceIdentifier<? extends Object> node) {
+    Preconditions.<InstanceIdentifier<? extends Object>>checkNotNull(node);
+    List<PathArgument> path = node.getPath();
+    Preconditions.<List<PathArgument>>checkNotNull(path);
+    int size = path.size();
+    Preconditions.checkArgument(size >= 2);
+    final PathArgument arg = path.get(1);
+    final IdentifiableItem item = Arguments.<IdentifiableItem>checkInstanceOf(arg, IdentifiableItem.class);
+    Identifier key = item.getKey();
+    final NodeKey nodeKey = Arguments.<NodeKey>checkInstanceOf(key, NodeKey.class);
+    return nodeKey.getId();
+  }
+  
+  public static String toADNodeId(final NodeId nodeId) {
+    Preconditions.<NodeId>checkNotNull(nodeId);
+    return nodeId.getValue();
+  }
+  
+  public static org.opendaylight.controller.sal.core.NodeConnector toADNodeConnector(final NodeConnectorRef source) throws ConstructionException {
+    Preconditions.<NodeConnectorRef>checkNotNull(source);
+    final InstanceIdentifier<?> path = Preconditions.<InstanceIdentifier<? extends Object>>checkNotNull(source.getValue());
+    Preconditions.checkArgument(path.getPath().size() >= 3);
+    final PathArgument arg = path.getPath().get(2);
+    final IdentifiableItem item = Arguments.<IdentifiableItem>checkInstanceOf(arg,IdentifiableItem.class);
+    final NodeConnectorKey connectorKey = Arguments.<NodeConnectorKey>checkInstanceOf(item.getKey(), NodeConnectorKey.class);
+    return NodeMapping.toADNodeConnector(connectorKey.getId(), NodeMapping.toNodeId(path));
+  }
+  
+  public static org.opendaylight.controller.sal.core.NodeConnector toADNodeConnector(final NodeConnectorId ncid, final NodeId nid) {
+    try {
+      String nodeConnectorType = NodeMapping.toNodeConnectorType(ncid, nid);
+      Object aDNodeConnectorId = NodeMapping.toADNodeConnectorId(ncid, nid);
+      org.opendaylight.controller.sal.core.Node aDNode = NodeMapping.toADNode(nid);
+      return new org.opendaylight.controller.sal.core.NodeConnector(nodeConnectorType, aDNodeConnectorId, aDNode);
+    } catch (Throwable e) {
+      throw Exceptions.sneakyThrow(e);
+    }
+  }
+  
+  public static String toNodeConnectorType(final NodeConnectorId ncId, final NodeId nodeId) {
+    if (ncId.equals(toLocalNodeConnectorId(nodeId))) {
+        return NodeConnectorIDType.SWSTACK;
+    } else if (ncId.equals(toNormalNodeConnectorId(nodeId))) {
+        return NodeConnectorIDType.HWPATH;
+    } else if (ncId.equals(toControllerNodeConnectorId(nodeId))) {
+        return NodeConnectorIDType.CONTROLLER;
+    }
+    return MD_SAL_TYPE;
+  }
+
+  public static Object toADNodeConnectorId(final NodeConnectorId nodeConnectorId, final NodeId nodeId) {
+    if (nodeConnectorId.equals(toLocalNodeConnectorId(nodeId)) ||
+        nodeConnectorId.equals(toNormalNodeConnectorId(nodeId)) ||
+        nodeConnectorId.equals(toControllerNodeConnectorId(nodeId))) {
+        return org.opendaylight.controller.sal.core.NodeConnector.SPECIALNODECONNECTORID;
+    }
+    return nodeConnectorId.getValue();
+  }
+  
+  public static NodeConnectorId toControllerNodeConnectorId(final NodeId node) {
+    return new NodeConnectorId(node.getValue() + ":" + 4294967293L);
+  }
+  
+  public static NodeConnectorId toLocalNodeConnectorId(final NodeId node) {
+    return new NodeConnectorId(node.getValue() + ":" + 4294967294L);
+  }
+  
+  public static NodeConnectorId toNormalNodeConnectorId(final NodeId node) {
+    return new NodeConnectorId(node.getValue() + ":" + 4294967290L);
+  }
+  
+  public static NodeRef toNodeRef(final org.opendaylight.controller.sal.core.Node node) {
+    Preconditions.checkArgument(MD_SAL_TYPE.equals(node.getType()));
+    final String nodeId = Arguments.<String>checkInstanceOf(node.getID(), String.class);
+    final NodeKey nodeKey = new NodeKey(new NodeId(nodeId));
+    final InstanceIdentifier<Node> nodePath = InstanceIdentifier.builder().node(Nodes.class).child(NODE_CLASS, nodeKey).toInstance();
+    return new NodeRef(nodePath);
+  }
+  
+  public static NodeConnectorRef toNodeConnectorRef(final org.opendaylight.controller.sal.core.NodeConnector nodeConnector) {
+
+    final NodeRef node = NodeMapping.toNodeRef(nodeConnector.getNode());
+    final InstanceIdentifier<Node> nodePath = ((InstanceIdentifier<Node>) node.getValue());
+    NodeConnectorId nodeConnectorId = null;
+
+    if (nodeConnector.getID().equals(org.opendaylight.controller.sal.core.NodeConnector.SPECIALNODECONNECTORID)) {
+        final NodeId nodeId = toNodeId(nodePath);
+        final String nodeConnectorType = nodeConnector.getType();
+        if (nodeConnectorType.equals(NodeConnectorIDType.SWSTACK)) {
+            nodeConnectorId = toLocalNodeConnectorId(nodeId);
+        } else if (nodeConnectorType.equals(NodeConnectorIDType.HWPATH)) {
+            nodeConnectorId = toNormalNodeConnectorId(nodeId);
+        } else if (nodeConnectorType.equals(NodeConnectorIDType.CONTROLLER)) {
+            nodeConnectorId = toControllerNodeConnectorId(nodeId);
+        }
+    } else {
+        nodeConnectorId = new NodeConnectorId(Arguments.<String>checkInstanceOf(nodeConnector.getID(), String.class));
+    }
+    final NodeConnectorKey connectorKey = new NodeConnectorKey(nodeConnectorId);
+    final InstanceIdentifier<NodeConnector> path = InstanceIdentifier.builder(nodePath).child(NODECONNECTOR_CLASS, connectorKey).toInstance();
+    return new NodeConnectorRef(path);
+  }
+  
+  public static org.opendaylight.controller.sal.core.Node toADNode(final NodeRef node) throws ConstructionException {
+    return NodeMapping.toADNode(node.getValue());
+  }
+  
+  public static HashSet<Property> toADNodeConnectorProperties(final NodeConnectorUpdated nc) {
+    final FlowCapableNodeConnectorUpdated fcncu = nc.<FlowCapableNodeConnectorUpdated>getAugmentation(FlowCapableNodeConnectorUpdated.class);
+    if (!Objects.equal(fcncu, null)) {
+      return NodeMapping.toADNodeConnectorProperties(fcncu);
+    }
+    return new HashSet<Property>();
+  }
+  
+  public static HashSet<Property> toADNodeConnectorProperties(final NodeConnector nc) {
+    final FlowCapableNodeConnector fcnc = nc.<FlowCapableNodeConnector>getAugmentation(FlowCapableNodeConnector.class);
+    if (!Objects.equal(fcnc, null)) {
+      return NodeMapping.toADNodeConnectorProperties(fcnc);
+    }
+    return new HashSet<Property>();
+  }
+  
+  public static HashSet<Property> toADNodeConnectorProperties(final FlowNodeConnector fcncu) {
+
+    final HashSet<org.opendaylight.controller.sal.core.Property> props = new HashSet<>();
+    if (fcncu != null) {
+        if (fcncu.getCurrentFeature() != null && toAdBandwidth(fcncu.getCurrentFeature()) != null) {
+            props.add(toAdBandwidth(fcncu.getCurrentFeature()));
+        }
+        if (fcncu.getAdvertisedFeatures() != null && toAdAdvertizedBandwidth(fcncu.getAdvertisedFeatures()) != null) {
+            props.add(toAdAdvertizedBandwidth(fcncu.getAdvertisedFeatures()));
+        }
+        if (fcncu.getSupported() != null && toAdSupportedBandwidth(fcncu.getSupported()) != null) {
+            props.add(toAdSupportedBandwidth(fcncu.getSupported()));
+        }
+        if (fcncu.getPeerFeatures() != null && toAdPeerBandwidth(fcncu.getPeerFeatures()) != null) {
+            props.add(toAdPeerBandwidth(fcncu.getPeerFeatures()));
+        }
+        if (fcncu.getName() != null && toAdName(fcncu.getName()) != null) {
+            props.add(toAdName(fcncu.getName()));
+        }
+        if (fcncu.getConfiguration() != null && toAdConfig(fcncu.getConfiguration()) != null) {
+            props.add(toAdConfig(fcncu.getConfiguration()));
+        }
+        if (fcncu.getState() != null && toAdState(fcncu.getState()) != null) {
+            props.add(toAdState(fcncu.getState()));
+        }
+    }
+    return props;
+  }
+  
+  public static Name toAdName(final String name) {
+    return new Name(name);
+  }
+  
+  public static Config toAdConfig(final PortConfig pc) {
+    Config config = null;
+    if (pc.isPORTDOWN()) {
+        config = new Config(Config.ADMIN_DOWN);
+    } else {
+        config = new Config(Config.ADMIN_UP);
+    }
+    return config;
+  }
+  
+  public static org.opendaylight.controller.sal.core.State toAdState(final State s) {
+
+    org.opendaylight.controller.sal.core.State state = null;
+    if (s.isLinkDown()) {
+        state = new org.opendaylight.controller.sal.core.State(org.opendaylight.controller.sal.core.State.EDGE_DOWN);
+    } else {
+        state = new org.opendaylight.controller.sal.core.State(org.opendaylight.controller.sal.core.State.EDGE_UP);
+    }
+    return state;
+  }
+  
+  public static Bandwidth toAdBandwidth(final PortFeatures pf) {
+    Bandwidth bw = null;
+    if (pf.isTenMbHd() || pf.isTenMbFd()) {
+        bw = new Bandwidth(Bandwidth.BW10Mbps);
+    } else if (pf.isHundredMbHd() || pf.isHundredMbFd()) {
+        bw = new Bandwidth(Bandwidth.BW100Mbps);
+    } else if (pf.isOneGbHd() || pf.isOneGbFd()) {
+        bw = new Bandwidth(Bandwidth.BW1Gbps);
+    } else if (pf.isOneGbFd()) {
+        bw = new Bandwidth(Bandwidth.BW10Gbps);
+    } else if (pf.isTenGbFd()) {
+        bw = new Bandwidth(Bandwidth.BW10Gbps);
+    } else if (pf.isFortyGbFd()) {
+        bw = new Bandwidth(Bandwidth.BW40Gbps);
+    } else if (pf.isHundredGbFd()) {
+        bw = new Bandwidth(Bandwidth.BW100Gbps);
+    } else if (pf.isOneTbFd()) {
+        bw = new Bandwidth(Bandwidth.BW1Tbps);
+    }
+    return bw;
+  }
+  
+  public static AdvertisedBandwidth toAdAdvertizedBandwidth(final PortFeatures pf) {
+    AdvertisedBandwidth abw = null;
+    final Bandwidth bw = toAdBandwidth(pf);
+    if (bw != null) {
+        abw = new AdvertisedBandwidth(bw.getValue());
+    }
+    return abw;
+  }
+  
+  public static SupportedBandwidth toAdSupportedBandwidth(final PortFeatures pf) {
+    SupportedBandwidth sbw = null;
+    final Bandwidth bw = toAdBandwidth(pf);
+    if (bw != null) {
+        sbw = new SupportedBandwidth(bw.getValue());
+    }
+    return sbw;
+  }
+  
+  public static PeerBandwidth toAdPeerBandwidth(final PortFeatures pf) {
+    PeerBandwidth pbw = null;
+    final Bandwidth bw = toAdBandwidth(pf);
+    if (bw != null) {
+        pbw = new PeerBandwidth(bw.getValue());
+    }
+    return pbw;
+  }
+  
+  public static HashSet<Property> toADNodeProperties(final NodeUpdated nu) {
+    final FlowCapableNodeUpdated fcnu = nu.getAugmentation(FlowCapableNodeUpdated.class);
+    if (fcnu != null) {
+        return toADNodeProperties(fcnu, nu.getId());
+    }
+    return new HashSet<org.opendaylight.controller.sal.core.Property>();
+  }
+  
+  public static HashSet<Property> toADNodeProperties(final FlowNode fcnu, final NodeId id) {
+
+    final HashSet<org.opendaylight.controller.sal.core.Property> props = new HashSet<>();
+
+    if (fcnu != null) {
+        props.add(toADTimestamp());
+
+        // props.add(fcnu.supportedActions.toADActions) - TODO
+        if (id != null) {
+            props.add(toADMacAddress(id));
+        }
+        SwitchFeatures switchFeatures = fcnu.getSwitchFeatures();
+        if (switchFeatures != null) {
+            if (switchFeatures.getMaxTables() != null) {
+                props.add(toADTables(switchFeatures.getMaxTables()));
+            }
+            if (switchFeatures.getCapabilities() != null) {
+                props.add(toADCapabiliities(switchFeatures.getCapabilities()));
+            }
+            if (switchFeatures.getMaxBuffers() != null) {
+                props.add(toADBuffers(switchFeatures.getMaxBuffers()));
+            }
+        }
+    }
+    return props;
+  }
+  
+  public static TimeStamp toADTimestamp() {
+    final Date date = new Date();
+    final TimeStamp timestamp = new TimeStamp(date.getTime(), "connectedSince");
+    return timestamp;
+  }
+  
+  public static MacAddress toADMacAddress(final NodeId id) {
+    final String nodeId = id.getValue().replaceAll("openflow:", "");
+    long lNodeId = Long.parseLong(nodeId);
+    lNodeId = Long.valueOf(lNodeId).longValue();
+    byte[] bytesFromDpid = ToSalConversionsUtils.bytesFromDpid(lNodeId);
+    return new MacAddress(bytesFromDpid);
+  }
+  
+  public static Tables toADTables(final Short tables) {
+    return new Tables(tables.byteValue());
+  }
+  
+  public static Capabilities toADCapabiliities(final List<Class<? extends FeatureCapability>> capabilities) {
+
+    int b = 0;
+    for (Class<? extends FeatureCapability> capability : capabilities) {
+        if (capability.equals(FlowFeatureCapabilityFlowStats.class)) {
+            b = Capabilities.CapabilitiesType.FLOW_STATS_CAPABILITY.getValue() | b;
+        } else if (capability.equals(FlowFeatureCapabilityTableStats.class)) {
+            b = Capabilities.CapabilitiesType.TABLE_STATS_CAPABILITY.getValue() | b;
+        } else if (capability.equals(FlowFeatureCapabilityPortStats.class)) {
+            b = Capabilities.CapabilitiesType.PORT_STATS_CAPABILITY.getValue() | b;
+        } else if (capability.equals(FlowFeatureCapabilityStp.class)) {
+            b = Capabilities.CapabilitiesType.STP_CAPABILITY.getValue() | b;
+        } else if (capability.equals(FlowFeatureCapabilityIpReasm.class)) {
+            b = Capabilities.CapabilitiesType.IP_REASSEM_CAPABILITY.getValue() | b;
+        } else if (capability.equals(FlowFeatureCapabilityQueueStats.class)) {
+            b = Capabilities.CapabilitiesType.QUEUE_STATS_CAPABILITY.getValue() | b;
+        } else if (capability.equals(FlowFeatureCapabilityArpMatchIp.class)) {
+            b = Capabilities.CapabilitiesType.ARP_MATCH_IP_CAPABILITY.getValue() | b;
+        }
+    }
+    return new Capabilities(b);
+  }
+  
+  public static Buffers toADBuffers(final Long buffers) {
+    return new Buffers(buffers.intValue());
+  }
+}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.xtend
deleted file mode 100644 (file)
index debcbac..0000000
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.compatibility
-
-import org.opendaylight.controller.sal.core.Node
-import org.opendaylight.controller.sal.core.NodeConnector
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
-
-import static com.google.common.base.Preconditions.*;
-import static extension org.opendaylight.controller.sal.common.util.Arguments.*;
-import static extension org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils.*;
-
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
-import org.opendaylight.controller.sal.core.ConstructionException
-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.NodeId
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures
-import org.opendaylight.controller.sal.core.Bandwidth
-import org.opendaylight.controller.sal.core.AdvertisedBandwidth
-import org.opendaylight.controller.sal.core.SupportedBandwidth
-import org.opendaylight.controller.sal.core.PeerBandwidth
-import org.opendaylight.controller.sal.core.Name
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortConfig
-import org.opendaylight.controller.sal.core.Config
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.State
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated
-import java.util.HashSet
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated
-import org.opendaylight.controller.sal.core.Tables
-import java.util.List
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FeatureCapability
-import org.opendaylight.controller.sal.core.Buffers
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityFlowStats
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityTableStats
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityIpReasm
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityPortStats
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityStp
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityQueueStats
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityArpMatchIp
-import org.opendaylight.controller.sal.core.Capabilities
-import org.opendaylight.controller.sal.core.MacAddress
-import java.util.Date
-import org.opendaylight.controller.sal.core.TimeStamp
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowNodeConnector
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowNode
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector
-
-public class NodeMapping {
-
-    public static val MD_SAL_TYPE = "MD_SAL";
-    private static val NODE_CLASS = org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-    private static val NODECONNECTOR_CLASS = org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.
-        NodeConnector;
-
-    private new() {
-        throw new UnsupportedOperationException("Utility class. Instantiation is not allowed.");
-    }
-
-    public static def toADNode(InstanceIdentifier<?> node) throws ConstructionException {
-        return node.toNodeId.toADNode
-    }
-
-    public static def toADNode(NodeId id) {
-        return new Node(MD_SAL_TYPE, id.toADNodeId);
-    }
-
-    public static def toNodeId(InstanceIdentifier<?> node) {
-        checkNotNull(node);
-        checkNotNull(node.getPath());
-        checkArgument(node.getPath().size() >= 2);
-        val arg = node.getPath().get(1);
-        val item = arg.checkInstanceOf(IdentifiableItem);
-        val nodeKey = item.getKey().checkInstanceOf(NodeKey);
-        return nodeKey.id
-    }
-
-    public static def toADNodeId(NodeId nodeId) {
-        checkNotNull(nodeId);
-        return nodeId.value
-    }
-
-    public static def toADNodeConnector(NodeConnectorRef source) throws ConstructionException {
-        checkNotNull(source);
-        val InstanceIdentifier<?> path = checkNotNull(source.getValue());
-        checkArgument(path.path.size() >= 3);
-        val arg = path.getPath().get(2);
-        val item = arg.checkInstanceOf(IdentifiableItem);
-        val connectorKey = item.getKey().checkInstanceOf(NodeConnectorKey);
-        return connectorKey.id.toADNodeConnector(path.toNodeId)
-    }
-    
-    public static def toADNodeConnector(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId ncid,
-        org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId nid) {
-            return new NodeConnector(ncid.toNodeConnectorType(nid),
-            ncid.toADNodeConnectorId(nid), nid.toADNode);
-     }
-
-    public static def toNodeConnectorType(NodeConnectorId ncId, NodeId nodeId) {
-        if (ncId.equals(nodeId.toLocalNodeConnectorId)) {
-            return NodeConnector.NodeConnectorIDType.SWSTACK
-        } else if (ncId.equals(nodeId.toNormalNodeConnectorId)) {
-            return NodeConnector.NodeConnectorIDType.HWPATH
-        } else if (ncId.equals(nodeId.toControllerNodeConnectorId)) {
-            return NodeConnector.NodeConnectorIDType.CONTROLLER
-        }
-        return MD_SAL_TYPE
-    }
-
-    public static def toADNodeConnectorId(NodeConnectorId nodeConnectorId, NodeId nodeId) {
-        if (nodeConnectorId.equals(nodeId.toLocalNodeConnectorId) ||
-            nodeConnectorId.equals(nodeId.toNormalNodeConnectorId) ||
-            nodeConnectorId.equals(nodeId.toControllerNodeConnectorId)) {
-            return NodeConnector.SPECIALNODECONNECTORID
-        }
-        return nodeConnectorId.value
-    }
-
-    public static def toControllerNodeConnectorId(NodeId node) {
-        return new NodeConnectorId(node.value + ":" + 4294967293L)
-    }
-
-    public static def toLocalNodeConnectorId(NodeId node) {
-        return new NodeConnectorId(node.value + ":" + 4294967294L)
-    }
-
-    public static def toNormalNodeConnectorId(NodeId node) {
-        return new NodeConnectorId(node.value + ":" + 4294967290L)
-    }
-
-    public static def toNodeRef(Node node) {
-        checkArgument(MD_SAL_TYPE.equals(node.getType()));
-        var nodeId = node.ID.checkInstanceOf(String)
-        val nodeKey = new NodeKey(new NodeId(nodeId));
-        val nodePath = InstanceIdentifier.builder().node(Nodes).child(NODE_CLASS, nodeKey).toInstance();
-        return new NodeRef(nodePath);
-    }
-
-    public static def toNodeConnectorRef(NodeConnector nodeConnector) {
-        val node = nodeConnector.node.toNodeRef();
-        val nodePath = node.getValue() as InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node>
-        var NodeConnectorId nodeConnectorId
-        if (nodeConnector.ID.equals(NodeConnector.SPECIALNODECONNECTORID)) {
-            if (nodeConnector.type.equals(NodeConnector.NodeConnectorIDType.SWSTACK)) {
-                nodeConnectorId = nodePath.toNodeId.toLocalNodeConnectorId
-            } else if (nodeConnector.type.equals(NodeConnector.NodeConnectorIDType.HWPATH)) {
-                nodeConnectorId = nodePath.toNodeId.toNormalNodeConnectorId
-            } else if (nodeConnector.type.equals(NodeConnector.NodeConnectorIDType.CONTROLLER)) {
-                nodeConnectorId = nodePath.toNodeId.toControllerNodeConnectorId
-            }
-        } else {
-            nodeConnectorId = new NodeConnectorId(nodeConnector.ID.checkInstanceOf(String))
-        }
-        val connectorKey = new NodeConnectorKey(nodeConnectorId);
-        val path = InstanceIdentifier.builder(nodePath).child(NODECONNECTOR_CLASS, connectorKey).toInstance();
-        return new NodeConnectorRef(path);
-    }
-
-    public static def toADNode(NodeRef node) throws ConstructionException {
-        return toADNode(node.getValue());
-    }
-
-    public static def toADNodeConnectorProperties(NodeConnectorUpdated nc) {
-        val fcncu = nc.getAugmentation(FlowCapableNodeConnectorUpdated)
-        if (fcncu != null) {
-            return fcncu.toADNodeConnectorProperties
-        }
-        return new HashSet<org.opendaylight.controller.sal.core.Property>();
-    }
-
-    public static def toADNodeConnectorProperties(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector nc) {
-        val fcnc = nc.getAugmentation(FlowCapableNodeConnector)
-        if (fcnc != null) {
-            return fcnc.toADNodeConnectorProperties
-        }
-        return new HashSet<org.opendaylight.controller.sal.core.Property>();
-    }
-
-    public static def toADNodeConnectorProperties(FlowNodeConnector fcncu) {
-        val props = new HashSet<org.opendaylight.controller.sal.core.Property>();
-        if (fcncu != null) {
-            if (fcncu.currentFeature != null && fcncu.currentFeature.toAdBandwidth != null) {
-                props.add(fcncu.currentFeature.toAdBandwidth)
-            }
-            if (fcncu.advertisedFeatures != null && fcncu.advertisedFeatures.toAdAdvertizedBandwidth != null) {
-                props.add(fcncu.advertisedFeatures.toAdAdvertizedBandwidth)
-            }
-            if (fcncu.supported != null && fcncu.supported.toAdSupportedBandwidth != null) {
-                props.add(fcncu.supported.toAdSupportedBandwidth)
-            }
-            if (fcncu.peerFeatures != null && fcncu.peerFeatures.toAdPeerBandwidth != null) {
-                props.add(fcncu.peerFeatures.toAdPeerBandwidth)
-            }
-            if (fcncu.name != null && fcncu.name.toAdName != null) {
-                props.add(fcncu.name.toAdName)
-            }
-            if (fcncu.configuration != null && fcncu.configuration.toAdConfig != null) {
-                props.add(fcncu.configuration.toAdConfig)
-            }
-            if (fcncu.state != null && fcncu.state.toAdState != null) {
-                props.add(fcncu.state.toAdState)
-            }
-        }
-        return props
-    }
-
-    public static def toAdName(String name) {
-        return new Name(name)
-    }
-
-    public static def toAdConfig(PortConfig pc) {
-        var Config config;
-        if (pc.PORTDOWN) {
-            config = new Config(Config.ADMIN_DOWN)
-        } else {
-            config = new Config(Config.ADMIN_UP)
-        }
-        return config
-    }
-
-    public static def toAdState(State s) {
-        var org.opendaylight.controller.sal.core.State state
-        if (s.linkDown) {
-            state = new org.opendaylight.controller.sal.core.State(org.opendaylight.controller.sal.core.State.EDGE_DOWN)
-        } else {
-            state = new org.opendaylight.controller.sal.core.State(org.opendaylight.controller.sal.core.State.EDGE_UP)
-        }
-        return state
-    }
-
-    public static def toAdBandwidth(PortFeatures pf) {
-        var Bandwidth bw = null
-        if (pf.isTenMbHd || pf.isTenMbFd) {
-            bw = new Bandwidth(Bandwidth.BW10Mbps)
-        } else if (pf.isHundredMbHd || pf.isHundredMbFd) {
-            bw = new Bandwidth(Bandwidth.BW100Mbps)
-        } else if (pf.isOneGbHd || pf.isOneGbFd) {
-            bw = new Bandwidth(Bandwidth.BW1Gbps)
-        } else if (pf.isOneGbFd) {
-            bw = new Bandwidth(Bandwidth.BW10Gbps)
-        } else if (pf.isTenGbFd) {
-            bw = new Bandwidth(Bandwidth.BW10Gbps)
-        } else if (pf.isFortyGbFd) {
-            bw = new Bandwidth(Bandwidth.BW40Gbps)
-        } else if (pf.isHundredGbFd) {
-            bw = new Bandwidth(Bandwidth.BW100Gbps)
-        } else if (pf.isOneTbFd) {
-            bw = new Bandwidth(Bandwidth.BW1Tbps)
-        }
-        return bw;
-    }
-
-    public static def toAdAdvertizedBandwidth(PortFeatures pf) {
-        var AdvertisedBandwidth abw
-        val bw = pf.toAdBandwidth
-        if (bw != null) {
-            abw = new AdvertisedBandwidth(bw.value)
-        }
-        return abw
-    }
-
-    public static def toAdSupportedBandwidth(PortFeatures pf) {
-        var SupportedBandwidth sbw
-        val bw = pf.toAdBandwidth
-        if (bw != null) {
-            sbw = new SupportedBandwidth(bw.value)
-        }
-        return sbw
-    }
-
-    public static def toAdPeerBandwidth(PortFeatures pf) {
-        var PeerBandwidth pbw
-        val bw = pf.toAdBandwidth
-        if (bw != null) {
-            pbw = new PeerBandwidth(bw.value)
-        }
-        return pbw
-    }
-
-    public static def toADNodeProperties(NodeUpdated nu) {
-        val fcnu = nu.getAugmentation(FlowCapableNodeUpdated)
-        if (fcnu != null) {
-            return fcnu.toADNodeProperties(nu.id)
-        }
-        return new HashSet<org.opendaylight.controller.sal.core.Property>();
-
-    }
-
-    public static def toADNodeProperties(FlowNode fcnu, NodeId id) {
-        val props = new HashSet<org.opendaylight.controller.sal.core.Property>();
-        if (fcnu != null) {
-            props.add(toADTimestamp)
-
-            // props.add(fcnu.supportedActions.toADActions) - TODO
-            if (id != null) {
-                props.add(id.toADMacAddress)
-            }
-            if (fcnu.switchFeatures != null) {
-                if (fcnu.switchFeatures.maxTables != null) {
-                    props.add(fcnu.switchFeatures.maxTables.toADTables)
-                }
-                if (fcnu.switchFeatures.capabilities != null) {
-                    props.add(fcnu.switchFeatures.capabilities.toADCapabiliities)
-                }
-                if (fcnu.switchFeatures.maxBuffers != null) {
-                    props.add(fcnu.switchFeatures.maxBuffers.toADBuffers)
-                }
-            }
-        }
-        return props;
-    }
-
-    public static def toADTimestamp() {
-        val date = new Date();
-        val timestamp = new TimeStamp(date.time, "connectedSince")
-        return timestamp;
-    }
-
-    public static def toADMacAddress(NodeId id) {
-        return new MacAddress(Long.parseLong(id.value.replaceAll("openflow:", "")).longValue.bytesFromDpid)
-    }
-
-    public static def toADTables(Short tables) {
-        return new Tables(tables.byteValue)
-    }
-
-    public static def toADCapabiliities(List<Class<? extends FeatureCapability>> capabilities) {
-        var int b
-        for (capability : capabilities) {
-            if (capability.equals(FlowFeatureCapabilityFlowStats)) {
-                b = Capabilities.CapabilitiesType.FLOW_STATS_CAPABILITY.value.bitwiseOr(b)
-            } else if (capability.equals(FlowFeatureCapabilityTableStats)) {
-                b = Capabilities.CapabilitiesType.TABLE_STATS_CAPABILITY.value.bitwiseOr(b)
-            } else if (capability.equals(FlowFeatureCapabilityPortStats)) {
-                b = Capabilities.CapabilitiesType.PORT_STATS_CAPABILITY.value.bitwiseOr(b)
-            } else if (capability.equals(FlowFeatureCapabilityStp)) {
-                b = Capabilities.CapabilitiesType.STP_CAPABILITY.value.bitwiseOr(b)
-            } else if (capability.equals(FlowFeatureCapabilityIpReasm)) {
-                b = Capabilities.CapabilitiesType.IP_REASSEM_CAPABILITY.value.bitwiseOr(b)
-            } else if (capability.equals(FlowFeatureCapabilityQueueStats)) {
-                b = Capabilities.CapabilitiesType.QUEUE_STATS_CAPABILITY.value.bitwiseOr(b)
-            } else if (capability.equals(FlowFeatureCapabilityArpMatchIp)) {
-                b = Capabilities.CapabilitiesType.ARP_MATCH_IP_CAPABILITY.value.bitwiseOr(b)
-            }
-        }
-        return new Capabilities(b)
-    }
-
-    public static def toADBuffers(Long buffers) {
-        return new Buffers(buffers.intValue)
-    }
-
-}
index a949e45d67d8200be7138a2e3b2dd3c1bbaec007..00cbc18e7e44ae7b0a8efbbfeb332374dc7b471b 100644 (file)
@@ -46,7 +46,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-binding-api</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-flow-service</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-flow-management</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
@@ -70,7 +67,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-binding-broker-impl</artifactId>
-      <version>1.1-SNAPSHOT</version>
       <scope>provided</scope>
     </dependency>
   </dependencies>
index ffdac63e4f051fb172d86cfa81f4eaeb55571c31..4d0465cba7b5ee768cca028a1fb56ce948f43550 100644 (file)
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-api</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
             <artifactId>model-flow-service</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
             <artifactId>model-inventory</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.eclipse.xtend</groupId>
index 1a66b3ba16316b4c5a1c92485e909cf061c3d398..43f48a50e56175a2297e78e32478f80404ff839d 100644 (file)
@@ -64,6 +64,8 @@ class FlowCapableInventoryProvider implements AutoCloseable {
 
 class NodeChangeCommiter implements OpendaylightInventoryListener {
 
+    static val LOG = LoggerFactory.getLogger(NodeChangeCommiter);
+
     @Property
     val FlowCapableInventoryProvider manager;
 
@@ -76,6 +78,9 @@ class NodeChangeCommiter implements OpendaylightInventoryListener {
 
         // Check path
         val it = manager.startChange()
+
+        LOG.debug("removing node connector : " + ref.value.toString());
+
         removeOperationalData(ref.value as InstanceIdentifier<? extends DataObject>);
         commit()
     }
@@ -93,6 +98,8 @@ class NodeChangeCommiter implements OpendaylightInventoryListener {
             data.addAugmentation(FlowCapableNodeConnector, augment)
         }
 
+        LOG.debug("updating node connector : " + ref.value.toString());
+
         putOperationalData(ref.value as InstanceIdentifier<NodeConnector>, data.build());
         commit()
     }
@@ -101,6 +108,8 @@ class NodeChangeCommiter implements OpendaylightInventoryListener {
         val ref = node.nodeRef;
         val it = manager.startChange()
 
+        LOG.debug("removing node : " + ref.value.toString());
+
         removeOperationalData(ref.value as InstanceIdentifier<? extends DataObject>);
         commit()
     }
@@ -117,6 +126,8 @@ class NodeChangeCommiter implements OpendaylightInventoryListener {
             data.addAugmentation(FlowCapableNode, augment)
         }
 
+        LOG.debug("updating node : " + ref.value.toString());
+
         putOperationalData(ref.value as InstanceIdentifier<Node>, data.build())
         commit()
     }
index d81669532b1ac04a5120d03e63879af739409e29..39f5060a32bd21f352e650164c7a3ddeaad400a1 100644 (file)
@@ -29,7 +29,6 @@
         <dependency>
             <groupId>org.opendaylight.yangtools.model</groupId>
             <artifactId>opendaylight-l2-types</artifactId>
-            <version>2013.08.27.3</version>
         </dependency>
     </dependencies>
     <packaging>bundle</packaging>
index 13efc4c3ae47f199c5e7c650821d80f028a76efc..54f232234b43557a09ef34d4d3cf54874a8f51c3 100644 (file)
@@ -29,7 +29,6 @@
         <dependency>
             <groupId>org.opendaylight.yangtools.model</groupId>
             <artifactId>opendaylight-l2-types</artifactId>
-            <version>2013.08.27.3</version>
         </dependency>
     </dependencies>
     <packaging>bundle</packaging>
index cd44bd247202846954d506fb5de46c218dd4d123..8e9f623efc7cc3da41c350c79fb0f0772af61664 100644 (file)
@@ -20,7 +20,6 @@
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
             <artifactId>model-inventory</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools.model</groupId>
index 86e14e4f5654bfc65427e5bd3782f3df4ff632be..f90031b2054a12794b22cfc2cf330d3d5f4934d5 100644 (file)
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
 
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common-api</artifactId>
-            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
-            <version>${osgi.core.version}</version>
             <scope>provided</scope>
         </dependency>
     </dependencies>
index fd2c8a2fa4b8026c94b7981e91ea3216a911fa5e..53674987772a50567f3fcdd23310c6c8700b2e52 100644 (file)
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common-util</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common-impl</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-api</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-util</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
-            <version>${osgi.core.version}</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-core-api</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-broker-impl</artifactId>
-            <version>1.1-SNAPSHOT</version>
             <scope>compile</scope>
         </dependency>
         <dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-config</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <dependency>
             <groupId>org.opendaylight.yangtools.model</groupId>
             <artifactId>ietf-inet-types</artifactId>
-            <version>2010.09.24.3</version>
         </dependency>
         <dependency>
-        <groupId>org.opendaylight.yangtools.model</groupId>
-        <artifactId>ietf-topology-l3-unicast-igp</artifactId>
-        <version>2013.10.21.1</version>
-        <scope>test</scope>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-topology-l3-unicast-igp</artifactId>
+            <scope>test</scope>
         </dependency>
         <dependency>
-               <groupId>org.opendaylight.controller.model</groupId>
-               <artifactId>model-flow-base</artifactId>
-               <version>1.1-SNAPSHOT</version>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-flow-base</artifactId>
         </dependency>
         <dependency>
-               <groupId>org.opendaylight.controller.model</groupId>
-               <artifactId>model-flow-service</artifactId>
-               <version>1.1-SNAPSHOT</version>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-flow-service</artifactId>
         </dependency>
         <dependency>
-               <groupId>org.opendaylight.controller.model</groupId>
-               <artifactId>model-flow-statistics</artifactId>
-               <version>1.1-SNAPSHOT</version>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-flow-statistics</artifactId>
         </dependency>
     </dependencies>
 </project>
index a0bbb28d9e07624e23ad0afd094c347c27d2fce2..790c1fcd4c61cb95f7f624392ab9fcc60b7d2089 100644 (file)
@@ -9,7 +9,10 @@ package org.opendaylight.controller.sal.binding.codegen.impl;
 
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
 
 import javassist.ClassPool;
 
@@ -27,13 +30,26 @@ public class SingletonHolder {
             CLASS_POOL);
     public static final RuntimeCodeGenerator RPC_GENERATOR = RPC_GENERATOR_IMPL;
     public static final NotificationInvokerFactory INVOKER_FACTORY = RPC_GENERATOR_IMPL.getInvokerFactory();
+
+    public static final int CORE_NOTIFICATION_THREADS = 4;
+    public static final int MAX_NOTIFICATION_THREADS = 32;
+    public static final int NOTIFICATION_THREAD_LIFE = 15;
+
     private static ListeningExecutorService NOTIFICATION_EXECUTOR = null;
     private static ListeningExecutorService COMMIT_EXECUTOR = null;
     private static ListeningExecutorService CHANGE_EVENT_EXECUTOR = null;
 
+    /**
+     * @deprecated This method is only used from configuration modules and thus callers of it
+     *             should use service injection to make the executor configurable.
+     */
+    @Deprecated
     public static synchronized final ListeningExecutorService getDefaultNotificationExecutor() {
         if (NOTIFICATION_EXECUTOR == null) {
-            NOTIFICATION_EXECUTOR = createNamedExecutor("md-sal-binding-notification-%d");
+            ThreadFactory factory = new ThreadFactoryBuilder().setDaemon(true).setNameFormat("md-sal-binding-notification-%d").build();
+            ExecutorService executor = new ThreadPoolExecutor(CORE_NOTIFICATION_THREADS, MAX_NOTIFICATION_THREADS,
+                    NOTIFICATION_THREAD_LIFE, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), factory);
+            NOTIFICATION_EXECUTOR = MoreExecutors.listeningDecorator(executor);
         }
         return NOTIFICATION_EXECUTOR;
     }
@@ -46,13 +62,13 @@ public class SingletonHolder {
     public static synchronized final ListeningExecutorService getDefaultCommitExecutor() {
         if (COMMIT_EXECUTOR == null) {
             ThreadFactory factory = new ThreadFactoryBuilder().setDaemon(true).setNameFormat("md-sal-binding-commit-%d").build();
-           /*
-            * FIXME: this used to be newCacheThreadPool(), but MD-SAL does not have transaction
-            *        ordering guarantees, which means that using a concurrent threadpool results
-            *        in application data being committed in random order, potentially resulting
-            *        in inconsistent data being present. Once proper primitives are introduced,
-            *        concurrency can be reintroduced.
-            */
+            /*
+             * FIXME: this used to be newCacheThreadPool(), but MD-SAL does not have transaction
+             *        ordering guarantees, which means that using a concurrent threadpool results
+             *        in application data being committed in random order, potentially resulting
+             *        in inconsistent data being present. Once proper primitives are introduced,
+             *        concurrency can be reintroduced.
+             */
             ExecutorService executor = Executors.newSingleThreadExecutor(factory);
             COMMIT_EXECUTOR = MoreExecutors.listeningDecorator(executor);
         }
@@ -60,12 +76,6 @@ public class SingletonHolder {
         return COMMIT_EXECUTOR;
     }
 
-    private static ListeningExecutorService createNamedExecutor(String format) {
-        ThreadFactory factory = new ThreadFactoryBuilder().setDaemon(true).setNameFormat(format).build();
-        ExecutorService executor = Executors.newCachedThreadPool(factory);
-        return MoreExecutors.listeningDecorator(executor);
-    }
-
     public static ExecutorService getDefaultChangeEventExecutor() {
         if (CHANGE_EVENT_EXECUTOR == null) {
             ThreadFactory factory = new ThreadFactoryBuilder().setDaemon(true).setNameFormat("md-sal-binding-change-%d").build();
index a7dcf80e8dbd5366ca366b0d2c50fce573a598bf..bf82302e548404cb4969cb01046dfae5b726c330 100644 (file)
@@ -8,25 +8,26 @@
 package org.opendaylight.controller.sal.binding.impl\r
 \r
 import com.google.common.collect.HashMultimap\r
+import com.google.common.collect.ImmutableSet\r
 import com.google.common.collect.Multimap\r
-import java.util.Collection\r
+import com.google.common.collect.Multimaps\r
 import java.util.Collections\r
 import java.util.concurrent.Callable\r
 import java.util.concurrent.ExecutorService\r
+import java.util.concurrent.Future\r
+import java.util.Set\r
 import org.opendaylight.controller.sal.binding.api.NotificationListener\r
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService\r
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService.NotificationInterestListener\r
+import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder\r
 import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory.NotificationInvoker\r
 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration\r
 import org.opendaylight.yangtools.concepts.ListenerRegistration\r
 import org.opendaylight.yangtools.concepts.Registration\r
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry\r
 import org.opendaylight.yangtools.yang.binding.Notification\r
 import org.slf4j.LoggerFactory\r
-import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder\rimport com.google.common.collect.Multimaps\r
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry\r
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService.NotificationInterestListener\rimport java.util.Set
-import com.google.common.collect.ImmutableSet
-import java.util.concurrent.Future
-
+\r
 class NotificationBrokerImpl implements NotificationProviderService, AutoCloseable {\r
     \r
     val ListenerRegistry<NotificationInterestListener> interestListeners = ListenerRegistry.create;\r
@@ -68,11 +69,6 @@ class NotificationBrokerImpl implements NotificationProviderService, AutoCloseab
         notification.class.interfaces.filter[it != Notification && Notification.isAssignableFrom(it)]\r
     }\r
 \r
-    @SuppressWarnings("unchecked")\r
-    private def notifyAll(Collection<NotificationListener<?>> listeners, Notification notification) {\r
-        listeners.forEach[(it as NotificationListener).onNotification(notification)]\r
-    }\r
-\r
     @Deprecated\r
     override addNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener listener) {\r
         throw new UnsupportedOperationException("Deprecated method. Use registerNotificationListener instead.");\r
@@ -105,14 +101,14 @@ class NotificationBrokerImpl implements NotificationProviderService, AutoCloseab
         submitAll(executor,tasks);\r
     }\r
     \r
-    def submitAll(ExecutorService service, Set<NotifyTask> tasks) {
+    def submitAll(ExecutorService service, Set<NotifyTask> tasks) {\r
         val ret = ImmutableSet.<Future<Object>>builder();\r
         for(task : tasks) {\r
             ret.add(service.submit(task));\r
         }\r
-        return ret.build();
+        return ret.build();\r
     }\r
-\r
+    \r
     override <T extends Notification> registerNotificationListener(Class<T> notificationType,\r
         NotificationListener<T> listener) {\r
         val reg = new GenericNotificationRegistration<T>(notificationType, listener, this);\r
index 5b947a5922589605abd146183802ffa07b6b84b4..e48ebbc0577f1b6101a772284ba9e07b3e6580cf 100644 (file)
@@ -149,8 +149,6 @@ public class BindingIndependentConnector implements //
 
     private RpcProviderRegistryImpl baRpcRegistryImpl;
 
-    private org.opendaylight.controller.sal.dom.broker.spi.RpcRouter biRouter;
-
     private NotificationProviderService baNotifyService;
 
     private NotificationPublishService domNotificationService;
@@ -319,9 +317,6 @@ public class BindingIndependentConnector implements //
                 baRpcRegistryImpl.registerRouterInstantiationListener(domToBindingRpcManager.getInstance());
                 baRpcRegistryImpl.registerGlobalRpcRegistrationListener(domToBindingRpcManager.getInstance());
             }
-            if (biRpcRegistry instanceof org.opendaylight.controller.sal.dom.broker.spi.RpcRouter) {
-                biRouter = (org.opendaylight.controller.sal.dom.broker.spi.RpcRouter) biRpcRegistry;
-            }
             rpcForwarding = true;
         }
     }
@@ -804,10 +799,10 @@ public class BindingIndependentConnector implements //
 
         @Override
         public Future<RpcResult<?>> forwardToDomBroker(DataObject input) {
-            if(biRouter != null) {
+            if(biRpcRegistry != null) {
                 CompositeNode xml = mappingService.toDataDom(input);
                 CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>> of(xml));
-                RpcResult<CompositeNode> result = biRouter.invokeRpc(rpc, wrappedXml);
+                RpcResult<CompositeNode> result = biRpcRegistry.invokeRpc(rpc, wrappedXml);
                 Object baResultValue = null;
                 if (result.getResult() != null) {
                     baResultValue = mappingService.dataObjectFromDataDom(outputClass.get(), result.getResult());
@@ -867,10 +862,10 @@ public class BindingIndependentConnector implements //
 
         @Override
         public Future<RpcResult<?>> forwardToDomBroker(DataObject input) {
-            if(biRouter != null) {
+            if(biRpcRegistry != null) {
                 CompositeNode xml = mappingService.toDataDom(input);
                 CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc,ImmutableList.<Node<?>>of(xml));
-                RpcResult<CompositeNode> result = biRouter.invokeRpc(rpc, wrappedXml);
+                RpcResult<CompositeNode> result = biRpcRegistry.invokeRpc(rpc, wrappedXml);
                 Object baResultValue = null;
                 RpcResult<?> baResult = Rpcs.<Void>getRpcResult(result.isSuccessful(), null, result.getErrors());
                 return Futures.<RpcResult<?>>immediateFuture(baResult);
index 95de575b518f698fab1f0dce58da2c6a3992b14f..c60686d209cecbee4aeb13ae513fe6082c889cdf 100644 (file)
@@ -7,13 +7,11 @@
  */
 package org.opendaylight.controller.sal.binding.impl.util
 
-import java.util.Map.Entry
-import org.opendaylight.yangtools.concepts.Path
-import java.util.Map
-import java.util.Set
+import com.google.common.collect.Multimap
 import java.util.Collection
 import java.util.HashSet
-import com.google.common.collect.Multimap
+import java.util.Map.Entry
+import org.opendaylight.yangtools.concepts.Path
 
 class MapUtils {
 
index b56b94a67b8ea8c63f7f5f3bd8b976761683c699..0a38c90a6af6b3f7763ac08437c381168ca03fa1 100644 (file)
@@ -16,5 +16,5 @@ import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext;
 public interface SimpleInput extends DataObject,Augmentable<SimpleInput> {
 
     @RoutingContext(BaseIdentity.class)
-    InstanceIdentifier getIdentifier();
+    InstanceIdentifier<?> getIdentifier();
 }
index d87e272032e5f5d47f1b53e0c2cb24bc2c8153b7..cb71b4fd3a5bf23646137b512df69a20314bb2f9 100644 (file)
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>config-api</artifactId>
-            <version>0.2.4-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-api</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
     </dependencies>
 </project>
index 8560848d5e85bf69e220eeb1c89d941a134e6911..82e3d975720ee97d7ba4e9b1451b82a620b47d02 100644 (file)
           <groupId>org.ops4j.pax.exam</groupId>
           <artifactId>pax-exam-container-native</artifactId>
           <scope>test</scope>
-          <version>${exam.version}</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-broker-impl</artifactId>
-            <version>1.1-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-broker-impl</artifactId>
-            <version>1.1-SNAPSHOT</version>
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
             <artifactId>model-flow-service</artifactId>
-            <version>1.1-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
             <artifactId>model-flow-management</artifactId>
-            <version>1.1-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
         <dependency>
index eaf5984c63c90f1e5ba35f9cf39231134f15ad58..9bc8a482145e120d10857a136d35caf1ec693121 100644 (file)
@@ -19,9 +19,6 @@
         <!-- Sonar jacoco plugin to get integration test coverage info -->
         <sonar.jacoco.reportPath>../sal-binding-broker/target/jacoco.exec</sonar.jacoco.reportPath>
         <sonar.jacoco.itReportPath>../sal-binding-broker/target/jacoco-it.exec</sonar.jacoco.itReportPath>
-        <netconf.version>0.2.4-SNAPSHOT</netconf.version>
-        <config.version>0.2.4-SNAPSHOT</config.version>
-        <moxy.controller.version>2.5.0</moxy.controller.version>
     </properties>
 
     <build>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-broker-impl</artifactId>
-            <version>1.1-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.ops4j.pax.exam</groupId>
             <artifactId>pax-exam-container-native</artifactId>
-            <version>${exam.version}</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.ops4j.pax.exam</groupId>
             <artifactId>pax-exam-junit4</artifactId>
-            <version>${exam.version}</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>config-netconf-connector</artifactId>
-            <version>${netconf.version}</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>yang-store-impl</artifactId>
-            <version>${config.version}</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>logback-config</artifactId>
-            <version>${config.version}</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>config-persister-impl</artifactId>
-            <version>${config.version}</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>config-persister-file-xml-adapter</artifactId>
-            <version>${config.version}</version>
         </dependency>
         <dependency>
             <groupId>org.eclipse.persistence</groupId>
             <artifactId>org.eclipse.persistence.moxy</artifactId>
-            <version>${moxy.controller.version}</version>
         </dependency>
         <dependency>
             <groupId>org.eclipse.persistence</groupId>
             <artifactId>org.eclipse.persistence.core</artifactId>
-            <version>${moxy.controller.version}</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>netconf-impl</artifactId>
-            <version>${netconf.version}</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>netconf-monitoring</artifactId>
-            <version>${netconf.version}</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>netconf-client</artifactId>
-            <version>${netconf.version}</version>
         </dependency>
         <dependency>
             <groupId>org.ops4j.pax.exam</groupId>
         <dependency>
             <groupId>org.ops4j.pax.exam</groupId>
             <artifactId>pax-exam-link-mvn</artifactId>
-            <version>${exam.version}</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>equinoxSDK381</groupId>
             <artifactId>org.eclipse.osgi</artifactId>
-            <version>3.8.1.v20120830-144521</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>log4j-over-slf4j</artifactId>
-            <version>1.7.2</version>
         </dependency>
         <dependency>
             <groupId>ch.qos.logback</groupId>
             <artifactId>logback-core</artifactId>
-            <version>1.0.9</version>
         </dependency>
         <dependency>
             <groupId>ch.qos.logback</groupId>
             <artifactId>logback-classic</artifactId>
-            <version>1.0.9</version>
         </dependency>
         <dependency>
             <groupId>org.mockito</groupId>
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
             <artifactId>model-flow-service</artifactId>
-            <version>1.1-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>config-manager</artifactId>
-            <version>0.2.4-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
             <artifactId>model-flow-management</artifactId>
-            <version>1.1-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
index 4e4416777b8eaed7f48aa1ddbb102a3a2b6c84ec..e8a52d069d72825c1cf71a6e9511abc70e900edd 100644 (file)
@@ -23,8 +23,6 @@ public class TestHelper {
 
     public static final String CONTROLLER_MODELS = "org.opendaylight.controller.model";
     public static final String YANGTOOLS_MODELS = "org.opendaylight.yangtools.model";
-    private static final String OPENDAYLIGHT_SNAPSHOT = "http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/";
-    private static final String OPENDAYLIGHT_RELEASE = "http://nexus.opendaylight.org/content/repositories/opendaylight.release/";
 
     public static Option mdSalCoreBundles() {
         return new DefaultCompositeOption( //
index 105f6e59a3d25def3de74d039e0c3dc794d94a37..8a390b337e1849ae8cf2c15f7799073ace928ee2 100644 (file)
@@ -7,15 +7,17 @@
  */
 package org.opendaylight.controller.test.sal.binding.it;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 
 import java.util.concurrent.Future;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer;
 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;
@@ -34,8 +36,8 @@ import com.google.inject.Inject;
 public class DataServiceTest extends AbstractTest {
 
     protected DataBrokerService consumerDataService;
-    
-    
+
+
     @Inject
     Broker broker2;
 
@@ -56,59 +58,58 @@ public class DataServiceTest extends AbstractTest {
 
         assertNotNull(consumerDataService);
 
-        
+
         DataModificationTransaction transaction = consumerDataService.beginTransaction();
         assertNotNull(transaction);
-        
+
         NodeRef node1 = createNodeRef("0");
         DataObject  node = consumerDataService.readConfigurationData(node1.getValue());
         assertNull(node);
         Node nodeData1 = createNode("0");
-        
+
         transaction.putConfigurationData(node1.getValue(), nodeData1);
         Future<RpcResult<TransactionStatus>> commitResult = transaction.commit();
         assertNotNull(commitResult);
-        
+
         RpcResult<TransactionStatus> result = commitResult.get();
-        
+
         assertNotNull(result);
         assertNotNull(result.getResult());
         assertEquals(TransactionStatus.COMMITED, result.getResult());
-        
+
         Node readedData = (Node) consumerDataService.readConfigurationData(node1.getValue());
         assertNotNull(readedData);
         assertEquals(nodeData1.getKey(), readedData.getKey());
-        
-        
+
+
         DataModificationTransaction transaction2 = consumerDataService.beginTransaction();
         assertNotNull(transaction);
-        
+
         transaction2.removeConfigurationData(node1.getValue());
-        
+
         Future<RpcResult<TransactionStatus>> commitResult2 = transaction2.commit();
         assertNotNull(commitResult2);
-        
+
         RpcResult<TransactionStatus> result2 = commitResult2.get();
-        
+
         assertNotNull(result2);
         assertNotNull(result2.getResult());
         assertEquals(TransactionStatus.COMMITED, result2.getResult());
-    
+
         DataObject readedData2 = consumerDataService.readConfigurationData(node1.getValue());
         assertNull(readedData2);
-        
-    
+
+
     }
 
-    
+
     private static NodeRef createNodeRef(String string) {
         NodeKey key = new NodeKey(new NodeId(string));
-        InstanceIdentifier<Node> path = InstanceIdentifier.builder().node(Nodes.class).node(Node.class, key)
-                .toInstance();
+        InstanceIdentifier<Node> path = InstanceIdentifier.builder(Nodes.class).child(Node.class, key).build();
 
         return new NodeRef(path);
     }
-    
+
     private static Node createNode(String string) {
         NodeBuilder ret = new NodeBuilder();
         NodeId id = new NodeId(string);
index befe70376468eef0d9687817268c312638698506..9c24ca08303b4f524198808b174ce0af67469bc6 100644 (file)
@@ -192,8 +192,7 @@ public class RoutedServiceTest extends AbstractTest {
      */
     private static NodeRef createNodeRef(String string) {
         NodeKey key = new NodeKey(new NodeId(string));
-        InstanceIdentifier<Node> path = InstanceIdentifier.builder().node(Nodes.class).node(Node.class, key)
-                .toInstance();
+        InstanceIdentifier<Node> path = InstanceIdentifier.builder(Nodes.class).child(Node.class, key).build();
 
         return new NodeRef(path);
     }
index 747e4205e1929da466f4096d531e9a9d5571be0e..4842d8cf28b873aaf3bad094713cbce206412433 100644 (file)
@@ -22,7 +22,6 @@
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-api</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
     </dependencies>
 </project>
index 5dd08d062d0159dfc18a7d4f11338c47505fb2a1..8a2571c727c5e89dbaf8a764fda5bdf4b6199dec 100644 (file)
@@ -17,7 +17,6 @@
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
@@ -30,7 +29,6 @@
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
-            <version>5.0.0</version>
         </dependency>
     </dependencies>
     <packaging>bundle</packaging>
index 92ff55175c4cb5ad948dfebc99d1bd0eacf6e32f..a8989c4ce865616d7515158407d228d922a50196 100644 (file)
@@ -8,9 +8,26 @@
 package org.opendaylight.controller.md.sal.common.api;
 
 public enum TransactionStatus {
+    /**
+     * The transaction has been freshly allocated. The user is still accessing
+     * it and it has not been sealed.
+     */
     NEW,
+    /**
+     * The transaction has been completed by the user and sealed. It is currently
+     * awaiting execution.
+     */
     SUBMITED,
+    /**
+     * The transaction has been successfully committed to backing store.
+     */
     COMMITED,
+    /**
+     * The transaction has failed to commit due to some underlying issue.
+     */
     FAILED,
-    CANCELED
+    /**
+     * Currently unused.
+     */
+    CANCELED,
 }
index 30a607d95b6a025619e836dd26097707704ecae3..ebffbcc811747307f2a3a67a7b83cb403d5757c2 100644 (file)
@@ -10,41 +10,40 @@ package org.opendaylight.controller.md.sal.common.api.data;
 import java.util.Map;
 import java.util.Set;
 
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Path;
 
-public interface DataChange<P/* extends Path<P> */, D> {
+public interface DataChange<P extends Path<P>, D> {
 
     /**
      * Returns a map of paths and newly created objects
-     * 
+     *
      * @return map of paths and newly created objects
      */
     Map<P, D> getCreatedOperationalData();
 
     /**
      * Returns a map of paths and newly created objects
-     * 
+     *
      * @return map of paths and newly created objects
      */
     Map<P, D> getCreatedConfigurationData();
 
     /**
      * Returns a map of paths and respective updated objects after update.
-     * 
+     *
      * Original state of the object is in
      * {@link #getOriginalOperationalData()}
-     * 
+     *
      * @return map of paths and newly created objects
      */
     Map<P, D> getUpdatedOperationalData();
 
     /**
      * Returns a map of paths and respective updated objects after update.
-     * 
+     *
      * Original state of the object is in
      * {@link #getOriginalConfigurationData()}
-     * 
+     *
      * @return map of paths and newly created objects
      */
     Map<P, D> getUpdatedConfigurationData();
@@ -53,34 +52,34 @@ public interface DataChange<P/* extends Path<P> */, D> {
 
     /**
      * Returns a set of paths of removed objects.
-     * 
+     *
      * Original state of the object is in
      * {@link #getOriginalConfigurationData()}
-     * 
+     *
      * @return map of paths and newly created objects
      */
     Set<P> getRemovedConfigurationData();
 
     /**
      * Returns a set of paths of removed objects.
-     * 
+     *
      * Original state of the object is in
      * {@link #getOriginalOperationalData()}
-     * 
+     *
      * @return map of paths and newly created objects
      */
     Set<P> getRemovedOperationalData();
 
     /**
      * Return a map of paths and original state of updated and removed objectd.
-     * 
+     *
      * @return map of paths and original state of updated and removed objectd.
      */
     Map<P, D> getOriginalConfigurationData();
 
     /**
      * Return a map of paths and original state of updated and removed objectd.
-     * 
+     *
      * @return map of paths and original state of updated and removed objectd.
      */
     Map<P, D> getOriginalOperationalData();
index d62e176e62d1beeb22c934f7c82aa3a713909b91..15d1daa1bbe882393f863e892728490c212f5e71 100644 (file)
@@ -8,36 +8,37 @@
 package org.opendaylight.controller.md.sal.common.api.data;
 
 import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.concepts.Path;
 
-public interface DataChangeEvent<P,D> extends DataChange<P, D>, Immutable {
+public interface DataChangeEvent<P extends Path<P>,D> extends DataChange<P, D>, Immutable {
 
     /**
      * Returns a orignal subtree of data, which starts at the path
      * where listener was registered.
-     * 
+     *
      */
     D getOriginalConfigurationSubtree();
 
     /**
      * Returns a new subtree of data, which starts at the path
      * where listener was registered.
-     * 
+     *
      */
     D getOriginalOperationalSubtree();
-    
-    
-    
+
+
+
     /**
      * Returns a updated subtree of data, which starts at the path
      * where listener was registered.
-     * 
+     *
      */
     D getUpdatedConfigurationSubtree();
 
     /**
      * Returns a udpated subtree of data, which starts at the path
      * where listener was registered.
-     * 
+     *
      */
     D getUpdatedOperationalSubtree();
 }
index 8b87139c7f97e78d09be1fad70fd192af52e48b2..8787a3fe8d82de85bc7e064177501e017d041cca 100644 (file)
@@ -9,10 +9,9 @@ package org.opendaylight.controller.md.sal.common.api.data;
 
 import java.util.EventListener;
 
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Path;
 
-public interface DataChangeListener<P/* extends Path<P> */,D> extends EventListener {
+public interface DataChangeListener<P extends Path<P>, D> extends EventListener {
 
     void onDataChanged(DataChangeEvent<P, D> change);
 }
index 66645e5538d6efb0935231100c0a72890ed09a70..0c4c6d179ff84faf955fb6989d8ca900cbb8722e 100644 (file)
@@ -7,12 +7,10 @@
  */
 package org.opendaylight.controller.md.sal.common.api.data;
 
-
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Path;
 
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
-public interface DataChangePublisher<P/* extends Path<P> */,D, L extends DataChangeListener<P,D>> {
+public interface DataChangePublisher<P extends Path<P>, D, L extends DataChangeListener<P,D>> {
 
     ListenerRegistration<L> registerDataChangeListener(P path, L listener);
 
index 90de13d15e8229238f36c5ec59b1180babcff1ae..939ff9513513ff1de802746facfdd09844952b76 100644 (file)
@@ -8,30 +8,29 @@
 package org.opendaylight.controller.md.sal.common.api.data;
 
 import org.opendaylight.controller.sal.common.DataStoreIdentifier;
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Path;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 /**
  * Two phase commit handler (cohort) of the two-phase commit protocol of data.
- * 
+ *
  * <p>
  * The provider should expose the implementation of DataCommitHandler if it's
  * functionality depends on any subset of data stored in data repositories, in
  * order to participate in {@link DataBrokerService#commit(DataStoreIdentifier)
  * operation.
- * 
+ *
  * <p>
  * Operations of two-phase commit handlers should not change data in data store,
  * this is responsibility of the coordinator (broker or some component of the
  * broker).
- * 
+ *
  * The commit handlers are responsible for changing the internal state of the
  * provider to reflect the commited changes in data.
- * 
+ *
  * <h3>Two-phase commit</h3>
- * 
+ *
  * <h4>Commit Request Phase</h4>
- * 
+ *
  * <ol>
  * <li> <code>Consumer</code> edits data by invocation of
  * <code>DataBrokerService.editCandidateData(DataStoreIdentifier, DataRoot)</code>
@@ -51,9 +50,9 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
  * </ol>
  * <li><code>Broker</code> starts a commit finish phase
  * </ol>
- * 
+ *
  * <h4>Commit Finish Phase</h4>
- * 
+ *
  * <ol>
  * <li>For each <code>CommitTransaction</code> from Commit Request phase
  * <ol>
@@ -69,7 +68,7 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
  * <li>If error occured, the broker starts a commit rollback phase.
  * </ul>
  * </ol>
- * 
+ *
  * <h4>Commit Rollback Phase</h4>
  * <li>For each <code>DataCommitTransaction</code> from Commit Request phase
  * <ol>
@@ -78,43 +77,43 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
  * <li>The provider rollbacks a commit and returns an {@link RpcResult} of
  * rollback. </ol>
  * <li>Broker returns a error result to the consumer.
- * 
+ *
  * @param <P> Class representing a path
  * @param <D> Superclass from which all data objects are derived from.
  */
-public interface DataCommitHandler<P/* extends Path<P> */,D> {
+public interface DataCommitHandler<P extends Path<P>, D> {
+
 
-    
     DataCommitTransaction<P, D> requestCommit(DataModification<P,D> modification);
 
-    public interface DataCommitTransaction<P/* extends Path<P> */,D> {
+    public interface DataCommitTransaction<P extends Path<P>, D> {
 
         DataModification<P,D> getModification();
 
         /**
-         * 
+         *
          * Finishes a commit.
-         * 
+         *
          * This callback is invoked by commit coordinator to finish commit action.
-         * 
+         *
          * The implementation is required to finish transaction or return unsuccessful
          * rpc result if something went wrong.
-         * 
+         *
          * The provider (commit handler) should apply all changes to its state
          * which are a result of data change-
-         * 
+         *
          * @return
          */
         RpcResult<Void> finish() throws IllegalStateException;
 
         /**
          * Rollbacks a commit.
-         * 
+         *
          * This callback is invoked by commit coordinator to finish commit action.
-         * 
+         *
          * The provider (commit handler) should rollback all changes to its state
          * which were a result of previous request commit.
-         * 
+         *
          * @return
          * @throws IllegalStateException
          *             If the method is invoked after {@link #finish()}
index 00db6064aa3bb54fa2a1f123be45d67289e63c52..f6662c388aa36e0092cf0ec8b5f262dcf981d163 100644 (file)
@@ -10,11 +10,10 @@ package org.opendaylight.controller.md.sal.common.api.data;
 import java.util.concurrent.Future;
 
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.yangtools.concepts.Path;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 
-//FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-//import org.opendaylight.yangtools.concepts.Path;
-public interface DataModification<P/* extends Path<P> */, D> extends DataChange<P, D>, DataReader<P, D> {
+public interface DataModification<P extends Path<P>, D> extends DataChange<P, D>, DataReader<P, D> {
 
     /**
      * Returns transaction identifier
index 64d90f6fd5e8ae0ceb471c051287eb8fb298bdbc..34f6fe970dd2e0105e6a21d32ca7049815ea87e7 100644 (file)
@@ -7,10 +7,9 @@
  */
 package org.opendaylight.controller.md.sal.common.api.data;
 
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Path;
 
-public interface DataModificationTransactionFactory<P/* extends Path<P> */,D> {
+public interface DataModificationTransactionFactory<P extends Path<P> ,D> {
 
     DataModification<P, D> beginTransaction();
 }
index 6c108bf5e49c1c6cb7fc3717e5f77649558e830f..dae9a1144b966a2e3c5e61884c1281e09a6229f3 100644 (file)
@@ -7,9 +7,8 @@
  */
 package org.opendaylight.controller.md.sal.common.api.data;
 
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Path;
 
-public interface DataProvider<P/* extends Path<P> */,D> extends DataReader<P, D> {
+public interface DataProvider<P extends Path<P>, D> extends DataReader<P, D> {
 
 }
index 7240a506bea5c0612f1c75424b85d544a09f9ec6..14731d688c964adaf264d8909a4c3e90ccc4484e 100644 (file)
@@ -7,23 +7,22 @@
  */
 package org.opendaylight.controller.md.sal.common.api.data;
 
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Path;
 
 /**
  * Reader for reading YANG subtrees based on their path.
- * 
+ *
  * Reader is requested to return object at specified path and all it's subnodes
  * known to the reader or null if node is not found in this reader.
  *
  * @param <P> Path Type
  * @param <D> Data Type
  */
-public interface DataReader<P/* extends Path<P> */,D> {
+public interface DataReader<P extends Path<P> ,D> {
 
     /**
      * Reads data from Operational data store located at provided path
-     * 
+     *
      * @param path Path to data
      * @return
      */
index ed5499870a9402cb0a8ef6f625a7528d14f8797a..3520ba1819b42fb0ce37ae3548631cd80753334b 100644 (file)
@@ -7,7 +7,9 @@
  */
 package org.opendaylight.controller.md.sal.common.api.data;
 
-public interface DataStore<P, D> extends //
+import org.opendaylight.yangtools.concepts.Path;
+
+public interface DataStore<P extends Path<P>, D> extends //
         DataReader<P, D>, //
         DataModificationTransactionFactory<P, D> {
 
index ff3aa2e325af0146d5cd878ea9aed88c350d4a6c..d542935dd6dbf0fdb91ce72b273d6bc9c87b2668 100644 (file)
@@ -7,12 +7,14 @@
  */
 package org.opendaylight.controller.md.sal.common.api.data;
 
+import org.opendaylight.yangtools.concepts.Path;
+
 /**
  * A chain of transactions. Transactions in a chain need to be committed in sequence and each
  * transaction should see the effects of previous transactions as if they happened. A chain
  * makes no guarantees of atomicity, in fact transactions are committed as soon as possible.
  */
-public interface TransactionChain<P/* extends Path<P> */, D> extends AutoCloseable {
+public interface TransactionChain<P extends Path<P>, D> extends AutoCloseable {
     /**
      * Create a new transaction which will continue the chain. The previous transaction
      * has to be either COMMITTED or CANCELLED.
index 4e7e12e0a15e3c5060a59eff76c35d9896ff00eb..94d21f5fd6bb02736a360592dc6826a3c70e4ae4 100644 (file)
@@ -7,10 +7,12 @@
  */
 package org.opendaylight.controller.md.sal.common.api.data;
 
+import org.opendaylight.yangtools.concepts.Path;
+
 /**
  * Interface for creating transaction chains.
  */
-public interface TransactionChainFactory<P/* extends Path<P> */, D> {
+public interface TransactionChainFactory<P extends Path<P>, D> {
     /**
      * Create a new transaction chain. The chain will be initialized to read
      * from its backing datastore, with no outstanding transaction. Listener
index 1139d03357999f5d71d3b0326ab1c621a14da984..f99c13ecf53499ab6770d9107025cb7f91828b8a 100644 (file)
@@ -8,10 +8,9 @@
 package org.opendaylight.controller.md.sal.common.api.routing;
 
 import org.opendaylight.yangtools.concepts.Mutable;
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Path;
 
-public interface MutableRoutingTable<C,P/* extends Path<P> */,T> extends RoutingTable<C,P,T>, Mutable {
+public interface MutableRoutingTable<C, P extends Path<P>, T> extends RoutingTable<C,P,T>, Mutable {
     
     void setDefaultRoute(T target);
     void updateRoute(P path,T target);
index 37ec2f6f1f90d4bae0e681d40e5674c1076ec504..5200c90561ecdb464060e0ba112a687de065c9ec 100644 (file)
@@ -7,11 +7,10 @@
  */
 package org.opendaylight.controller.md.sal.common.api.routing;
 
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Path;
 import org.opendaylight.yangtools.concepts.Registration;
 
-public interface RoutedRegistration<C,P/* extends Path<P> */,S> extends Registration<S> {
+public interface RoutedRegistration<C, P extends Path<P>, S> extends Registration<S> {
 
     void registerPath(C context, P path);
     void unregisterPath(C context, P path);
index 211cf188795a1feee2d2abe11a028ff0b6a0786f..4402f69a5f73896f8f905c190a7743f3f0b28e80 100644 (file)
@@ -9,10 +9,9 @@ package org.opendaylight.controller.md.sal.common.api.routing;
 
 import java.util.Map;
 
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Path;
 
-public interface RoutingTable<C,P/* extends Path<P> */,T> {
+public interface RoutingTable<C, P extends Path<P>, T> {
 
     C getIdentifier();
     
index 46493ddad0cb0611f300daca683739e94123fa55..d3504bd0180e9d9d34e94115adab1ab0124ac679 100644 (file)
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common-api</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common-util</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>com.google.guava</groupId>
index bfa4f36c18ca1d23f852a3da9c554942aa0b3e0e..9001aaa4dede9ded757c68b737446ea11a09db79 100644 (file)
@@ -16,33 +16,33 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 
 public class RoutingUtils {
-    
+
     public static <C,P> RouteChange<C,P> removalChange(C context,P path) {
         final ImmutableMap<C, Set<P>> announcements = ImmutableMap.<C,Set<P>>of();
         final ImmutableMap<C, Set<P>> removals = ImmutableMap.<C,Set<P>>of(context, ImmutableSet.of(path));
         return new RouteChangeImpl<C,P>(announcements, removals);
     }
-    
+
     public static <C,P> RouteChange<C,P> announcementChange(C context,P path) {
         final ImmutableMap<C, Set<P>> announcements = ImmutableMap.<C,Set<P>>of(context, ImmutableSet.of(path));
         final ImmutableMap<C, Set<P>> removals = ImmutableMap.<C,Set<P>>of();
         return new RouteChangeImpl<C,P>(announcements, removals);
     }
-    
-    
+
+
     public static <C,P> RouteChange<C,P> change(Map<C, Set<P>> announcements,
             Map<C, Set<P>> removals) {
         final ImmutableMap<C, Set<P>> immutableAnnouncements = ImmutableMap.<C,Set<P>>copyOf(announcements);
         final ImmutableMap<C, Set<P>> immutableRemovals = ImmutableMap.<C,Set<P>>copyOf(removals);
         return new RouteChangeImpl<C,P>(immutableAnnouncements, immutableRemovals);
     }
-    
-    
+
+
     private static class RouteChangeImpl<C,P> implements RouteChange<C, P> {
         private final Map<C, Set<P>> removal;
         private final Map<C, Set<P>> announcement;
 
-        public RouteChangeImpl(ImmutableMap<C, Set<P>> removal, ImmutableMap<C, Set<P>> announcement) {
+        public RouteChangeImpl(ImmutableMap<C, Set<P>> announcement, ImmutableMap<C, Set<P>> removal) {
             super();
             this.removal = removal;
             this.announcement = announcement;
@@ -52,7 +52,7 @@ public class RoutingUtils {
         public Map<C, Set<P>> getAnnouncements() {
             return announcement;
         }
-        
+
         @Override
         public Map<C, Set<P>> getRemovals() {
             return removal;
@@ -78,7 +78,7 @@ public class RoutingUtils {
             if (getClass() != obj.getClass()) {
                 return false;
             }
-            RouteChangeImpl other = (RouteChangeImpl) obj;
+            RouteChangeImpl<?, ?> other = (RouteChangeImpl<?, ?>) obj;
             if (announcement == null) {
                 if (other.announcement != null)
                     return false;
@@ -95,5 +95,5 @@ public class RoutingUtils {
     }
 
 
-    
+
 }
index bfffb594cb6fd73d9654d402be5a66aa076eaa30..ed186dcf314fd0ea075ad81bc3b3e19fb942a48b 100644 (file)
@@ -408,7 +408,7 @@ public abstract class AbstractDataBroker<P extends Path<P>, D extends Object, DC
         Preconditions.checkNotNull(transaction);
         transaction.changeStatus(TransactionStatus.SUBMITED);
         final TwoPhaseCommit<P, D, DCL> task = new TwoPhaseCommit<P, D, DCL>(transaction, this);
-        ;
+
         this.getSubmittedTransactionsCount().getAndIncrement();
         return this.getExecutor().submit(task);
     }
index e99fc0f24c16d424524c2d1642d2109a5193c173..33de1d83dae3cf40ff875625b979a3182783cf20 100644 (file)
@@ -61,6 +61,17 @@ public class TwoPhaseCommit<P extends Path<P>, D extends Object, DCL extends Dat
 
         log.trace("Transaction: {} Affected Subtrees:", transactionId, changedPaths);
 
+        // The transaction has no effects, let's just shortcut it
+        if (changedPaths.isEmpty()) {
+            dataBroker.getFinishedTransactionsCount().getAndIncrement();
+            transaction.changeStatus(TransactionStatus.COMMITED);
+
+            log.trace("Transaction: {} Finished successfully (no effects).", transactionId);
+
+            return Rpcs.<TransactionStatus> getRpcResult(true, TransactionStatus.COMMITED,
+                    Collections.<RpcError> emptySet());
+        }
+
         final ImmutableList.Builder<ListenerStateCapture<P, D, DCL>> listenersBuilder = ImmutableList.builder();
         listenersBuilder.addAll(dataBroker.affectedListeners(changedPaths));
         filterProbablyAffectedListeners(dataBroker.probablyAffectedListeners(changedPaths),listenersBuilder);
@@ -211,14 +222,12 @@ public class TwoPhaseCommit<P extends Path<P>, D extends Object, DCL extends Dat
             @Override
             public void run() {
                 for (final ListenerStateCapture<P, D, DCL> listenerSet : listeners) {
-                    {
-                        DataChangeEvent<P, D> changeEvent = listenerSet.createEvent(transaction);
-                        for (final DataChangeListenerRegistration<P, D, DCL> listener : listenerSet.getListeners()) {
-                            try {
-                                listener.getInstance().onDataChanged(changeEvent);
-                            } catch (Exception e) {
-                                log.error("Unhandled exception when invoking listener {}", listener);
-                            }
+                    DataChangeEvent<P, D> changeEvent = listenerSet.createEvent(transaction);
+                    for (final DataChangeListenerRegistration<P, D, DCL> listener : listenerSet.getListeners()) {
+                        try {
+                            listener.getInstance().onDataChanged(changeEvent);
+                        } catch (Exception e) {
+                            log.error("Unhandled exception when invoking listener {}", listener, e);
                         }
                     }
                 }
index 3a9b00dce079994d1351142a3f288ffbacf631fc..d3514ecc693d1cbacc4f3b71665fc20452d0a9a3 100644 (file)
@@ -29,7 +29,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-common-api</artifactId>
-      <version>${project.version}</version>
     </dependency>
     
   </dependencies>
index f28057e8a6bb5b339bc886f9e6d94d90ac9337b1..14733bc6b59d01d88f277777e3bab3a3ea1c4a70 100644 (file)
@@ -17,7 +17,6 @@
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-core-api</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
index d7b0296ce1d2ac761a371b948273f903b2c45cf8..9c253eecb8383d6ee5d6fe7259e81d506656686f 100644 (file)
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
-
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>config-api</artifactId>
-            <version>0.2.4-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common-api</artifactId>
-            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
-            <version>5.0.0</version>
         </dependency>
     </dependencies>
     <packaging>bundle</packaging>
index 24cb99f8c367cd566c576f877cb6bcb20b6519e9..8a9d1678657c6b3555ba23d4a3c536cae5d3d30d 100644 (file)
@@ -14,7 +14,7 @@ import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 
-public interface RpcProvisionRegistry extends BrokerService, RouteChangePublisher<RpcRoutingContext, InstanceIdentifier> {
+public interface RpcProvisionRegistry extends RpcImplementation, BrokerService, RouteChangePublisher<RpcRoutingContext, InstanceIdentifier> {
 
     /**
      * Registers an implementation of the rpc.
index 8553d9eea5d9c9259f7ff55f638871b4be4e6b46..d22b54ee19c2e1dde0b3f75f7f63ef3f7f3005e5 100644 (file)
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-core-api</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common-util</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common-impl</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-core-spi</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
@@ -50,7 +46,6 @@
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>config-api</artifactId>
-            <version>0.2.4-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
index aa5138a04db226d777c70dbd8ece6d3df5b77736..3bbdab2c0722d656aba74035186faa4bc0d843aa 100644 (file)
@@ -8,32 +8,27 @@
 package org.opendaylight.controller.sal.dom.broker;
 
 import java.util.Collections
-import java.util.HashMap
 import java.util.HashSet
-import java.util.Map
 import java.util.Set
 import java.util.concurrent.Callable
 import java.util.concurrent.ExecutorService
 import java.util.concurrent.Executors
 import java.util.concurrent.Future
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener
 import org.opendaylight.controller.sal.core.api.Broker
-import org.opendaylight.controller.sal.core.api.BrokerService
 import org.opendaylight.controller.sal.core.api.Consumer
 import org.opendaylight.controller.sal.core.api.Provider
-import org.opendaylight.controller.sal.core.spi.BrokerModule
+import org.opendaylight.controller.sal.core.api.RpcImplementation
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry
+import org.opendaylight.controller.sal.core.api.RpcRegistrationListener
+import org.opendaylight.controller.sal.core.api.RpcRoutingContext
+import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter
 import org.opendaylight.yangtools.yang.common.QName
 import org.opendaylight.yangtools.yang.common.RpcResult
 import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
 import org.osgi.framework.BundleContext
 import org.slf4j.LoggerFactory
-import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter
-import org.opendaylight.yangtools.concepts.ListenerRegistration
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry
-import org.opendaylight.controller.sal.core.api.RpcImplementation
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener
-import org.opendaylight.controller.sal.core.api.RpcRoutingContext
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
 
 public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
     private static val log = LoggerFactory.getLogger(BrokerImpl);
@@ -73,7 +68,7 @@ public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
         return session;
     }
 
-    protected def Future<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
+    protected def Future<RpcResult<CompositeNode>> invokeRpcAsync(QName rpc, CompositeNode input) {
         val result = executor.submit([|router.invokeRpc(rpc, input)] as Callable<RpcResult<CompositeNode>>);
         return result;
     }
@@ -135,5 +130,13 @@ public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
     override <L extends RouteChangeListener<RpcRoutingContext, InstanceIdentifier>> registerRouteChangeListener(L listener) {
         return router.registerRouteChangeListener(listener);
     }
+
+    override invokeRpc(QName rpc,CompositeNode input){
+        return router.invokeRpc(rpc,input)
+    }
+
+    override getSupportedRpcs() {
+        return router.getSupportedRpcs();
+    }
     
 }
index e4808e9bd6ddfdc86dace504e67f8173eb1e8ca9..813f52b67d4bab0632fdefb6a9fe7d23d8054792 100644 (file)
@@ -37,7 +37,7 @@ class ConsumerContextImpl implements ConsumerSession {
     }
 
     override rpc(QName rpc, CompositeNode input) {
-        return broker.invokeRpc(rpc, input);
+        return broker.invokeRpcAsync(rpc, input);
     }
 
     override <T extends BrokerService> T getService(Class<T> service) {
index 5a3e060a3c9a52a2c55b4876b283ec5559de63e5..a8bdddb5108d3ab0242024b7c3db4df3a1d1694a 100644 (file)
@@ -219,4 +219,6 @@ public class MountPointImpl implements MountProvisionInstance, SchemaContextProv
             L listener) {
         return rpcs.registerRouteChangeListener(listener);
     }
+
+
 }
index cc44613e448ad520063120f31c481e987f032ee5..95d0018b2117c8c970a61c7902bbc44f2b3d8396 100644 (file)
@@ -7,29 +7,26 @@
  */
 package org.opendaylight.controller.sal.dom.broker.impl
 
-import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.controller.md.sal.common.api.data.DataReader
-import org.opendaylight.yangtools.yang.common.QName
 import java.net.URI
-import java.util.List
-import org.opendaylight.yangtools.yang.data.api.Node
 import java.util.ArrayList
-import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
-import java.util.Map
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
-import org.opendaylight.yangtools.yang.data.api.SimpleNode
+import java.util.Collection
 import java.util.Collections
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
 import java.util.HashMap
-import static com.google.common.base.Preconditions.*;
-import java.util.Collection
-import java.util.Set
+import java.util.Map
 import java.util.Map.Entry
-import org.slf4j.LoggerFactory
+import java.util.Set
+import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.data.api.SimpleNode
 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import org.slf4j.LoggerFactory
+
+import static com.google.common.base.Preconditions.*
 
 class DataReaderRouter extends AbstractDataReadRouter<InstanceIdentifier, CompositeNode> {
     private static val LOG = LoggerFactory.getLogger(DataReaderRouter);
@@ -42,7 +39,6 @@ class DataReaderRouter extends AbstractDataReadRouter<InstanceIdentifier, Compos
         var name = pathArgument?.nodeType;
         val nodes = new ArrayList<Node<?>>();
         val keyNodes = new HashMap<QName, SimpleNode<?>>();
-        val iterator = data.iterator;
         for(dataBit : data) {
             try {
                 if(pathArgument != null && dataBit != null) {
index 9600881e505abdeb8c4d5022d4f1c91c94907e80..12835ccf0a235ec2a312e32313818525425c6f36 100644 (file)
@@ -18,9 +18,11 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
 import org.opendaylight.yangtools.yang.data.api.CompositeNode
 import org.opendaylight.controller.sal.core.api.data.DataStore
 import java.util.HashSet
+import org.slf4j.LoggerFactory
+import org.slf4j.Logger
 
-class HashMapDataStore implements DataStore, AutoCloseable {
-
+final class HashMapDataStore implements DataStore, AutoCloseable {
+    private val Logger LOG = LoggerFactory.getLogger(HashMapDataStore)
 
     val Map<InstanceIdentifier, CompositeNode> configuration = new ConcurrentHashMap();
     val Map<InstanceIdentifier, CompositeNode> operational = new ConcurrentHashMap();
@@ -28,12 +30,11 @@ class HashMapDataStore implements DataStore, AutoCloseable {
     
     
     override containsConfigurationPath(InstanceIdentifier path) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-        
+        return configuration.containsKey(path)
     }
     
     override containsOperationalPath(InstanceIdentifier path) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+        return operational.containsKey(path)
     }
     
     override getStoredConfigurationPaths() {
@@ -45,10 +46,12 @@ class HashMapDataStore implements DataStore, AutoCloseable {
     }
 
     override readConfigurationData(InstanceIdentifier path) {
+        LOG.trace("Reading configuration path {}", path)
         configuration.get(path);
     }
 
     override readOperationalData(InstanceIdentifier path) {
+        LOG.trace("Reading operational path {}", path)
         operational.get(path);
     }
 
@@ -65,11 +68,21 @@ class HashMapDataStore implements DataStore, AutoCloseable {
     def RpcResult<Void> finish(HashMapDataStoreTransaction transaction) {
         val modification = transaction.modification;
         for (removal : modification.removedConfigurationData) {
+            LOG.trace("Removing configuration path {}", removal)
             remove(configuration,removal);
         }
         for (removal : modification.removedOperationalData) {
+            LOG.trace("Removing operational path {}", removal)
             remove(operational,removal);
         }
+        if (LOG.isTraceEnabled()) {
+            for (a : modification.updatedConfigurationData.keySet) {
+                LOG.trace("Adding configuration path {}", a)
+            }
+            for (a : modification.updatedOperationalData.keySet) {
+                LOG.trace("Adding operational path {}", a)
+            }
+        }
         configuration.putAll(modification.updatedConfigurationData);
         operational.putAll(modification.updatedOperationalData);
 
@@ -84,6 +97,7 @@ class HashMapDataStore implements DataStore, AutoCloseable {
             }
         }
         for(pathToRemove : affected) {
+            LOG.trace("Removed path {}", pathToRemove)
             map.remove(pathToRemove);
         }
         
index b02a37c3003e594b728554f6c5a0124961872ce3..602afd7c0cf01d4bccc810e0b0dc2d1e5d9a0fd4 100644 (file)
@@ -150,7 +150,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
 
     protected CompositeNode mergeData(InstanceIdentifier path, CompositeNode stored, CompositeNode modified,
             boolean config) {
-        long startTime = System.nanoTime();
+        // long startTime = System.nanoTime();
         try {
             DataSchemaNode node = schemaNodeFor(path);
             return YangDataOperations.merge(node, stored, modified, config);
index e375e14cf2e96bf9e4ca29998a156df402ec3420..e218a957826f110bd36d3acb3fe059fc69b5092a 100644 (file)
@@ -16,9 +16,13 @@ import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
 import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.osgi.framework.ServiceReference;
 
+import java.util.Set;
+
 public class RpcProvisionRegistryProxy extends AbstractBrokerServiceProxy<RpcProvisionRegistry>
                                        implements RpcProvisionRegistry {
 
@@ -45,4 +49,15 @@ public class RpcProvisionRegistryProxy extends AbstractBrokerServiceProxy<RpcPro
     public <L extends RouteChangeListener<RpcRoutingContext, InstanceIdentifier>> ListenerRegistration<L> registerRouteChangeListener(L listener) {
         return getDelegate().registerRouteChangeListener(listener);
     }
+
+
+  @Override
+  public Set<QName> getSupportedRpcs() {
+    return getDelegate().getSupportedRpcs();
+  }
+
+  @Override
+  public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
+    return getDelegate().invokeRpc(rpc,input);
+  }
 }
index 1e89281df498b34d82bea1f3e6b08574c0941a06..d80e405b4e05dc7df3bd9ed5c9de3610644e7b18 100644 (file)
@@ -38,12 +38,6 @@ class YangDataOperations {
         throw new IllegalArgumentException("Supplied node is not data node container.");
     }
 
-    private def static checkConfigurational(DataSchemaNode node, boolean config) {
-        if (config) {
-            checkArgument(node.configuration, "Supplied composite node is not configurational.");
-        }
-    }
-
     private static dispatch def Iterable<? extends Node<?>> mergeMultiple(LeafSchemaNode node, List<Node<?>> original,
         List<Node<?>> modified, boolean configurational) {
         checkArgument(original.size === 1);
index 8aa2a006f6723a9e94f8caa05e748c798054d2e8..e007ee7429faa418ee6e7fdd98e2e9f67fad93e1 100644 (file)
@@ -17,7 +17,6 @@
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-core-api</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
     </dependencies>
     <packaging>bundle</packaging>
index 597b02ebb5d1f480e041146507075bfd61735a3b..b060ca42d0bca2423cc1af699973706162805f17 100644 (file)
@@ -33,7 +33,6 @@
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>netty-threadgroup-config</artifactId>
-            <version>0.2.4-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>logback-config</artifactId>
             <scope>test</scope>
-            <version>${netconf.version}</version>
         </dependency>
         <dependency>
             <groupId>org.mockito</groupId>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-broker-impl</artifactId>
-            <version>1.1-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
         <dependency>
            <groupId>org.opendaylight.controller</groupId>
            <artifactId>sal-binding-broker-impl</artifactId>
-           <version>1.1-SNAPSHOT</version>
            <type>test-jar</type>
            <scope>test</scope>
         </dependency>
         <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>ietf-netconf-monitoring</artifactId>
-        <version>0.2.4-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools.model</groupId>
             <artifactId>ietf-inet-types</artifactId>
-            <version>2010.09.24.3</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>threadpool-config-api</artifactId>
-            <version>0.2.4-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>netty-config-api</artifactId>
-            <version>0.2.4-SNAPSHOT</version>
         </dependency>
     </dependencies>
 
index c16ee170def8fe7fc13c24a15456058e0a356b8c..c5390e540911d23865b83d53aaf55c230f1098dd 100644 (file)
@@ -7,11 +7,11 @@
  */
 package org.opendaylight.controller.sal.connect.netconf;
 
-import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_ACTION_QNAME;
 import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_CANDIDATE_QNAME;
 import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_COMMIT_QNAME;
 import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_CONFIG_QNAME;
 import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_EDIT_CONFIG_QNAME;
+import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_OPERATION_QNAME;
 import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_RUNNING_QNAME;
 import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_TARGET_QNAME;
 
@@ -52,7 +52,7 @@ public class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransac
 
     public void prepare() {
         for (InstanceIdentifier toRemove : modification.getRemovedConfigurationData()) {
-            sendRemove(toRemove);
+            sendDelete(toRemove);
         }
         for(Entry<InstanceIdentifier, CompositeNode> toUpdate : modification.getUpdatedConfigurationData().entrySet()) {
             sendMerge(toUpdate.getKey(),toUpdate.getValue());
@@ -64,8 +64,8 @@ public class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransac
         sendEditRpc(createEditStructure(key, Optional.<String>absent(), Optional.of(value)));
     }
 
-    private void sendRemove(InstanceIdentifier toRemove) {
-        sendEditRpc(createEditStructure(toRemove, Optional.of("remove"), Optional.<CompositeNode> absent()));
+    private void sendDelete(InstanceIdentifier toDelete) {
+        sendEditRpc(createEditStructure(toDelete, Optional.of("delete"), Optional.<CompositeNode> absent()));
     }
 
     private void sendEditRpc(CompositeNode editStructure) {
@@ -92,7 +92,7 @@ public class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransac
         return ret;
     }
 
-    private CompositeNode createEditStructure(InstanceIdentifier dataPath, Optional<String> action,
+    private CompositeNode createEditStructure(InstanceIdentifier dataPath, Optional<String> operation,
             Optional<CompositeNode> lastChildOverride) {
         List<PathArgument> path = dataPath.getPath();
         List<PathArgument> reversed = Lists.reverse(path);
@@ -110,8 +110,8 @@ public class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransac
             }
 
             if (isLast) {
-                if (action.isPresent()) {
-                    builder.setAttribute(NETCONF_ACTION_QNAME, action.get());
+                if (operation.isPresent()) {
+                    builder.setAttribute(NETCONF_OPERATION_QNAME, operation.get());
                 }
                 if (lastChildOverride.isPresent()) {
                     List<Node<?>> children = lastChildOverride.get().getChildren();
@@ -132,7 +132,7 @@ public class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransac
     }
 
     @Override
-    public RpcResult<Void> finish() throws IllegalStateException {
+    public RpcResult<Void> finish() {
         CompositeNodeBuilder<ImmutableCompositeNode> commitInput = ImmutableCompositeNode.builder();
         commitInput.setQName(NETCONF_COMMIT_QNAME);
         RpcResult<?> rpcResult = device.invokeRpc(NetconfMapping.NETCONF_COMMIT_QNAME, commitInput.toInstance());
index 53ed49cd2a73a4b97b44b697fb923f63a32ece7c..e5a24fcf63914f35492f50e7186ff2ed844761e4 100644 (file)
@@ -27,7 +27,6 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
 import org.opendaylight.yangtools.yang.data.api.Node
 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode
-import org.opendaylight.yangtools.yang.data.impl.NodeUtils
 import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
 import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils
 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
@@ -50,7 +49,7 @@ class NetconfMapping {
     public static val NETCONF_GET_CONFIG_QNAME = QName.create(NETCONF_QNAME, "get-config");
     public static val NETCONF_EDIT_CONFIG_QNAME = QName.create(NETCONF_QNAME, "edit-config");
     public static val NETCONF_DELETE_CONFIG_QNAME = QName.create(NETCONF_QNAME, "delete-config");
-    public static val NETCONF_ACTION_QNAME = QName.create(NETCONF_QNAME, "action");
+    public static val NETCONF_OPERATION_QNAME = QName.create(NETCONF_QNAME, "operation");
     public static val NETCONF_COMMIT_QNAME = QName.create(NETCONF_QNAME, "commit");
     
     public static val NETCONF_CONFIG_QNAME = QName.create(NETCONF_QNAME, "config");
@@ -92,6 +91,9 @@ class NetconfMapping {
         for (arg : argument.keyValues.entrySet) {
             list.add = new SimpleNodeTOImpl(arg.key, null, arg.value);
         }
+        if (node != null) {
+            list.add(node);
+        }
         return new CompositeNodeTOImpl(argument.nodeType, null, list)
     }
 
@@ -120,9 +122,9 @@ class NetconfMapping {
     }
 
     static def NetconfMessage toRpcMessage(QName rpc, CompositeNode node,Optional<SchemaContext> ctx) {
-        val rpcPayload = wrap(NETCONF_RPC_QNAME, flattenInput(node));
-        val w3cPayload = NodeUtils.buildShadowDomTree(rpcPayload);
-        w3cPayload.documentElement.setAttribute("message-id", "m-" + messageId.andIncrement);
+        val rpcPayload = wrap(NETCONF_RPC_QNAME, flattenInput(node))
+        val w3cPayload = XmlDocumentUtils.toDocument(rpcPayload, XmlDocumentUtils.defaultValueCodecProvider)
+        w3cPayload.documentElement.setAttribute("message-id", "m-" + messageId.andIncrement)
         return new NetconfMessage(w3cPayload);
     }
     
index a4d2f4ca25d729b68eaabebf4e84d444d72b800c..cc3b0296ed3ed299ab0ffe5a58b3d2e2775b78bd 100644 (file)
@@ -48,7 +48,6 @@
     <dependency>
       <groupId>com.google.code.gson</groupId>
       <artifactId>gson</artifactId>
-      <version>2.2.4</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
@@ -57,7 +56,6 @@
     <dependency>
       <groupId>io.netty</groupId>
       <artifactId>netty-codec-http</artifactId>
-      <version>4.0.10.Final</version>
     </dependency>
     
     <!-- Testing Dependencies -->
@@ -74,7 +72,6 @@
     <dependency>
       <groupId>ch.qos.logback</groupId>
       <artifactId>logback-classic</artifactId>
-      <version>1.0.9</version>
       <scope>test</scope>
     </dependency>
     <dependency>
index cef5df9e579fb5c8142ca186364044c591421a91..f6c39bf8c5a3ac70d75b8490f01aa2c5dfe73bc7 100644 (file)
@@ -16,6 +16,7 @@ import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.Encoded;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
@@ -106,25 +107,25 @@ public interface RestconfService {
     @Path("/config/{identifier:.+}")
     @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
                MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public StructuredData readConfigurationData(@PathParam("identifier") String identifier);
+    public StructuredData readConfigurationData(@Encoded @PathParam("identifier") String identifier);
 
     @GET
     @Path("/operational/{identifier:.+}")
     @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
                MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public StructuredData readOperationalData(@PathParam("identifier") String identifier);
+    public StructuredData readOperationalData(@Encoded @PathParam("identifier") String identifier);
 
     @PUT
     @Path("/config/{identifier:.+}")
     @Consumes({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
                MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public Response updateConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
+    public Response updateConfigurationData(@Encoded @PathParam("identifier") String identifier, CompositeNode payload);
 
     @POST
     @Path("/config/{identifier:.+}")
     @Consumes({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
                MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public Response createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
+    public Response createConfigurationData(@Encoded @PathParam("identifier") String identifier, CompositeNode payload);
 
     @POST
     @Path("/config")
@@ -134,10 +135,10 @@ public interface RestconfService {
 
     @DELETE
     @Path("/config/{identifier:.+}")
-    public Response deleteConfigurationData(@PathParam("identifier") String identifier);
+    public Response deleteConfigurationData(@Encoded @PathParam("identifier") String identifier);
 
     @GET
     @Path("/streams/stream/{identifier:.+}")
-    public Response subscribeToStream(@PathParam("identifier") String identifier, @Context UriInfo uriInfo);
+    public Response subscribeToStream(@Encoded @PathParam("identifier") String identifier, @Context UriInfo uriInfo);
 
 }
index c2b82eae632290cc60d48df245d70fa1c583e8b8..f1d412cdb0082960aa02f93dcffbc3b5ba0ca6e3 100644 (file)
@@ -57,6 +57,8 @@ class ControllerContext implements SchemaServiceListener {
     val static MOUNT_MODULE = "yang-ext"
     val static MOUNT_NODE = "mount"
     public val static MOUNT = "yang-ext:mount"
+    val static URI_ENCODING_CHAR_SET = "ISO-8859-1"
+    val static URI_SLASH_PLACEHOLDER = "%2F";
 
     @Property
     var SchemaContext globalSchema;
@@ -98,7 +100,8 @@ class ControllerContext implements SchemaServiceListener {
 
     private def InstanceIdWithSchemaNode toIdentifier(String restconfInstance, boolean toMountPointIdentifier) {
         checkPreconditions
-        val pathArgs = Lists.newArrayList(Splitter.on("/").split(restconfInstance))
+        val encodedPathArgs = Lists.newArrayList(Splitter.on("/").split(restconfInstance))
+        val pathArgs = urlPathArgsDecode(encodedPathArgs)
         pathArgs.omitFirstAndLastEmptyString
         if (pathArgs.empty) {
             return null;
@@ -353,7 +356,8 @@ class ControllerContext implements SchemaServiceListener {
 
     private def toUriString(Object object) {
         if(object === null) return "";
-        return URLEncoder.encode(object.toString)
+//        return object.toString.replace("/",URI_SLASH_PLACEHOLDER)
+        return URLEncoder.encode(object.toString,URI_ENCODING_CHAR_SET)        
     }
     
     private def InstanceIdWithSchemaNode collectPathArguments(InstanceIdentifierBuilder builder, List<String> strings,
@@ -606,4 +610,13 @@ class ControllerContext implements SchemaServiceListener {
         }
     }
 
+
+    def urlPathArgsDecode(List<String> strings) {
+        val List<String> decodedPathArgs = new ArrayList();
+        for (pathArg : strings) {
+            decodedPathArgs.add(URLDecoder.decode(pathArg, URI_ENCODING_CHAR_SET))
+        }
+        return decodedPathArgs
+    }    
+
 }
index e1d7e6a62447d3b1145c4bb672267ec77e4fc762..5a2c964b8b15a8eb46c6fea2cc46e77c350cdcdf 100644 (file)
@@ -15,7 +15,6 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.JSON;
 import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.XML;
-import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.createUri;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -24,6 +23,7 @@ import java.io.UnsupportedEncodingException;
 import javax.ws.rs.client.Entity;
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
 
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
@@ -70,7 +70,7 @@ public class MediaTypesTest extends JerseyTest {
   public void testPostOperationsWithInputDataMediaTypes() throws UnsupportedEncodingException {
       String uriPrefix = "/operations/";
       String uriPath = "ietf-interfaces:interfaces";
-      String uri = createUri(uriPrefix, uriPath);
+      String uri = uriPrefix + uriPath;
       when(restconfService.invokeRpc(eq(uriPath), any(CompositeNode.class))).thenReturn(null);
       post(uri, Draft02.MediaTypes.OPERATION+JSON, Draft02.MediaTypes.OPERATION+JSON, jsonData);
       verify(restconfService, times(1)).invokeRpc(eq(uriPath), any(CompositeNode.class));
@@ -96,7 +96,7 @@ public class MediaTypesTest extends JerseyTest {
     public void testGetConfigMediaTypes() throws UnsupportedEncodingException {
         String uriPrefix = "/config/";
         String uriPath = "ietf-interfaces:interfaces";
-        String uri = createUri(uriPrefix, uriPath);
+        String uri = uriPrefix + uriPath;
         when(restconfService.readConfigurationData(uriPath)).thenReturn(null);
         get(uri, Draft02.MediaTypes.DATA+JSON);
         verify(restconfService, times(1)).readConfigurationData(uriPath);
@@ -118,7 +118,7 @@ public class MediaTypesTest extends JerseyTest {
     public void testGetOperationalMediaTypes() throws UnsupportedEncodingException {
         String uriPrefix = "/operational/";
         String uriPath = "ietf-interfaces:interfaces";
-        String uri = createUri(uriPrefix, uriPath);
+        String uri = uriPrefix + uriPath;
         when(restconfService.readOperationalData(uriPath)).thenReturn(null);
         get(uri, Draft02.MediaTypes.DATA+JSON);
         verify(restconfService, times(1)).readOperationalData(uriPath);
@@ -140,7 +140,7 @@ public class MediaTypesTest extends JerseyTest {
     public void testPutConfigMediaTypes() throws UnsupportedEncodingException {
         String uriPrefix = "/config/";
         String uriPath = "ietf-interfaces:interfaces";
-        String uri = createUri(uriPrefix, uriPath);
+        String uri = uriPrefix + uriPath;
         when(restconfService.updateConfigurationData(eq(uriPath), any(CompositeNode.class))).thenReturn(null);
         put(uri, null, Draft02.MediaTypes.DATA+JSON, jsonData);
         verify(restconfService, times(1)).updateConfigurationData(eq(uriPath), any(CompositeNode.class));
@@ -160,7 +160,7 @@ public class MediaTypesTest extends JerseyTest {
     public void testPostConfigWithPathMediaTypes() throws UnsupportedEncodingException {
         String uriPrefix = "/config/";
         String uriPath = "ietf-interfaces:interfaces";
-        String uri = createUri(uriPrefix, uriPath);
+        String uri = uriPrefix + uriPath;
         when(restconfService.createConfigurationData(eq(uriPath), any(CompositeNode.class))).thenReturn(null);
         post(uri, null, Draft02.MediaTypes.DATA+JSON, jsonData);
         verify(restconfService, times(1)).createConfigurationData(eq(uriPath), any(CompositeNode.class));
@@ -179,7 +179,7 @@ public class MediaTypesTest extends JerseyTest {
     @Test
     public void testPostConfigMediaTypes() throws UnsupportedEncodingException {
         String uriPrefix = "/config/";
-        String uri = createUri(uriPrefix, "");
+        String uri = uriPrefix;
         when(restconfService.createConfigurationData(any(CompositeNode.class))).thenReturn(null);
         post(uri, null, Draft02.MediaTypes.DATA+JSON, jsonData);
         verify(restconfService, times(1)).createConfigurationData(any(CompositeNode.class));
@@ -199,7 +199,7 @@ public class MediaTypesTest extends JerseyTest {
     public void testDeleteConfigMediaTypes() throws UnsupportedEncodingException {
         String uriPrefix = "/config/";
         String uriPath = "ietf-interfaces:interfaces";
-        String uri = createUri(uriPrefix, uriPath);
+        String uri = uriPrefix + uriPath;
         when(restconfService.deleteConfigurationData(eq(uriPath))).thenReturn(null);
         target(uri).request("fooMediaType").delete();
         verify(restconfService, times(1)).deleteConfigurationData(uriPath);
index 73b4b3a2af4d8092b2076d7b79c6c78aabc004f6..408b14acfe8e67d93fb45c31a55fd0700f9b23a5 100644 (file)
@@ -12,7 +12,6 @@ import static org.junit.Assert.assertNotNull;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
-import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.createUri;
 
 import java.io.FileNotFoundException;
 import java.io.UnsupportedEncodingException;
@@ -72,7 +71,7 @@ public class RestDeleteOperationTest extends JerseyTest {
 
     @Test
     public void deleteConfigStatusCodes() throws UnsupportedEncodingException {
-        String uri = createUri("/config/", "test-interface:interfaces");
+        String uri = "/config/test-interface:interfaces";
         Future<RpcResult<TransactionStatus>> dummyFuture = createFuture(TransactionStatus.COMMITED);
         when(brokerFacade.commitConfigurationDataDelete(any(InstanceIdentifier.class))).thenReturn(dummyFuture);
         Response response = target(uri).request(MediaType.APPLICATION_XML).delete();
index 1e01020e78925f6b8b33606da8f43967a584ff12..6f507f96e27faf82550e4bc92a842528b888c5c0 100644 (file)
@@ -12,7 +12,6 @@ import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
-import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.createUri;
 
 import java.io.FileNotFoundException;
 import java.io.UnsupportedEncodingException;
@@ -94,10 +93,10 @@ public class RestGetOperationTest extends JerseyTest {
     @Test
     public void getOperationalStatusCodes() throws UnsupportedEncodingException {
         mockReadOperationalDataMethod();
-        String uri = createUri("/operational/", "ietf-interfaces:interfaces/interface/eth0");
+        String uri = "/operational/ietf-interfaces:interfaces/interface/eth0";
         assertEquals(200, get(uri, MediaType.APPLICATION_XML));
 
-        uri = createUri("/operational/", "wrong-module:interfaces/interface/eth0");
+        uri = "/operational/wrong-module:interfaces/interface/eth0";
         assertEquals(400, get(uri, MediaType.APPLICATION_XML));
     }
 
@@ -107,10 +106,10 @@ public class RestGetOperationTest extends JerseyTest {
     @Test
     public void getConfigStatusCodes() throws UnsupportedEncodingException {
         mockReadConfigurationDataMethod();
-        String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0");
+        String uri = "/config/ietf-interfaces:interfaces/interface/eth0";
         assertEquals(200, get(uri, MediaType.APPLICATION_XML));
 
-        uri = createUri("/config/", "wrong-module:interfaces/interface/eth0");
+        uri = "/config/wrong-module:interfaces/interface/eth0";
         assertEquals(400, get(uri, MediaType.APPLICATION_XML));
     }
 
@@ -129,11 +128,10 @@ public class RestGetOperationTest extends JerseyTest {
 
         ControllerContext.getInstance().setMountService(mockMountService);
 
-        String uri = createUri("/config/",
-                "ietf-interfaces:interfaces/interface/0/yang-ext:mount/test-module:cont/cont1");
+        String uri = "/config/ietf-interfaces:interfaces/interface/0/yang-ext:mount/test-module:cont/cont1";
         assertEquals(200, get(uri, MediaType.APPLICATION_XML));
 
-        uri = createUri("/config/", "ietf-interfaces:interfaces/yang-ext:mount/test-module:cont/cont1");
+        uri = "/config/ietf-interfaces:interfaces/yang-ext:mount/test-module:cont/cont1";
         assertEquals(200, get(uri, MediaType.APPLICATION_XML));
     }
 
@@ -149,7 +147,7 @@ public class RestGetOperationTest extends JerseyTest {
 
         ControllerContext.getInstance().setMountService(mockMountService);
 
-        String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/0/yang-ext:mount/");
+        String uri = "/config/ietf-interfaces:interfaces/interface/0/yang-ext:mount/";
         assertEquals(200, get(uri, MediaType.APPLICATION_XML));
     }
 
@@ -158,7 +156,7 @@ public class RestGetOperationTest extends JerseyTest {
     public void getModulesTest() throws UnsupportedEncodingException, FileNotFoundException {
         ControllerContext.getInstance().setGlobalSchema(schemaContextModules);
 
-        String uri = createUri("/modules", "");
+        String uri = "/modules";
 
         Response response = target(uri).request("application/yang.api+json").get();
         validateModulesResponseJson(response);
@@ -172,7 +170,7 @@ public class RestGetOperationTest extends JerseyTest {
     public void getModuleTest() throws FileNotFoundException, UnsupportedEncodingException {
         ControllerContext.getInstance().setGlobalSchema(schemaContextModules);
 
-        String uri = createUri("/modules/module/module2/2014-01-02", "");
+        String uri = "/modules/module/module2/2014-01-02";
 
         Response response = target(uri).request("application/yang.api+xml").get();
         assertEquals(200, response.getStatus());
@@ -197,7 +195,7 @@ public class RestGetOperationTest extends JerseyTest {
     public void getOperationsTest() throws FileNotFoundException, UnsupportedEncodingException {
         ControllerContext.getInstance().setGlobalSchema(schemaContextModules);
 
-        String uri = createUri("/operations", "");
+        String uri = "/operations";
 
         Response response = target(uri).request("application/yang.api+xml").get();
         assertEquals(200, response.getStatus());
@@ -238,7 +236,7 @@ public class RestGetOperationTest extends JerseyTest {
 
         controllerContext.setMountService(mockMountService);
 
-        String uri = createUri("/operations/", "ietf-interfaces:interfaces/interface/0/yang-ext:mount/");
+        String uri = "/operations/ietf-interfaces:interfaces/interface/0/yang-ext:mount/";
 
         Response response = target(uri).request("application/yang.api+xml").get();
         assertEquals(200, response.getStatus());
@@ -329,7 +327,7 @@ public class RestGetOperationTest extends JerseyTest {
 
         controllerContext.setMountService(mockMountService);
 
-        String uri = createUri("/modules/", "ietf-interfaces:interfaces/interface/0/yang-ext:mount/");
+        String uri = "/modules/ietf-interfaces:interfaces/interface/0/yang-ext:mount/";
 
         Response response = target(uri).request("application/yang.api+json").get();
         assertEquals(200, response.getStatus());
@@ -371,8 +369,7 @@ public class RestGetOperationTest extends JerseyTest {
 
         controllerContext.setMountService(mockMountService);
 
-        String uri = createUri("/modules/module/",
-                "ietf-interfaces:interfaces/interface/0/yang-ext:mount/module1-behind-mount-point/2014-02-03");
+        String uri = "/modules/module/ietf-interfaces:interfaces/interface/0/yang-ext:mount/module1-behind-mount-point/2014-02-03";
 
         Response response = target(uri).request("application/yang.api+json").get();
         assertEquals(200, response.getStatus());
index a0e61a6fa12335239ba94efd386e841eda745d1c..7bf4782790506631de6652a2ef67126071d9ba74 100644 (file)
@@ -7,12 +7,6 @@
  */
 package org.opendaylight.controller.sal.restconf.impl.test;
 
-import java.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.net.URLEncoder;
-
-import com.google.common.base.Charsets;
-
 public class RestOperationUtils {
 
     public static final String JSON = "+json";
@@ -20,8 +14,4 @@ public class RestOperationUtils {
 
     private RestOperationUtils() {
     }
-
-    public static String createUri(String prefix, String encodedPart) throws UnsupportedEncodingException {
-        return URI.create(prefix + URLEncoder.encode(encodedPart, Charsets.US_ASCII.name()).toString()).toASCIIString();
-    }
 }
index 050aa9ab240575c8a216f8e4678787c25fdb3003..11264e7f860dcdd9c2820f7a8a89b056add4fca8 100644 (file)
@@ -109,7 +109,7 @@ public class RestPostOperationTest extends JerseyTest {
     public void postOperationsStatusCodes() throws UnsupportedEncodingException {
         controllerContext.setSchemas(schemaContextTestModule);
         mockInvokeRpc(cnSnDataOutput, true);
-        String uri = createUri("/operations/", "test-module:rpc-test");
+        String uri = "/operations/test-module:rpc-test";
         assertEquals(200, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
 
         mockInvokeRpc(null, true);
@@ -118,7 +118,7 @@ public class RestPostOperationTest extends JerseyTest {
         mockInvokeRpc(null, false);
         assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
 
-        uri = createUri("/operations/", "test-module:rpc-wrongtest");
+        uri = "/operations/test-module:rpc-wrongtest";
         assertEquals(404, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
     }
 
@@ -126,7 +126,7 @@ public class RestPostOperationTest extends JerseyTest {
     public void postConfigOnlyStatusCodes() throws UnsupportedEncodingException {
         controllerContext.setSchemas(schemaContextYangsIetf);
         mockCommitConfigurationDataPostMethod(TransactionStatus.COMMITED);
-        String uri = createUri("/config", "");
+        String uri = "/config";
         assertEquals(204, post(uri, MediaType.APPLICATION_XML, xmlDataAbsolutePath));
 
         mockCommitConfigurationDataPostMethod(null);
@@ -140,7 +140,7 @@ public class RestPostOperationTest extends JerseyTest {
     public void postConfigStatusCodes() throws UnsupportedEncodingException {
         controllerContext.setSchemas(schemaContextYangsIetf);
         mockCommitConfigurationDataPostMethod(TransactionStatus.COMMITED);
-        String uri = createUri("/config/", "ietf-interfaces:interfaces");
+        String uri = "/config/ietf-interfaces:interfaces";
         assertEquals(204, post(uri, MediaType.APPLICATION_XML, xmlDataInterfaceAbsolutePath));
 
         mockCommitConfigurationDataPostMethod(null);
@@ -167,9 +167,9 @@ public class RestPostOperationTest extends JerseyTest {
 
         ControllerContext.getInstance().setMountService(mockMountService);
 
-        String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/0/");
+        String uri = "/config/ietf-interfaces:interfaces/interface/0/";
         assertEquals(204, post(uri, Draft02.MediaTypes.DATA + XML, xmlData4));
-        uri = createUri("/config/", "ietf-interfaces:interfaces/interface/0/yang-ext:mount/test-module:cont");
+        uri = "/config/ietf-interfaces:interfaces/interface/0/yang-ext:mount/test-module:cont";
         assertEquals(204, post(uri, Draft02.MediaTypes.DATA + XML, xmlData3));
     }
 
@@ -206,13 +206,13 @@ public class RestPostOperationTest extends JerseyTest {
         ArgumentCaptor<InstanceIdentifier> instanceIdCaptor = ArgumentCaptor.forClass(InstanceIdentifier.class);
         ArgumentCaptor<CompositeNode> compNodeCaptor = ArgumentCaptor.forClass(CompositeNode.class);
 
-        String URI_1 = createUri("/config", "");
+        String URI_1 = "/config";
         assertEquals(204, post(URI_1, Draft02.MediaTypes.DATA + XML, xmlTestInterface));
         verify(brokerFacade).commitConfigurationDataPost(instanceIdCaptor.capture(), compNodeCaptor.capture());
         String identifier = "[(urn:ietf:params:xml:ns:yang:test-interface?revision=2014-07-01)interfaces]";
         assertEquals(identifier, instanceIdCaptor.getValue().getPath().toString());
 
-        String URI_2 = createUri("/config/", "test-interface:interfaces");
+        String URI_2 = "/config/test-interface:interfaces";
         assertEquals(204, post(URI_2, Draft02.MediaTypes.DATA + XML, xmlBlockData));
         verify(brokerFacade, times(2))
                 .commitConfigurationDataPost(instanceIdCaptor.capture(), compNodeCaptor.capture());
@@ -227,17 +227,13 @@ public class RestPostOperationTest extends JerseyTest {
         when(brokerFacade.commitConfigurationDataPost(any(InstanceIdentifier.class), any(CompositeNode.class)))
                 .thenReturn(null);
 
-        String URI_1 = createUri("/config", "");
+        String URI_1 = "/config";
         assertEquals(202, post(URI_1, Draft02.MediaTypes.DATA + XML, xmlTestInterface));
 
-        String URI_2 = createUri("/config/", "test-interface:interfaces");
+        String URI_2 = "/config/test-interface:interfaces";
         assertEquals(202, post(URI_2, Draft02.MediaTypes.DATA + XML, xmlBlockData));
     }
 
-    private String createUri(String prefix, String encodedPart) throws UnsupportedEncodingException {
-        return URI.create(prefix + URLEncoder.encode(encodedPart, Charsets.US_ASCII.name()).toString()).toASCIIString();
-    }
-
     private static void initMocking() {
         controllerContext = ControllerContext.getInstance();
         controllerContext.setSchemas(schemaContext);
index 2ba4a38c88582f9cb1c4ba49a8a586024c070e37..3af2945526466fabf3e9c139b79eb4134107752f 100644 (file)
@@ -11,7 +11,6 @@ import static org.junit.Assert.assertEquals;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
-import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.createUri;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -95,7 +94,7 @@ public class RestPutOperationTest extends JerseyTest {
      */
     @Test
     public void putConfigStatusCodes() throws UnsupportedEncodingException {
-        String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0");
+        String uri = "/config/ietf-interfaces:interfaces/interface/eth0";
         mockCommitConfigurationDataPutMethod(TransactionStatus.COMMITED);
         assertEquals(200, put(uri, MediaType.APPLICATION_XML, xmlData));
 
@@ -121,10 +120,10 @@ public class RestPutOperationTest extends JerseyTest {
 
         ControllerContext.getInstance().setMountService(mockMountService);
 
-        String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/0/yang-ext:mount/test-module:cont");
+        String uri = "/config/ietf-interfaces:interfaces/interface/0/yang-ext:mount/test-module:cont";
         assertEquals(200, put(uri, MediaType.APPLICATION_XML, xmlData2));
 
-        uri = createUri("/config/", "ietf-interfaces:interfaces/yang-ext:mount/test-module:cont");
+        uri = "/config/ietf-interfaces:interfaces/yang-ext:mount/test-module:cont";
         assertEquals(200, put(uri, MediaType.APPLICATION_XML, xmlData2));
     }
 
@@ -144,7 +143,7 @@ public class RestPutOperationTest extends JerseyTest {
 
         ControllerContext.getInstance().setMountService(mockMountService);
 
-        String uri = createUri("/config/", "ietf-interfaces:interfaces/yang-ext:mount");
+        String uri = "/config/ietf-interfaces:interfaces/yang-ext:mount";
         assertEquals(200, put(uri, MediaType.APPLICATION_XML, xmlData3));
     }
 
index 4dcc63e89aa76d27bc58cfdeebce4243f7bbaa23..d9ef2ef243986bb63960f8212f4ab2bbf81346f6 100644 (file)
@@ -11,7 +11,6 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
-import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.createUri;
 
 import java.io.FileNotFoundException;
 import java.io.UnsupportedEncodingException;
@@ -69,13 +68,13 @@ public class RestStream extends JerseyTest {
 
     @Test
     public void testCallRpcCallGet() throws UnsupportedEncodingException, InterruptedException {
-        String uri = createUri("/operations/", "sal-remote:create-data-change-event-subscription");
+        String uri = "/operations/sal-remote:create-data-change-event-subscription";
         Response responseWithStreamName = post(uri, MediaType.APPLICATION_XML, getRpcInput());
         String xmlResponse = responseWithStreamName.readEntity(String.class);
         assertNotNull(xmlResponse);
         assertTrue(xmlResponse.contains("<stream-name>ietf-interfaces:interfaces/ietf-interfaces:interface/eth0</stream-name>"));
 
-        uri = createUri("/streams/stream/", "ietf-interfaces:interfaces/ietf-interfaces:interface/eth0");
+        uri = "/streams/stream/ietf-interfaces:interfaces/ietf-interfaces:interface/eth0";
         Response responseWithRedirectionUri = get(uri, MediaType.APPLICATION_XML);
         final URI websocketServerUri = responseWithRedirectionUri.getLocation();
         assertNotNull(websocketServerUri);
index 8159707d57dd4e7cf3010f1aa6678af62cc52a4c..2fe625ffb3fc2596eb8e14e111e4aa7ab8cfafbe 100644 (file)
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>restconf-client-api</artifactId>
-            <version>${yangtools.version}</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>restconf-client-impl</artifactId>
-            <version>${yangtools.version}</version>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
index 5fad76ff0831e089216337321ffaf57ed1d62989..9dfd262da2a99c55f899ea9b615ed9e911f5fa89 100644 (file)
@@ -7,24 +7,79 @@
  */
 package org.opendaylight.controller.sal.restconf.broker.event;
 
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+
+import javax.annotation.concurrent.ThreadSafe;
+
 import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.remote.rev140114.DataChangedNotification;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
+@ThreadSafe
 public class RemoteDataChangeEvent implements DataChangeEvent<InstanceIdentifier<? extends DataObject>,DataObject> {
-
-
-    private final DataChangedNotification dataChangedNotification;
-
-
-    public RemoteDataChangeEvent(DataChangedNotification dataChangedNotification){
-
-        this.dataChangedNotification = dataChangedNotification;
+    private final Map<InstanceIdentifier<?>, DataObject> createdConfig, createdOper, origConfig, origOper, updatedConfig, updatedOper;
+    private final Set<InstanceIdentifier<?>> removedConfig, removedOper;
+
+    public RemoteDataChangeEvent(DataChangedNotification dataChangedNotification) {
+        final Map<InstanceIdentifier<?>, DataObject> createdConfig = new HashMap<>();
+        final Map<InstanceIdentifier<?>, DataObject> createdOper = new HashMap<>();
+        final Map<InstanceIdentifier<?>, DataObject> origConfig = new HashMap<>();
+        final Map<InstanceIdentifier<?>, DataObject> origOper = new HashMap<>();
+        final Map<InstanceIdentifier<?>, DataObject> updatedConfig = new HashMap<>();
+        final Map<InstanceIdentifier<?>, DataObject> updatedOper = new HashMap<>();
+        final Set<InstanceIdentifier<?>> removedConfig = new HashSet<>();
+        final Set<InstanceIdentifier<?>> removedOper = new HashSet<>();
+
+        for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.remote.rev140114.data.changed.notification.DataChangeEvent d :dataChangedNotification.getDataChangeEvent()) {
+            switch (d.getOperation()) {
+            case Created:
+                switch (d.getStore()) {
+                case Config:
+                    createdConfig.put(d.getPath(), d);
+                    break;
+                case Operation:
+                    createdOper.put(d.getPath(), d);
+                    break;
+                }
+                break;
+            case Deleted:
+                switch (d.getStore()) {
+                case Config:
+                    removedConfig.add(d.getPath());
+                    break;
+                case Operation:
+                    removedOper.add(d.getPath());
+                    break;
+                }
+                break;
+            case Updated:
+                switch (d.getStore()) {
+                case Config:
+                    origConfig.put(d.getPath(), d);
+                    updatedConfig.put(d.getPath(), d);
+                    break;
+                case Operation:
+                    origOper.put(d.getPath(),d);
+                    updatedOper.put(d.getPath(),d);
+                    break;
+                }
+                break;
+            }
+        }
+
+        this.createdConfig = Collections.unmodifiableMap(createdConfig);
+        this.createdOper = Collections.unmodifiableMap(createdOper);
+        this.origConfig = Collections.unmodifiableMap(origConfig);
+        this.origOper = Collections.unmodifiableMap(origOper);
+        this.updatedConfig = Collections.unmodifiableMap(updatedConfig);
+        this.updatedOper = Collections.unmodifiableMap(updatedOper);
+        this.removedConfig = Collections.unmodifiableSet(removedConfig);
+        this.removedOper = Collections.unmodifiableSet(removedOper);
     }
 
     @Override
@@ -49,89 +104,41 @@ public class RemoteDataChangeEvent implements DataChangeEvent<InstanceIdentifier
 
     @Override
     public Map<InstanceIdentifier<?>, DataObject> getCreatedOperationalData() {
-        return new HashMap<InstanceIdentifier<?>, DataObject>(){{
-            for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.remote.rev140114.data.changed.notification.DataChangeEvent d :dataChangedNotification.getDataChangeEvent()){
-                if (d.getOperation().getIntValue() == 0 && d.getStore().getIntValue() == 1){
-                    put(d.getPath(),d);
-                }
-            }
-        }};
+        return createdOper;
     }
 
     @Override
     public Map<InstanceIdentifier<?>, DataObject> getCreatedConfigurationData() {
-        return new HashMap<InstanceIdentifier<?>, DataObject>(){{
-            for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.remote.rev140114.data.changed.notification.DataChangeEvent d :dataChangedNotification.getDataChangeEvent()){
-                if (d.getOperation().getIntValue() == 0 && d.getStore().getIntValue() == 0){
-                    put(d.getPath(),d);
-                }
-            }
-        }};
+        return createdConfig;
     }
 
     @Override
     public Map<InstanceIdentifier<?>, DataObject> getUpdatedOperationalData() {
-        return new HashMap<InstanceIdentifier<?>, DataObject>(){{
-            for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.remote.rev140114.data.changed.notification.DataChangeEvent d :dataChangedNotification.getDataChangeEvent()){
-                if (d.getOperation().getIntValue() == 1 && d.getStore().getIntValue() == 1){
-                    put(d.getPath(),d);
-                }
-            }
-        }};
+        return updatedOper;
     }
 
     @Override
     public Map<InstanceIdentifier<?>, DataObject> getUpdatedConfigurationData() {
-        return new HashMap<InstanceIdentifier<?>, DataObject>(){{
-            for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.remote.rev140114.data.changed.notification.DataChangeEvent d :dataChangedNotification.getDataChangeEvent()){
-                if (d.getOperation().getIntValue() == 1 && d.getStore().getIntValue() == 0){
-                    put(d.getPath(),d);
-                }
-            }
-        }};
+        return updatedConfig;
     }
 
     @Override
     public Set<InstanceIdentifier<?>> getRemovedConfigurationData() {
-        return new HashSet<InstanceIdentifier<?>>(){{
-            for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.remote.rev140114.data.changed.notification.DataChangeEvent d :dataChangedNotification.getDataChangeEvent()){
-                if (d.getOperation().getIntValue() == 2 && d.getStore().getIntValue() == 0){
-                    add(d.getPath());
-                }
-            }
-        }};
+        return removedConfig;
     }
 
     @Override
     public Set<InstanceIdentifier<?>> getRemovedOperationalData() {
-        return new HashSet<InstanceIdentifier<?>>(){{
-            for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.remote.rev140114.data.changed.notification.DataChangeEvent d :dataChangedNotification.getDataChangeEvent()){
-                if (d.getOperation().getIntValue() == 2 && d.getStore().getIntValue() == 1){
-                    add(d.getPath());
-                }
-            }
-        }};
+        return removedOper;
     }
 
     @Override
     public Map<InstanceIdentifier<?>, DataObject> getOriginalConfigurationData() {
-        return new HashMap<InstanceIdentifier<?>, DataObject>(){{
-            for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.remote.rev140114.data.changed.notification.DataChangeEvent d :dataChangedNotification.getDataChangeEvent()){
-                if (d.getOperation().getIntValue() == 1 && d.getStore().getIntValue() == 0){
-                    put(d.getPath(),d);
-                }
-            }
-        }};
+        return origConfig;
     }
 
     @Override
     public Map<InstanceIdentifier<?>, DataObject> getOriginalOperationalData() {
-        return new HashMap<InstanceIdentifier<?>, DataObject>(){{
-            for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.remote.rev140114.data.changed.notification.DataChangeEvent d :dataChangedNotification.getDataChangeEvent()){
-                if (d.getOperation().getIntValue() == 1 && d.getStore().getIntValue() == 1){
-                    put(d.getPath(),d);
-                }
-            }
-        }};
+        return origOper;
     }
 }
index a0162395f57c6a88f529ab407d2ebe8578e194e3..3272ce56707eff0159efbab3d3106f281e188f1a 100644 (file)
@@ -7,14 +7,11 @@
  */
 package org.opendaylight.controller.sal.restconf.broker.impl;
 
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Multimaps;
-import com.google.common.collect.SetMultimap;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ExecutorService;
+
 import org.opendaylight.controller.sal.binding.api.NotificationListener;
 import org.opendaylight.controller.sal.binding.api.NotificationService;
 import org.opendaylight.controller.sal.restconf.broker.listeners.RemoteNotificationListener;
@@ -27,9 +24,14 @@ import org.opendaylight.yangtools.restconf.client.api.RestconfClientContext;
 import org.opendaylight.yangtools.restconf.client.api.event.EventStreamInfo;
 import org.opendaylight.yangtools.yang.binding.Notification;
 
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.SetMultimap;
+
 public class NotificationServiceImpl implements NotificationService {
-    private SalRemoteService salRemoteService;
-    private RestconfClientContext restconfClientContext;
+    private final SalRemoteService salRemoteService;
+    private final RestconfClientContext restconfClientContext;
 
     private final Multimap<Class<? extends Notification>,NotificationListener<? extends Object>> listeners;
     private ExecutorService _executor;
@@ -82,9 +84,8 @@ public class NotificationServiceImpl implements NotificationService {
         String notificationStreamName = RemoteStreamTools.createNotificationStream(salRemoteService, notifications);
         final Map<String,EventStreamInfo> desiredEventStream = RemoteStreamTools.createEventStream(restconfClientContext, notificationStreamName);
         RemoteNotificationListener remoteNotificationListener = new RemoteNotificationListener(listener);
-        ListenerRegistration listenerRegistration = restconfClientContext.getEventStreamContext(desiredEventStream.get(desiredEventStream.get(notificationStreamName))).registerNotificationListener(remoteNotificationListener);
-        SalNotificationRegistration salNotificationRegistration = new SalNotificationRegistration(listenerRegistration);
-        return salNotificationRegistration;
+        ListenerRegistration<?> listenerRegistration = restconfClientContext.getEventStreamContext(desiredEventStream.get(desiredEventStream.get(notificationStreamName))).registerNotificationListener(remoteNotificationListener);
+        return new SalNotificationRegistration<T>(listenerRegistration);
     }
 
     @Override
@@ -92,14 +93,13 @@ public class NotificationServiceImpl implements NotificationService {
         //TODO implementation using sal-remote
         String notificationStreamName = RemoteStreamTools.createNotificationStream(salRemoteService, null);
         final Map<String,EventStreamInfo> desiredEventStream = RemoteStreamTools.createEventStream(restconfClientContext, notificationStreamName);
-        ListenerRegistration listenerRegistration = restconfClientContext.getEventStreamContext(desiredEventStream.get(desiredEventStream.get(notificationStreamName))).registerNotificationListener(listener);
-        return listenerRegistration;
+        return restconfClientContext.getEventStreamContext(desiredEventStream.get(desiredEventStream.get(notificationStreamName))).registerNotificationListener(listener);
     }
 
     private class SalNotificationRegistration<T extends Notification> implements Registration<NotificationListener<T>>{
-        private Registration registration;
+        private final Registration<?> registration;
 
-        public SalNotificationRegistration(ListenerRegistration listenerRegistration){
+        public SalNotificationRegistration(ListenerRegistration<?> listenerRegistration){
             this.registration = listenerRegistration;
         }
 
index ff09c1dbf05e84eae907cf06fbf73530b8e7db8a..40e99ec28b74920996b962d99964ee9e8bff98dd 100644 (file)
@@ -39,7 +39,6 @@
                <dependency>
                        <groupId>org.opendaylight.controller</groupId>
                        <artifactId>sal-binding-api</artifactId>
-                       <version>1.1-SNAPSHOT</version>
                </dependency>
        </dependencies>
 </project>
index 3f9ac737a27c7b4f755864bd1515f1841fd8a671..ca1e3b468941af54cd4fd0b9e6e68b5c45e9ed52 100644 (file)
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-api</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common-util</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
     </dependencies>
 </project>
index 5c3fc2329af03cf5b44f079ec211a2cdff06ca26..a9c1e054136d49f98f885b2b07575f2a33303aac 100644 (file)
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-api</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
             <artifactId>model-flow-statistics</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
             <artifactId>model-flow-base</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.eclipse.xtend</groupId>
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/AbstractListeningStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/AbstractListeningStatsTracker.java
new file mode 100644 (file)
index 0000000..4a58579
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.statistics.manager;
+
+import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+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;
+
+abstract class AbstractListeningStatsTracker<I, K> extends AbstractStatsTracker<I, K> implements AutoCloseable, DataChangeListener {
+    private static final Logger logger = LoggerFactory.getLogger(AbstractListeningStatsTracker.class);
+    private ListenerRegistration<?> reg;
+
+    protected AbstractListeningStatsTracker(FlowCapableContext context, long lifetimeNanos) {
+        super(context, lifetimeNanos);
+    }
+
+    protected abstract InstanceIdentifier<?> listenPath();
+    protected abstract String statName();
+
+    public void start(final DataBrokerService dbs) {
+        Preconditions.checkState(reg == null);
+
+        reg = dbs.registerDataChangeListener(listenPath(), this);
+        logger.debug("{} Statistics tracker for node {} started", statName(), getNodeIdentifier());
+    }
+
+    @Override
+    public final void close() {
+        if (reg != null) {
+            try {
+                reg.close();
+            } catch (Exception e) {
+                logger.warn("Failed to stop {} Statistics tracker for node {}", statName(), getNodeIdentifier(), e);
+            }
+            reg = null;
+        }
+    }
+}
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/AbstractStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/AbstractStatsTracker.java
new file mode 100644 (file)
index 0000000..c29b6a7
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright IBM Corporation, 2013.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.statistics.manager;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+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.JdkFutureAdapters;
+
+abstract class AbstractStatsTracker<I, K> {
+    private static final Logger logger = LoggerFactory.getLogger(AbstractStatsTracker.class);
+    private final FutureCallback<RpcResult<? extends TransactionAware>> callback =
+            new FutureCallback<RpcResult<? extends TransactionAware>>() {
+        @Override
+        public void onSuccess(RpcResult<? extends TransactionAware> result) {
+            if (result.isSuccessful()) {
+                final TransactionId id = result.getResult().getTransactionId();
+                if (id == null) {
+                    final Throwable t = new UnsupportedOperationException("No protocol support");
+                    t.fillInStackTrace();
+                    onFailure(t);
+                } else {
+                    context.registerTransaction(id);
+                }
+            } else {
+                logger.debug("Statistics request failed: {}", result.getErrors());
+
+                final Throwable t = new RPCFailedException("Failed to send statistics request", result.getErrors());
+                t.fillInStackTrace();
+                onFailure(t);
+            }
+        }
+
+        @Override
+        public void onFailure(Throwable t) {
+            logger.debug("Failed to send statistics request", t);
+        }
+    };
+
+    private final Map<K, Long> trackedItems = new HashMap<>();
+    private final FlowCapableContext context;
+    private final long lifetimeNanos;
+
+    protected AbstractStatsTracker(final FlowCapableContext context, final long lifetimeNanos) {
+        this.context = Preconditions.checkNotNull(context);
+        this.lifetimeNanos = lifetimeNanos;
+    }
+
+    protected final InstanceIdentifierBuilder<Node> getNodeIdentifierBuilder() {
+        return InstanceIdentifier.builder(getNodeIdentifier());
+    }
+
+    protected final NodeRef getNodeRef() {
+        return context.getNodeRef();
+    }
+
+    protected final InstanceIdentifier<Node> getNodeIdentifier() {
+        return context.getNodeIdentifier();
+    }
+
+    protected final <T extends TransactionAware> void requestHelper(Future<RpcResult<T>> future) {
+        Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), callback);
+    }
+
+    protected final DataModificationTransaction startTransaction() {
+        return context.startDataModification();
+    }
+
+    protected abstract void cleanupSingleStat(DataModificationTransaction trans, K item);
+    protected abstract K updateSingleStat(DataModificationTransaction trans, I item);
+
+    public final synchronized void updateStats(List<I> list) {
+        final Long expiryTime = System.nanoTime() + lifetimeNanos;
+        final DataModificationTransaction trans = startTransaction();
+
+        for (final I item : list) {
+            trackedItems.put(updateSingleStat(trans, item), expiryTime);
+        }
+
+        trans.commit();
+    }
+
+    public final synchronized void cleanup(final DataModificationTransaction trans, long now) {
+        for (Iterator<Entry<K, Long>> it = trackedItems.entrySet().iterator();it.hasNext();){
+            Entry<K, Long> e = it.next();
+            if (now > e.getValue()) {
+                cleanupSingleStat(trans, e.getKey());
+                it.remove();
+            }
+        }
+    }
+}
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowCapableContext.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowCapableContext.java
new file mode 100644 (file)
index 0000000..520b344
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.statistics.manager;
+
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Interface exposed to AbstractStatsTracker by its parent NodeStatisticsHandler.
+ * While we could simply exist without this interface, its purpose is to document
+ * the contract between the two classes.
+ */
+interface FlowCapableContext {
+    InstanceIdentifier<Node> getNodeIdentifier();
+    NodeRef getNodeRef();
+    DataModificationTransaction startDataModification();
+    void registerTransaction(TransactionId id);
+    void registerTableTransaction(TransactionId id, Short tableId);
+}
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowCapableTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowCapableTracker.java
new file mode 100644 (file)
index 0000000..bb1544c
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright IBM Corporation, 2013.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.statistics.manager;
+
+import java.util.Collection;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Sets;
+
+/**
+ * There is a single instance of this class and that instance is responsible for
+ * monitoring the operational data store for nodes being created/deleted and
+ * notifying StatisticsProvider. These events then control the lifecycle of
+ * NodeStatisticsHandler for a particular switch.
+ */
+final class FlowCapableTracker implements DataChangeListener {
+    private static final Logger logger = LoggerFactory.getLogger(FlowCapableTracker.class);
+
+    private final InstanceIdentifier<FlowCapableNode> root;
+    private final StatisticsProvider stats;
+
+    private final Predicate<InstanceIdentifier<?>> filterIdentifiers = new Predicate<InstanceIdentifier<?>>() {
+        @Override
+        public boolean apply(final InstanceIdentifier<?> input) {
+            /*
+             * This notification has been triggered either by the ancestor,
+             * descendant or directly for the FlowCapableNode itself. We
+             * are not interested descendants, so let's prune them based
+             * on the depth of their identifier.
+             */
+            if (root.getPath().size() < input.getPath().size()) {
+                logger.debug("Ignoring notification for descendant {}", input);
+                return false;
+            }
+
+            logger.debug("Including notification for {}", input);
+            return true;
+        }
+    };
+
+    public FlowCapableTracker(final StatisticsProvider stats, InstanceIdentifier<FlowCapableNode> root) {
+        this.stats = Preconditions.checkNotNull(stats);
+        this.root = Preconditions.checkNotNull(root);
+    }
+
+    /*
+     * This method is synchronized because we want to make sure to serialize input
+     * from the datastore. Competing add/remove could be problematic otherwise.
+     */
+    @Override
+    public synchronized void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        logger.debug("Tracker at root {} processing notification", root);
+
+        /*
+         * First process all the identifiers which were removed, trying to figure out
+         * whether they constitute removal of FlowCapableNode.
+         */
+        final Collection<NodeKey> removedNodes =
+            Collections2.filter(Collections2.transform(
+                Sets.filter(change.getRemovedOperationalData(), filterIdentifiers),
+                new Function<InstanceIdentifier<?>, NodeKey>() {
+                    @Override
+                    public NodeKey apply(final InstanceIdentifier<?> input) {
+                        final NodeKey key = input.firstKeyOf(Node.class, NodeKey.class);
+                        if (key == null) {
+                            // FIXME: do we have a backup plan?
+                            logger.info("Failed to extract node key from {}", input);
+                        }
+                        return key;
+                    }
+                }), Predicates.notNull());
+        stats.stopNodeHandlers(removedNodes);
+
+        final Collection<NodeKey> addedNodes =
+            Collections2.filter(Collections2.transform(
+                Sets.filter(change.getCreatedOperationalData().keySet(), filterIdentifiers),
+                new Function<InstanceIdentifier<?>, NodeKey>() {
+                    @Override
+                    public NodeKey apply(final InstanceIdentifier<?> input) {
+                        final NodeKey key = input.firstKeyOf(Node.class, NodeKey.class);
+                        if (key == null) {
+                            // FIXME: do we have a backup plan?
+                            logger.info("Failed to extract node key from {}", input);
+                    }
+                    return key;
+                }
+            }), Predicates.notNull());
+        stats.startNodeHandlers(addedNodes);
+
+        logger.debug("Tracker at root {} finished processing notification", root);
+    }
+}
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowStatsEntry.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowStatsEntry.java
new file mode 100644 (file)
index 0000000..b5b39d9
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright IBM Corporation, 2013.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.statistics.manager;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+
+final class FlowStatsEntry {
+    private final Short tableId;
+    private final Flow flow;
+
+    public FlowStatsEntry(Short tableId, Flow flow){
+        this.tableId = tableId;
+        this.flow = flow;
+    }
+
+    public Short getTableId() {
+        return tableId;
+    }
+
+    public Flow getFlow() {
+        return flow;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((flow == null) ? 0 : flow.hashCode());
+        result = prime * result + ((tableId == null) ? 0 : tableId.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        FlowStatsEntry other = (FlowStatsEntry) obj;
+        if (flow == null) {
+            if (other.flow != null)
+                return false;
+        } else if (!flow.equals(other.flow))
+            return false;
+        if (tableId == null) {
+            if (other.tableId != null)
+                return false;
+        } else if (!tableId.equals(other.tableId))
+            return false;
+        return true;
+    }
+}
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowStatsTracker.java
new file mode 100644 (file)
index 0000000..90ddc28
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright IBM Corporation, 2013.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.statistics.manager;
+
+import 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.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService;
+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.model.statistics.types.rev130925.GenericStatistics;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class FlowStatsTracker extends AbstractListeningStatsTracker<FlowAndStatisticsMapList, FlowStatsEntry> {
+    private static final Logger logger = LoggerFactory.getLogger(FlowStatsTracker.class);
+    private final OpendaylightFlowStatisticsService flowStatsService;
+    private int unaccountedFlowsCounter = 1;
+
+    FlowStatsTracker(OpendaylightFlowStatisticsService flowStatsService, final FlowCapableContext context, long lifetimeNanos) {
+        super(context, lifetimeNanos);
+        this.flowStatsService = flowStatsService;
+    }
+
+    @Override
+    protected void cleanupSingleStat(DataModificationTransaction trans, FlowStatsEntry item) {
+        InstanceIdentifier<?> flowRef = getNodeIdentifierBuilder()
+                            .augmentation(FlowCapableNode.class)
+                            .child(Table.class, new TableKey(item.getTableId()))
+                            .child(Flow.class,item.getFlow().getKey())
+                            .augmentation(FlowStatisticsData.class).toInstance();
+        trans.removeOperationalData(flowRef);
+    }
+
+    @Override
+    protected FlowStatsEntry updateSingleStat(DataModificationTransaction trans, FlowAndStatisticsMapList map) {
+        short tableId = map.getTableId();
+
+        FlowBuilder flowBuilder = new FlowBuilder();
+
+        FlowStatisticsDataBuilder flowStatisticsData = new FlowStatisticsDataBuilder();
+
+        FlowBuilder flow = new FlowBuilder();
+        flow.setContainerName(map.getContainerName());
+        flow.setBufferId(map.getBufferId());
+        flow.setCookie(map.getCookie());
+        flow.setCookieMask(map.getCookieMask());
+        flow.setFlags(map.getFlags());
+        flow.setFlowName(map.getFlowName());
+        flow.setHardTimeout(map.getHardTimeout());
+        if(map.getFlowId() != null)
+            flow.setId(new FlowId(map.getFlowId().getValue()));
+        flow.setIdleTimeout(map.getIdleTimeout());
+        flow.setInstallHw(map.isInstallHw());
+        flow.setInstructions(map.getInstructions());
+        if(map.getFlowId()!= null)
+            flow.setKey(new FlowKey(new FlowId(map.getKey().getFlowId().getValue())));
+        flow.setMatch(map.getMatch());
+        flow.setOutGroup(map.getOutGroup());
+        flow.setOutPort(map.getOutPort());
+        flow.setPriority(map.getPriority());
+        flow.setStrict(map.isStrict());
+        flow.setTableId(tableId);
+
+        Flow flowRule = flow.build();
+
+        FlowAndStatisticsMapListBuilder stats = new FlowAndStatisticsMapListBuilder();
+        stats.setByteCount(map.getByteCount());
+        stats.setPacketCount(map.getPacketCount());
+        stats.setDuration(map.getDuration());
+
+        GenericStatistics flowStats = stats.build();
+
+        //Augment the data to the flow node
+
+        FlowStatisticsBuilder flowStatistics = new FlowStatisticsBuilder();
+        flowStatistics.setByteCount(flowStats.getByteCount());
+        flowStatistics.setPacketCount(flowStats.getPacketCount());
+        flowStatistics.setDuration(flowStats.getDuration());
+        flowStatistics.setContainerName(map.getContainerName());
+        flowStatistics.setBufferId(map.getBufferId());
+        flowStatistics.setCookie(map.getCookie());
+        flowStatistics.setCookieMask(map.getCookieMask());
+        flowStatistics.setFlags(map.getFlags());
+        flowStatistics.setFlowName(map.getFlowName());
+        flowStatistics.setHardTimeout(map.getHardTimeout());
+        flowStatistics.setIdleTimeout(map.getIdleTimeout());
+        flowStatistics.setInstallHw(map.isInstallHw());
+        flowStatistics.setInstructions(map.getInstructions());
+        flowStatistics.setMatch(map.getMatch());
+        flowStatistics.setOutGroup(map.getOutGroup());
+        flowStatistics.setOutPort(map.getOutPort());
+        flowStatistics.setPriority(map.getPriority());
+        flowStatistics.setStrict(map.isStrict());
+        flowStatistics.setTableId(tableId);
+
+        flowStatisticsData.setFlowStatistics(flowStatistics.build());
+
+        logger.debug("Flow : {}",flowRule.toString());
+        logger.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();
+                    flowBuilder.setKey(existingFlow.getKey());
+                    flowBuilder.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
+                    logger.debug("Found matching flow in the datastore, augmenting statistics");
+                    // Update entry with timestamp of latest response
+                    flow.setKey(existingFlow.getKey());
+                    FlowStatsEntry flowStatsEntry = new FlowStatsEntry(tableId,flow.build());
+                    trans.putOperationalData(flowRef, flowBuilder.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();
+                        flowBuilder.setKey(existingFlow.getKey());
+                        flowBuilder.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
+                        logger.debug("Found matching unaccounted flow in the operational datastore, augmenting statistics");
+                        // Update entry with timestamp of latest response
+                        flow.setKey(existingFlow.getKey());
+                        FlowStatsEntry flowStatsEntry = new FlowStatsEntry(tableId,flow.build());
+                        trans.putOperationalData(flowRef, flowBuilder.build());
+                        return flowStatsEntry;
+                    }
+                }
+            }
+        }
+
+        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();
+        flowBuilder.setKey(newFlowKey);
+        flowBuilder.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
+        logger.debug("Flow {} is not present in config data store, augmenting statistics as an unaccounted flow",
+                    flowBuilder.build());
+
+        // Update entry with timestamp of latest response
+        flow.setKey(newFlowKey);
+        FlowStatsEntry flowStatsEntry = new FlowStatsEntry(tableId,flow.build());
+        trans.putOperationalData(flowRef, flowBuilder.build());
+        return flowStatsEntry;
+    }
+
+    @Override
+    protected InstanceIdentifier<?> listenPath() {
+        return getNodeIdentifierBuilder().augmentation(FlowCapableNode.class).child(Table.class).child(Flow.class).build();
+    }
+
+    @Override
+    protected String statName() {
+        return "Flow";
+    }
+
+    public void requestAllFlowsAllTables() {
+        if (flowStatsService != null) {
+            final GetAllFlowsStatisticsFromAllFlowTablesInputBuilder input = new GetAllFlowsStatisticsFromAllFlowTablesInputBuilder();
+            input.setNode(getNodeRef());
+
+            requestHelper(flowStatsService.getAllFlowsStatisticsFromAllFlowTables(input.build()));
+        }
+    }
+
+    public void requestAggregateFlows(final TableKey key) {
+        if (flowStatsService != null) {
+            GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder input =
+                    new GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder();
+
+            input.setNode(getNodeRef());
+            input.setTableId(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId(key.getId()));
+            requestHelper(flowStatsService.getAggregateFlowStatisticsFromFlowTableForAllFlows(input.build()));
+        }
+    }
+
+    public void requestFlow(final Flow flow) {
+        if (flowStatsService != null) {
+            final GetFlowStatisticsFromFlowTableInputBuilder input =
+                    new GetFlowStatisticsFromFlowTableInputBuilder(flow);
+            input.setNode(getNodeRef());
+
+            requestHelper(flowStatsService.getFlowStatisticsFromFlowTable(input.build()));
+        }
+    }
+
+    @Override
+    public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        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);
+                requestFlow(flow);
+            } else {
+                logger.debug("Ignoring key {}", e.getKey());
+            }
+        }
+
+        final DataModificationTransaction trans = startTransaction();
+        for (InstanceIdentifier<?> key : change.getRemovedConfigurationData()) {
+            if (Flow.class.equals(key.getTargetType())) {
+                @SuppressWarnings("unchecked")
+                final InstanceIdentifier<Flow> flow = (InstanceIdentifier<Flow>)key;
+                final InstanceIdentifier<?> del = InstanceIdentifier.builder(flow)
+                        .augmentation(FlowStatisticsData.class).build();
+                logger.debug("Key {} triggered remove of augmentation {}", key, del);
+
+                trans.removeOperationalData(del);
+            }
+        }
+        trans.commit();
+    }
+
+    @Override
+    public void start(final DataBrokerService dbs) {
+        if (flowStatsService == null) {
+            logger.debug("No Flow Statistics service, not subscribing to flows on node {}", getNodeIdentifier());
+            return;
+        }
+
+        super.start(dbs);
+    }
+}
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowTableStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowTableStatsTracker.java
new file mode 100644 (file)
index 0000000..3fe68c1
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright IBM Corporation, 2013.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.statistics.manager;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+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.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatisticsBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+final class FlowTableStatsTracker extends AbstractStatsTracker<FlowTableAndStatisticsMap, FlowTableAndStatisticsMap> {
+    private final Set<TableKey> privateTables = new ConcurrentSkipListSet<>();
+    private final Set<TableKey> tables = Collections.unmodifiableSet(privateTables);
+    private final OpendaylightFlowTableStatisticsService flowTableStatsService;
+
+    FlowTableStatsTracker(OpendaylightFlowTableStatisticsService flowTableStatsService, final FlowCapableContext context, long lifetimeNanos) {
+        super(context, lifetimeNanos);
+        this.flowTableStatsService = flowTableStatsService;
+    }
+
+    Set<TableKey> getTables() {
+        return tables;
+    }
+
+    @Override
+    protected void cleanupSingleStat(DataModificationTransaction trans, FlowTableAndStatisticsMap item) {
+        // TODO: do we want to do this?
+    }
+
+    @Override
+    protected FlowTableAndStatisticsMap updateSingleStat(DataModificationTransaction trans, FlowTableAndStatisticsMap item) {
+
+        InstanceIdentifier<Table> tableRef = getNodeIdentifierBuilder()
+                .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(item.getTableId().getValue())).build();
+
+        FlowTableStatisticsDataBuilder statisticsDataBuilder = new FlowTableStatisticsDataBuilder();
+        final FlowTableStatistics stats = new FlowTableStatisticsBuilder(item).build();
+        statisticsDataBuilder.setFlowTableStatistics(stats);
+
+        TableBuilder tableBuilder = new TableBuilder();
+        tableBuilder.setKey(new TableKey(item.getTableId().getValue()));
+        tableBuilder.addAugmentation(FlowTableStatisticsData.class, statisticsDataBuilder.build());
+        trans.putOperationalData(tableRef, tableBuilder.build());
+        return item;
+    }
+
+    public void request() {
+        if (flowTableStatsService != null) {
+            final GetFlowTablesStatisticsInputBuilder input = new GetFlowTablesStatisticsInputBuilder();
+            input.setNode(getNodeRef());
+
+            requestHelper(flowTableStatsService.getFlowTablesStatistics(input.build()));
+        }
+    }
+}
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/GroupDescStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/GroupDescStatsTracker.java
new file mode 100644 (file)
index 0000000..8aebd6b
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright IBM Corporation, 2013.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.statistics.manager;
+
+import org.opendaylight.controller.md.sal.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.group.statistics.rev131111.GetGroupDescriptionInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupDescStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupDescStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.desc.GroupDescBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class GroupDescStatsTracker extends AbstractListeningStatsTracker<GroupDescStats, GroupDescStats> {
+    private static final Logger logger = LoggerFactory.getLogger(GroupDescStatsTracker.class);
+    private final OpendaylightGroupStatisticsService groupStatsService;
+
+    public GroupDescStatsTracker(OpendaylightGroupStatisticsService groupStatsService, final FlowCapableContext context, final long lifetimeNanos) {
+        super(context, lifetimeNanos);
+        this.groupStatsService = groupStatsService;
+    }
+
+    @Override
+    protected GroupDescStats updateSingleStat(DataModificationTransaction trans, GroupDescStats item) {
+        GroupBuilder groupBuilder = new GroupBuilder();
+        GroupKey groupKey = new GroupKey(item.getGroupId());
+        groupBuilder.setKey(groupKey);
+
+        InstanceIdentifier<Group> groupRef = getNodeIdentifierBuilder()
+                .augmentation(FlowCapableNode.class).child(Group.class,groupKey).build();
+
+        NodeGroupDescStatsBuilder groupDesc= new NodeGroupDescStatsBuilder();
+        groupDesc.setGroupDesc(new GroupDescBuilder(item).build());
+
+        //Update augmented data
+        groupBuilder.addAugmentation(NodeGroupDescStats.class, groupDesc.build());
+
+        trans.putOperationalData(groupRef, groupBuilder.build());
+        return item;
+    }
+
+    @Override
+    protected void cleanupSingleStat(DataModificationTransaction trans, GroupDescStats item) {
+        InstanceIdentifier<NodeGroupDescStats> groupRef = getNodeIdentifierBuilder().augmentation(FlowCapableNode.class)
+                .child(Group.class, new GroupKey(item.getGroupId())).augmentation(NodeGroupDescStats.class).build();
+        trans.removeOperationalData(groupRef);
+    }
+
+    @Override
+    protected InstanceIdentifier<?> listenPath() {
+        return getNodeIdentifierBuilder().augmentation(FlowCapableNode.class).child(Group.class).build();
+    }
+
+    @Override
+    protected String statName() {
+        return "Group Descriptor";
+    }
+
+    public void request() {
+        if (groupStatsService != null) {
+            final GetGroupDescriptionInputBuilder input = new GetGroupDescriptionInputBuilder();
+            input.setNode(getNodeRef());
+
+            requestHelper(groupStatsService.getGroupDescription(input.build()));
+        }
+    }
+
+    @Override
+    public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        for (InstanceIdentifier<?> key : change.getCreatedConfigurationData().keySet()) {
+            if (Group.class.equals(key.getTargetType())) {
+                logger.debug("Key {} triggered request", key);
+                request();
+            } else {
+                logger.debug("Ignoring key {}", key);
+            }
+        }
+
+        final DataModificationTransaction trans = startTransaction();
+        for (InstanceIdentifier<?> key : change.getRemovedConfigurationData()) {
+            if (Group.class.equals(key.getTargetType())) {
+                @SuppressWarnings("unchecked")
+                InstanceIdentifier<Group> group = (InstanceIdentifier<Group>)key;
+                InstanceIdentifier<?> del = InstanceIdentifier.builder(group).augmentation(NodeGroupDescStats.class).toInstance();
+                logger.debug("Key {} triggered remove of augmentation {}", key, del);
+
+                trans.removeOperationalData(del);
+            }
+        }
+        trans.commit();
+    }
+
+    @Override
+    public void start(final DataBrokerService dbs) {
+        if (groupStatsService == null) {
+            logger.debug("No Group Statistics service, not subscribing to groups on node {}", getNodeIdentifier());
+            return;
+        }
+
+        super.start(dbs);
+    }
+}
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/GroupStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/GroupStatsTracker.java
new file mode 100644 (file)
index 0000000..1af8e4e
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright IBM Corporation, 2013.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.statistics.manager;
+
+import org.opendaylight.controller.md.sal.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.group.statistics.rev131111.GetAllGroupStatisticsInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+final class GroupStatsTracker extends AbstractListeningStatsTracker<GroupStats, GroupStats> {
+    private static final Logger logger = LoggerFactory.getLogger(GroupStatsTracker.class);
+    private final OpendaylightGroupStatisticsService groupStatsService;
+
+    GroupStatsTracker(OpendaylightGroupStatisticsService groupStatsService, FlowCapableContext context, long lifetimeNanos) {
+        super(context, lifetimeNanos);
+        this.groupStatsService = Preconditions.checkNotNull(groupStatsService);
+    }
+
+    @Override
+    protected void cleanupSingleStat(DataModificationTransaction trans, GroupStats item) {
+        InstanceIdentifier<NodeGroupStatistics> groupRef = getNodeIdentifierBuilder().augmentation(FlowCapableNode.class)
+                .child(Group.class, new GroupKey(item.getGroupId())).augmentation(NodeGroupStatistics.class).build();
+        trans.removeOperationalData(groupRef);
+    }
+
+    @Override
+    protected GroupStats updateSingleStat(DataModificationTransaction trans,
+            GroupStats item) {
+        GroupBuilder groupBuilder = new GroupBuilder();
+        GroupKey groupKey = new GroupKey(item.getGroupId());
+        groupBuilder.setKey(groupKey);
+
+        InstanceIdentifier<Group> groupRef = getNodeIdentifierBuilder().augmentation(FlowCapableNode.class)
+                .child(Group.class,groupKey).build();
+
+        NodeGroupStatisticsBuilder groupStatisticsBuilder= new NodeGroupStatisticsBuilder();
+        groupStatisticsBuilder.setGroupStatistics(new GroupStatisticsBuilder(item).build());
+
+        //Update augmented data
+        groupBuilder.addAugmentation(NodeGroupStatistics.class, groupStatisticsBuilder.build());
+        trans.putOperationalData(groupRef, groupBuilder.build());
+        return item;
+    }
+
+    @Override
+    protected InstanceIdentifier<?> listenPath() {
+        return getNodeIdentifierBuilder().augmentation(FlowCapableNode.class).child(Group.class).build();
+    }
+
+    @Override
+    protected String statName() {
+        return "Group";
+    }
+
+    public void request() {
+        final GetAllGroupStatisticsInputBuilder input = new GetAllGroupStatisticsInputBuilder();
+        input.setNode(getNodeRef());
+
+        requestHelper(groupStatsService.getAllGroupStatistics(input.build()));
+    }
+
+    @Override
+    public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        final DataModificationTransaction trans = startTransaction();
+        for (InstanceIdentifier<?> key : change.getRemovedConfigurationData()) {
+            if (Group.class.equals(key.getTargetType())) {
+                @SuppressWarnings("unchecked")
+                InstanceIdentifier<Group> group = (InstanceIdentifier<Group>)key;
+                InstanceIdentifier<?> del = InstanceIdentifier.builder(group).augmentation(NodeGroupStatistics.class).toInstance();
+                logger.debug("Key {} triggered remove of augmentation {}", key, del);
+
+                trans.removeOperationalData(del);
+            }
+        }
+        trans.commit();
+    }
+
+    @Override
+    public void start(final DataBrokerService dbs) {
+        if (groupStatsService == null) {
+            logger.debug("No Group Statistics service, not subscribing to groups on node {}", getNodeIdentifier());
+            return;
+        }
+
+        super.start(dbs);
+    }
+}
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MeterConfigStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MeterConfigStatsTracker.java
new file mode 100644 (file)
index 0000000..4b95925
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright IBM Corporation, 2013.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.statistics.manager;
+
+import org.opendaylight.controller.md.sal.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.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterConfigStatisticsInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterConfigStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterConfigStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterConfigStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class MeterConfigStatsTracker extends AbstractListeningStatsTracker<MeterConfigStats, MeterConfigStats> {
+    private static final Logger logger = LoggerFactory.getLogger(MeterConfigStatsTracker.class);
+    private final OpendaylightMeterStatisticsService meterStatsService;
+
+    protected MeterConfigStatsTracker(OpendaylightMeterStatisticsService meterStatsService, final FlowCapableContext context, long lifetimeNanos) {
+        super(context, lifetimeNanos);
+        this.meterStatsService = meterStatsService;
+    }
+
+    @Override
+    protected void cleanupSingleStat(DataModificationTransaction trans, MeterConfigStats item) {
+        InstanceIdentifier<NodeMeterConfigStats> meterRef = getNodeIdentifierBuilder()
+                            .augmentation(FlowCapableNode.class)
+                            .child(Meter.class, new MeterKey(item.getMeterId()))
+                            .augmentation(NodeMeterConfigStats.class).build();
+        trans.removeOperationalData(meterRef);
+    }
+
+    @Override
+    protected MeterConfigStats updateSingleStat(DataModificationTransaction trans, MeterConfigStats item) {
+        MeterBuilder meterBuilder = new MeterBuilder();
+        MeterKey meterKey = new MeterKey(item.getMeterId());
+        meterBuilder.setKey(meterKey);
+
+        InstanceIdentifier<Meter> meterRef = getNodeIdentifierBuilder().augmentation(FlowCapableNode.class)
+                .child(Meter.class,meterKey).toInstance();
+
+        NodeMeterConfigStatsBuilder meterConfig = new NodeMeterConfigStatsBuilder();
+        meterConfig.setMeterConfigStats(new MeterConfigStatsBuilder(item).build());
+
+        //Update augmented data
+        meterBuilder.addAugmentation(NodeMeterConfigStats.class, meterConfig.build());
+
+        trans.putOperationalData(meterRef, meterBuilder.build());
+        return item;
+    }
+
+    public void request() {
+        if (meterStatsService != null) {
+            GetAllMeterConfigStatisticsInputBuilder input = new GetAllMeterConfigStatisticsInputBuilder();
+            input.setNode(getNodeRef());
+
+            requestHelper(meterStatsService.getAllMeterConfigStatistics(input.build()));
+        }
+    }
+
+    @Override
+    public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        final DataModificationTransaction trans = startTransaction();
+
+        for (InstanceIdentifier<?> key : change.getRemovedConfigurationData()) {
+            if (Meter.class.equals(key.getTargetType())) {
+                @SuppressWarnings("unchecked")
+                InstanceIdentifier<Meter> meter = (InstanceIdentifier<Meter>)key;
+
+                InstanceIdentifier<?> nodeMeterStatisticsAugmentation =
+                        InstanceIdentifier.builder(meter).augmentation(NodeMeterConfigStats.class).toInstance();
+                trans.removeOperationalData(nodeMeterStatisticsAugmentation);
+            }
+        }
+
+        trans.commit();
+    }
+
+    @Override
+    protected InstanceIdentifier<?> listenPath() {
+        return getNodeIdentifierBuilder().augmentation(FlowCapableNode.class).child(Meter.class).build();
+    }
+
+    @Override
+    protected String statName() {
+        return "Meter Config";
+    }
+
+    @Override
+    public void start(final DataBrokerService dbs) {
+        if (meterStatsService == null) {
+            logger.debug("No Meter Statistics service, not subscribing to meter on node {}", getNodeIdentifier());
+            return;
+        }
+
+        super.start(dbs);
+    }
+}
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MeterStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MeterStatsTracker.java
new file mode 100644 (file)
index 0000000..091cbcc
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright IBM Corporation, 2013.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.statistics.manager;
+
+import org.opendaylight.controller.md.sal.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.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterStatisticsInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class MeterStatsTracker extends AbstractListeningStatsTracker<MeterStats, MeterStats> {
+    private static final Logger logger = LoggerFactory.getLogger(MeterStatsTracker.class);
+    private final OpendaylightMeterStatisticsService meterStatsService;
+
+    MeterStatsTracker(OpendaylightMeterStatisticsService meterStatsService, final FlowCapableContext context, long lifetimeNanos) {
+        super(context, lifetimeNanos);
+        this.meterStatsService = meterStatsService;
+    }
+
+    @Override
+    protected void cleanupSingleStat(DataModificationTransaction trans, MeterStats item) {
+        InstanceIdentifier<NodeMeterStatistics> meterRef = getNodeIdentifierBuilder()
+                            .augmentation(FlowCapableNode.class)
+                            .child(Meter.class,new MeterKey(item.getMeterId()))
+                            .augmentation(NodeMeterStatistics.class).build();
+        trans.removeOperationalData(meterRef);
+    }
+
+    @Override
+    protected MeterStats updateSingleStat(DataModificationTransaction trans, MeterStats item) {
+        MeterBuilder meterBuilder = new MeterBuilder();
+        MeterKey meterKey = new MeterKey(item.getMeterId());
+        meterBuilder.setKey(meterKey);
+
+        InstanceIdentifier<Meter> meterRef = getNodeIdentifierBuilder()
+                .augmentation(FlowCapableNode.class).child(Meter.class,meterKey).build();
+
+        NodeMeterStatisticsBuilder meterStatsBuilder= new NodeMeterStatisticsBuilder();
+        meterStatsBuilder.setMeterStatistics(new MeterStatisticsBuilder(item).build());
+
+        //Update augmented data
+        meterBuilder.addAugmentation(NodeMeterStatistics.class, meterStatsBuilder.build());
+        trans.putOperationalData(meterRef, meterBuilder.build());
+        return item;
+    }
+
+    public void request() {
+        if (meterStatsService != null) {
+            GetAllMeterStatisticsInputBuilder input = new GetAllMeterStatisticsInputBuilder();
+            input.setNode(getNodeRef());
+
+            requestHelper(meterStatsService.getAllMeterStatistics(input.build()));
+        }
+    }
+
+    @Override
+    public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        for (InstanceIdentifier<?> key : change.getCreatedConfigurationData().keySet()) {
+            if (Meter.class.equals(key.getTargetType())) {
+                request();
+            }
+        }
+
+        final DataModificationTransaction trans = startTransaction();
+        for (InstanceIdentifier<?> key : change.getRemovedConfigurationData()) {
+            if (Meter.class.equals(key.getTargetType())) {
+                @SuppressWarnings("unchecked")
+                InstanceIdentifier<Meter> meter = (InstanceIdentifier<Meter>)key;
+
+                InstanceIdentifier<?> nodeMeterStatisticsAugmentation =
+                        InstanceIdentifier.builder(meter).augmentation(NodeMeterStatistics.class).toInstance();
+                trans.removeOperationalData(nodeMeterStatisticsAugmentation);
+            }
+        }
+        trans.commit();
+    }
+
+    @Override
+    protected InstanceIdentifier<?> listenPath() {
+        return getNodeIdentifierBuilder().augmentation(FlowCapableNode.class).child(Meter.class).build();
+    }
+
+    @Override
+    protected String statName() {
+        return "Meter";
+    }
+
+    @Override
+    public void start(final DataBrokerService dbs) {
+        if (meterStatsService == null) {
+            logger.debug("No Meter Statistics service, not subscribing to meters on node {}", getNodeIdentifier());
+            return;
+        }
+
+        super.start(dbs);
+    }
+}
index 6f58708e1b207edf898f606448147119ec3e106b..56b205216f2b8768fe66606808ec83c7906859e8 100644 (file)
@@ -7,63 +7,53 @@
  */
 package org.opendaylight.controller.md.statistics.manager;
 
-import java.util.Date;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+
+import com.google.common.base.Preconditions;
 
 /**
- * Main responsibility of the class is to manage multipart response 
+ * Main responsibility of the class is to manage multipart response
  * for multipart request. It also handles the flow aggregate request
- * and response mapping. 
+ * and response mapping.
  * @author avishnoi@in.ibm.com
  *
  */
-public class MultipartMessageManager {
-
+class MultipartMessageManager {
     /*
-     *  Map for tx id and type of request, to keep track of all the request sent 
-     *  by Statistics Manager. Statistics Manager won't entertain any multipart 
-     *  response for which it didn't send the request.  
+     *  Map for tx id and type of request, to keep track of all the request sent
+     *  by Statistics Manager. Statistics Manager won't entertain any multipart
+     *  response for which it didn't send the request.
      */
-    
-    private static Map<TxIdEntry,Date> txIdToRequestTypeMap = new ConcurrentHashMap<TxIdEntry,Date>();
+    private final Map<TxIdEntry,Long> txIdToRequestTypeMap = new ConcurrentHashMap<>();
     /*
      * Map to keep track of the request tx id for flow table statistics request.
      * Because flow table statistics multi part response do not contains the table id.
      */
-    private static Map<TxIdEntry,Short> txIdTotableIdMap = new ConcurrentHashMap<TxIdEntry,Short>();
-    
-    private final int NUMBER_OF_WAIT_CYCLES =2;
+    private final Map<TxIdEntry,Short> txIdTotableIdMap = new ConcurrentHashMap<>();
+    private final long lifetimeNanos;
+
+    public MultipartMessageManager(long lifetimeNanos) {
+        this.lifetimeNanos = lifetimeNanos;
+    }
 
-    class TxIdEntry{
+    private static final class TxIdEntry {
         private final TransactionId txId;
-        private final NodeId nodeId;
-        private final StatsRequestType requestType;
-        
-        public TxIdEntry(NodeId nodeId, TransactionId txId, StatsRequestType requestType){
+
+        public TxIdEntry(TransactionId txId) {
             this.txId = txId;
-            this.nodeId = nodeId;
-            this.requestType = requestType;
         }
         public TransactionId getTxId() {
             return txId;
         }
-        public NodeId getNodeId() {
-            return nodeId;
-        }
-        public StatsRequestType getRequestType() {
-            return requestType;
-        }
         @Override
         public int hashCode() {
             final int prime = 31;
             int result = 1;
-            result = prime * result + getOuterType().hashCode();
-            result = prime * result + ((nodeId == null) ? 0 : nodeId.hashCode());
             result = prime * result + ((txId == null) ? 0 : txId.hashCode());
             return result;
         }
@@ -79,16 +69,7 @@ public class MultipartMessageManager {
                 return false;
             }
             TxIdEntry other = (TxIdEntry) obj;
-            if (!getOuterType().equals(other.getOuterType())) {
-                return false;
-            }
-            if (nodeId == null) {
-                if (other.nodeId != null) {
-                    return false;
-                }
-            } else if (!nodeId.equals(other.nodeId)) {
-                return false;
-            }
+
             if (txId == null) {
                 if (other.txId != null) {
                     return false;
@@ -98,75 +79,60 @@ public class MultipartMessageManager {
             }
             return true;
         }
-        private MultipartMessageManager getOuterType() {
-            return MultipartMessageManager.this;
-        }
+
         @Override
         public String toString() {
-            return "TxIdEntry [txId=" + txId + ", nodeId=" + nodeId + ", requestType=" + requestType + "]";
+            return "TxIdEntry [txId=" + txId + ']';
         }
     }
 
-    public MultipartMessageManager(){}
-    
-    public Short getTableIdForTxId(NodeId nodeId,TransactionId id){
-        
-        return txIdTotableIdMap.get(new TxIdEntry(nodeId,id,null));
-        
-    }
-    
-    public void setTxIdAndTableIdMapEntry(NodeId nodeId, TransactionId id,Short tableId){
-        if(id == null)
-            return;
-        txIdTotableIdMap.put(new TxIdEntry(nodeId,id,null), tableId);
+    public void recordExpectedTableTransaction(TransactionId id, Short tableId) {
+        recordExpectedTransaction(id);
+        txIdTotableIdMap.put(new TxIdEntry(id), Preconditions.checkNotNull(tableId));
     }
-    
-    public boolean isRequestTxIdExist(NodeId nodeId, TransactionId id, Boolean moreRepliesToFollow){
-        TxIdEntry entry = new TxIdEntry(nodeId,id,null);
-        if(moreRepliesToFollow.booleanValue()){
-            return txIdToRequestTypeMap.containsKey(entry);
-        }else{
-            return txIdToRequestTypeMap.remove(entry)==null?false:true;
+
+    public Short isExpectedTableTransaction(TransactionAware transaction, Boolean more) {
+        if (!isExpectedTransaction(transaction, more)) {
+            return null;
+        }
+
+        final TxIdEntry key = new TxIdEntry(transaction.getTransactionId());
+        if (more != null && more.booleanValue()) {
+            return txIdTotableIdMap.get(key);
+        } else {
+            return txIdTotableIdMap.remove(key);
         }
     }
-    public void addTxIdToRequestTypeEntry (NodeId nodeId, TransactionId id,StatsRequestType type){
-        if(id == null)
-            return;
-        TxIdEntry entry = new TxIdEntry(nodeId,id,type);
+
+    public void recordExpectedTransaction(TransactionId id) {
+        TxIdEntry entry = new TxIdEntry(Preconditions.checkNotNull(id));
         txIdToRequestTypeMap.put(entry, getExpiryTime());
     }
-    public boolean removeTxId(NodeId nodeId, TransactionId id){
-        TxIdEntry entry = new TxIdEntry(nodeId,id,null);
-        return txIdToRequestTypeMap.remove(entry)==null?false:true;
-    }
-    
-    private Date getExpiryTime(){
-        Date expires = new Date();
-        expires.setTime(expires.getTime()+StatisticsProvider.STATS_THREAD_EXECUTION_TIME*NUMBER_OF_WAIT_CYCLES);
-        return expires;
+
+    public boolean isExpectedTransaction(TransactionAware transaction, Boolean more) {
+        TxIdEntry entry = new TxIdEntry(transaction.getTransactionId());
+        if (more != null && more.booleanValue()) {
+            return txIdToRequestTypeMap.containsKey(entry);
+        } else {
+            return txIdToRequestTypeMap.remove(entry) != null;
+        }
     }
 
-    public enum StatsRequestType{
-        ALL_FLOW,
-        AGGR_FLOW,
-        ALL_PORT,
-        ALL_FLOW_TABLE,
-        ALL_QUEUE_STATS,
-        ALL_GROUP,
-        ALL_METER,
-        GROUP_DESC,
-        METER_CONFIG
+    private Long getExpiryTime() {
+        return System.nanoTime() + lifetimeNanos;
     }
-    
-    public void cleanStaleTransactionIds(){
+
+    public void cleanStaleTransactionIds() {
+        final long now = System.nanoTime();
+
         for (Iterator<TxIdEntry> it = txIdToRequestTypeMap.keySet().iterator();it.hasNext();){
             TxIdEntry txIdEntry = it.next();
-            Date now = new Date();
-            Date expiryTime = txIdToRequestTypeMap.get(txIdEntry);
-            if(now.after(expiryTime)){
+
+            Long expiryTime = txIdToRequestTypeMap.get(txIdEntry);
+            if(now > expiryTime){
                 it.remove();
                 txIdTotableIdMap.remove(txIdEntry);
-            }            
+            }
         }
     }
 }
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeConnectorStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeConnectorStatsTracker.java
new file mode 100644 (file)
index 0000000..00bd274
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright IBM Corporation, 2013.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.statistics.manager;
+
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllNodeConnectorsStatisticsInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class NodeConnectorStatsTracker extends AbstractStatsTracker<NodeConnectorStatisticsAndPortNumberMap, NodeConnectorStatisticsAndPortNumberMap> {
+    private static final Logger logger = LoggerFactory.getLogger(NodeConnectorStatsTracker.class);
+    private final OpendaylightPortStatisticsService portStatsService;
+
+    NodeConnectorStatsTracker(final OpendaylightPortStatisticsService portStatsService, final FlowCapableContext context, long lifetimeNanos) {
+        super(context, lifetimeNanos);
+        this.portStatsService = portStatsService;
+    }
+
+    @Override
+    protected void cleanupSingleStat(DataModificationTransaction trans, NodeConnectorStatisticsAndPortNumberMap item) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    protected NodeConnectorStatisticsAndPortNumberMap updateSingleStat(DataModificationTransaction trans, NodeConnectorStatisticsAndPortNumberMap item) {
+        FlowCapableNodeConnectorStatisticsBuilder statisticsBuilder
+                                        = new FlowCapableNodeConnectorStatisticsBuilder();
+        statisticsBuilder.setBytes(item.getBytes());
+        statisticsBuilder.setCollisionCount(item.getCollisionCount());
+        statisticsBuilder.setDuration(item.getDuration());
+        statisticsBuilder.setPackets(item.getPackets());
+        statisticsBuilder.setReceiveCrcError(item.getReceiveCrcError());
+        statisticsBuilder.setReceiveDrops(item.getReceiveDrops());
+        statisticsBuilder.setReceiveErrors(item.getReceiveErrors());
+        statisticsBuilder.setReceiveFrameError(item.getReceiveFrameError());
+        statisticsBuilder.setReceiveOverRunError(item.getReceiveOverRunError());
+        statisticsBuilder.setTransmitDrops(item.getTransmitDrops());
+        statisticsBuilder.setTransmitErrors(item.getTransmitErrors());
+
+        //Augment data to the node-connector
+        FlowCapableNodeConnectorStatisticsDataBuilder statisticsDataBuilder =
+                new FlowCapableNodeConnectorStatisticsDataBuilder();
+
+        statisticsDataBuilder.setFlowCapableNodeConnectorStatistics(statisticsBuilder.build());
+
+        InstanceIdentifier<NodeConnector> nodeConnectorRef = getNodeIdentifierBuilder()
+                .child(NodeConnector.class, new NodeConnectorKey(item.getNodeConnectorId())).build();
+
+        // 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);
+            trans.putOperationalData(nodeConnectorRef, nodeConnectorBuilder.build());
+        }
+
+        return item;
+    }
+
+    public void request() {
+        if (portStatsService != null) {
+            final GetAllNodeConnectorsStatisticsInputBuilder input = new GetAllNodeConnectorsStatisticsInputBuilder();
+            input.setNode(getNodeRef());
+
+            requestHelper(portStatsService.getAllNodeConnectorsStatistics(input.build()));
+        }
+    }
+}
index 395bacb5e374f9595f1d0f6a63e8778b6f83d1f6..6796b4eb8723d02064d31a56bfa479c9412a4246 100644 (file)
@@ -7,90 +7,52 @@
  */
 package org.opendaylight.controller.md.statistics.manager;
 
-import java.util.HashMap;
-import java.util.Iterator;
+import java.util.Collection;
 import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
+import java.util.Timer;
+import java.util.TimerTask;
 import java.util.concurrent.TimeUnit;
 
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 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.FlowId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsData;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsDataBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.aggregate.flow.statistics.AggregateFlowStatisticsBuilder;
 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.table.statistics.rev131215.FlowTableStatisticsData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMap;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatistics;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatisticsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.queue.rev130925.QueueId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupDescStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupDescStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeatures;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeaturesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatisticsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.desc.GroupDescBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.features.GroupFeaturesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatisticsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupFeatures;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterConfigStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterConfigStatsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeatures;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeaturesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterFeaturesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterConfigStatsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatisticsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterFeatures;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.AggregateFlowStatistics;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.GenericStatistics;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsDataBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsDataBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.flow.capable.node.connector.queue.statistics.FlowCapableNodeConnectorQueueStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMap;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -103,363 +65,124 @@ import com.google.common.base.Preconditions;
  *
  * @author avishnoi@in.ibm.com
  */
-public class NodeStatisticsHandler {
+public final class NodeStatisticsHandler implements AutoCloseable, FlowCapableContext {
     private static final Logger logger = LoggerFactory.getLogger(NodeStatisticsHandler.class);
+
+    private static final long STATS_COLLECTION_MILLIS = TimeUnit.SECONDS.toMillis(15);
+    private static final long FIRST_COLLECTION_MILLIS = TimeUnit.SECONDS.toMillis(5);
     private static final int NUMBER_OF_WAIT_CYCLES = 2;
 
-    private final Map<GroupDescStats,Long> groupDescStatsUpdate = new HashMap<>();
-    private final Map<MeterConfigStats,Long> meterConfigStatsUpdate = new HashMap<>();
-    private final Map<FlowEntry,Long> flowStatsUpdate = new HashMap<>();
-    private final Map<QueueEntry,Long> queuesStatsUpdate = new HashMap<>();
+    private final MultipartMessageManager msgManager;
     private final InstanceIdentifier<Node> targetNodeIdentifier;
-    private final StatisticsProvider statisticsProvider;
+    private final FlowStatsTracker flowStats;
+    private final FlowTableStatsTracker flowTableStats;
+    private final GroupDescStatsTracker groupDescStats;
+    private final GroupStatsTracker groupStats;
+    private final MeterConfigStatsTracker meterConfigStats;
+    private final MeterStatsTracker meterStats;
+    private final NodeConnectorStatsTracker nodeConnectorStats;
+    private final QueueStatsTracker queueStats;
+    private final DataProviderService dps;
+    private final NodeRef targetNodeRef;
     private final NodeKey targetNodeKey;
-    private int unaccountedFlowsCounter = 1;
-
-    public NodeStatisticsHandler(StatisticsProvider statisticsProvider, NodeKey nodeKey){
-        this.statisticsProvider = Preconditions.checkNotNull(statisticsProvider);
-        this.targetNodeKey = Preconditions.checkNotNull(nodeKey);
-        this.targetNodeIdentifier = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey).build();
-    }
-
-    private static class FlowEntry {
-        private final Short tableId;
-        private final Flow flow;
-
-        public FlowEntry(Short tableId, Flow flow){
-            this.tableId = tableId;
-            this.flow = flow;
-        }
-
-        public Short getTableId() {
-            return tableId;
-        }
-
-        public Flow getFlow() {
-            return flow;
-        }
-
+    private final TimerTask task = new TimerTask() {
         @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + ((flow == null) ? 0 : flow.hashCode());
-            result = prime * result + ((tableId == null) ? 0 : tableId.hashCode());
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj)
-                return true;
-            if (obj == null)
-                return false;
-            if (getClass() != obj.getClass())
-                return false;
-            FlowEntry other = (FlowEntry) obj;
-            if (flow == null) {
-                if (other.flow != null)
-                    return false;
-            } else if (!flow.equals(other.flow))
-                return false;
-            if (tableId == null) {
-                if (other.tableId != null)
-                    return false;
-            } else if (!tableId.equals(other.tableId))
-                return false;
-            return true;
-        }
-    }
-
-    private static final class QueueEntry{
-        private final NodeConnectorId nodeConnectorId;
-        private final QueueId queueId;
-        public QueueEntry(NodeConnectorId ncId, QueueId queueId){
-            this.nodeConnectorId = ncId;
-            this.queueId = queueId;
-        }
-        public NodeConnectorId getNodeConnectorId() {
-            return nodeConnectorId;
-        }
-        public QueueId getQueueId() {
-            return queueId;
-        }
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + ((nodeConnectorId == null) ? 0 : nodeConnectorId.hashCode());
-            result = prime * result + ((queueId == null) ? 0 : queueId.hashCode());
-            return result;
-        }
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj == null) {
-                return false;
-            }
-            if (!(obj instanceof QueueEntry)) {
-                return false;
-            }
-            QueueEntry other = (QueueEntry) obj;
-            if (nodeConnectorId == null) {
-                if (other.nodeConnectorId != null) {
-                    return false;
-                }
-            } else if (!nodeConnectorId.equals(other.nodeConnectorId)) {
-                return false;
-            }
-            if (queueId == null) {
-                if (other.queueId != null) {
-                    return false;
-                }
-            } else if (!queueId.equals(other.queueId)) {
-                return false;
-            }
-            return true;
+        public void run() {
+            requestPeriodicStatistics();
+            cleanStaleStatistics();
         }
+    };
+
+    public NodeStatisticsHandler(final DataProviderService dps, final NodeKey nodeKey,
+            final OpendaylightFlowStatisticsService flowStatsService,
+            final OpendaylightFlowTableStatisticsService flowTableStatsService,
+            final OpendaylightGroupStatisticsService groupStatsService,
+            final OpendaylightMeterStatisticsService meterStatsService,
+            final OpendaylightPortStatisticsService portStatsService,
+            final OpendaylightQueueStatisticsService queueStatsService) {
+        this.dps = Preconditions.checkNotNull(dps);
+        this.targetNodeKey = Preconditions.checkNotNull(nodeKey);
+        this.targetNodeIdentifier = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey).build();
+        this.targetNodeRef = new NodeRef(targetNodeIdentifier);
+
+        final long lifetimeNanos = TimeUnit.MILLISECONDS.toNanos(STATS_COLLECTION_MILLIS * NUMBER_OF_WAIT_CYCLES);
+
+        msgManager = new MultipartMessageManager(lifetimeNanos);
+        flowStats = new FlowStatsTracker(flowStatsService, this, lifetimeNanos);
+        flowTableStats = new FlowTableStatsTracker(flowTableStatsService, this, lifetimeNanos);
+        groupDescStats = new GroupDescStatsTracker(groupStatsService, this, lifetimeNanos);
+        groupStats = new GroupStatsTracker(groupStatsService, this, lifetimeNanos);
+        meterConfigStats = new MeterConfigStatsTracker(meterStatsService, this, lifetimeNanos);
+        meterStats = new MeterStatsTracker(meterStatsService, this, lifetimeNanos);
+        nodeConnectorStats = new NodeConnectorStatsTracker(portStatsService, this, lifetimeNanos);
+        queueStats = new QueueStatsTracker(queueStatsService, this, lifetimeNanos);
     }
 
     public NodeKey getTargetNodeKey() {
         return targetNodeKey;
     }
 
-    public synchronized void updateGroupDescStats(List<GroupDescStats> list){
-        final Long expiryTime = getExpiryTime();
-        final DataModificationTransaction trans = statisticsProvider.startChange();
-
-        for (GroupDescStats groupDescStats : list) {
-            GroupBuilder groupBuilder = new GroupBuilder();
-            GroupKey groupKey = new GroupKey(groupDescStats.getGroupId());
-            groupBuilder.setKey(groupKey);
-
-            InstanceIdentifier<Group> groupRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey)
-                                                                                        .augmentation(FlowCapableNode.class)
-                                                                                        .child(Group.class,groupKey).toInstance();
+    @Override
+    public InstanceIdentifier<Node> getNodeIdentifier() {
+        return targetNodeIdentifier;
+    }
 
-            NodeGroupDescStatsBuilder groupDesc= new NodeGroupDescStatsBuilder();
-            GroupDescBuilder stats = new GroupDescBuilder();
-            stats.fieldsFrom(groupDescStats);
-            groupDesc.setGroupDesc(stats.build());
+    @Override
+    public NodeRef getNodeRef() {
+        return targetNodeRef;
+    }
 
-            //Update augmented data
-            groupBuilder.addAugmentation(NodeGroupDescStats.class, groupDesc.build());
+    @Override
+    public DataModificationTransaction startDataModification() {
+        return dps.beginTransaction();
+    }
 
-            trans.putOperationalData(groupRef, groupBuilder.build());
-            this.groupDescStatsUpdate.put(groupDescStats, expiryTime);
+    public synchronized void updateGroupDescStats(TransactionAware transaction, Boolean more, List<GroupDescStats> list) {
+        if (msgManager.isExpectedTransaction(transaction, more)) {
+            groupDescStats.updateStats(list);
         }
-
-        trans.commit();
     }
 
-
-    public synchronized void updateGroupStats(List<GroupStats> list) {
-        final DataModificationTransaction trans = statisticsProvider.startChange();
-
-        for(GroupStats groupStats : list) {
-            GroupBuilder groupBuilder = new GroupBuilder();
-            GroupKey groupKey = new GroupKey(groupStats.getGroupId());
-            groupBuilder.setKey(groupKey);
-
-            InstanceIdentifier<Group> groupRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey)
-                                                                                        .augmentation(FlowCapableNode.class)
-                                                                                        .child(Group.class,groupKey).toInstance();
-
-            NodeGroupStatisticsBuilder groupStatisticsBuilder= new NodeGroupStatisticsBuilder();
-            GroupStatisticsBuilder stats = new GroupStatisticsBuilder();
-            stats.fieldsFrom(groupStats);
-            groupStatisticsBuilder.setGroupStatistics(stats.build());
-
-            //Update augmented data
-            groupBuilder.addAugmentation(NodeGroupStatistics.class, groupStatisticsBuilder.build());
-            trans.putOperationalData(groupRef, groupBuilder.build());
-
-            // FIXME: should we be tracking this data?
+    public synchronized void updateGroupStats(TransactionAware transaction, Boolean more, List<GroupStats> list) {
+        if (msgManager.isExpectedTransaction(transaction, more)) {
+            groupStats.updateStats(list);
         }
-
-        trans.commit();
     }
 
-    public synchronized void updateMeterConfigStats(List<MeterConfigStats> list) {
-        final Long expiryTime = getExpiryTime();
-        final DataModificationTransaction trans = statisticsProvider.startChange();
-
-        for(MeterConfigStats meterConfigStats : list) {
-            MeterBuilder meterBuilder = new MeterBuilder();
-            MeterKey meterKey = new MeterKey(meterConfigStats.getMeterId());
-            meterBuilder.setKey(meterKey);
-
-            InstanceIdentifier<Meter> meterRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey)
-                                                                                        .augmentation(FlowCapableNode.class)
-                                                                                        .child(Meter.class,meterKey).toInstance();
-
-            NodeMeterConfigStatsBuilder meterConfig= new NodeMeterConfigStatsBuilder();
-            MeterConfigStatsBuilder stats = new MeterConfigStatsBuilder();
-            stats.fieldsFrom(meterConfigStats);
-            meterConfig.setMeterConfigStats(stats.build());
-
-            //Update augmented data
-            meterBuilder.addAugmentation(NodeMeterConfigStats.class, meterConfig.build());
-
-            trans.putOperationalData(meterRef, meterBuilder.build());
-            this.meterConfigStatsUpdate.put(meterConfigStats, expiryTime);
+    public synchronized void updateMeterConfigStats(TransactionAware transaction, Boolean more, List<MeterConfigStats> list) {
+        if (msgManager.isExpectedTransaction(transaction, more)) {
+            meterConfigStats.updateStats(list);
         }
-
-        trans.commit();
     }
 
-
-    public synchronized void updateMeterStats(List<MeterStats> list) {
-        final DataModificationTransaction trans = statisticsProvider.startChange();
-
-        for(MeterStats meterStats : list) {
-            MeterBuilder meterBuilder = new MeterBuilder();
-            MeterKey meterKey = new MeterKey(meterStats.getMeterId());
-            meterBuilder.setKey(meterKey);
-
-            InstanceIdentifier<Meter> meterRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey)
-                                                                                        .augmentation(FlowCapableNode.class)
-                                                                                        .child(Meter.class,meterKey).toInstance();
-
-            NodeMeterStatisticsBuilder meterStatsBuilder= new NodeMeterStatisticsBuilder();
-            MeterStatisticsBuilder stats = new MeterStatisticsBuilder();
-            stats.fieldsFrom(meterStats);
-            meterStatsBuilder.setMeterStatistics(stats.build());
-
-            //Update augmented data
-            meterBuilder.addAugmentation(NodeMeterStatistics.class, meterStatsBuilder.build());
-            trans.putOperationalData(meterRef, meterBuilder.build());
-
-            // FIXME: should we be tracking this data?
+    public synchronized void updateMeterStats(TransactionAware transaction, Boolean more, List<MeterStats> list) {
+        if (msgManager.isExpectedTransaction(transaction, more)) {
+            meterStats.updateStats(list);
         }
-
-        trans.commit();
     }
 
-    public synchronized void updateQueueStats(List<QueueIdAndStatisticsMap> list) {
-        final Long expiryTime = getExpiryTime();
-        final DataModificationTransaction trans = statisticsProvider.startChange();
-
-        for (QueueIdAndStatisticsMap swQueueStats : list) {
-
-            QueueEntry queueEntry = new QueueEntry(swQueueStats.getNodeConnectorId(),swQueueStats.getQueueId());
-
-            FlowCapableNodeConnectorQueueStatisticsDataBuilder queueStatisticsDataBuilder = new FlowCapableNodeConnectorQueueStatisticsDataBuilder();
-
-            FlowCapableNodeConnectorQueueStatisticsBuilder queueStatisticsBuilder = new FlowCapableNodeConnectorQueueStatisticsBuilder();
-
-            queueStatisticsBuilder.fieldsFrom(swQueueStats);
-
-            queueStatisticsDataBuilder.setFlowCapableNodeConnectorQueueStatistics(queueStatisticsBuilder.build());
-
-            InstanceIdentifier<Queue> queueRef
-                    = InstanceIdentifier.builder(Nodes.class)
-                                        .child(Node.class, targetNodeKey)
-                                        .child(NodeConnector.class, new NodeConnectorKey(swQueueStats.getNodeConnectorId()))
-                                        .augmentation(FlowCapableNodeConnector.class)
-                                        .child(Queue.class, new QueueKey(swQueueStats.getQueueId())).toInstance();
-
-            QueueBuilder queueBuilder = new QueueBuilder();
-            FlowCapableNodeConnectorQueueStatisticsData qsd = queueStatisticsDataBuilder.build();
-            queueBuilder.addAugmentation(FlowCapableNodeConnectorQueueStatisticsData.class, qsd);
-            queueBuilder.setKey(new QueueKey(swQueueStats.getQueueId()));
-
-            logger.debug("Augmenting queue statistics {} of queue {} to port {}",
-                                        qsd,
-                                        swQueueStats.getQueueId(),
-                                        swQueueStats.getNodeConnectorId());
-
-            trans.putOperationalData(queueRef, queueBuilder.build());
-            this.queuesStatsUpdate.put(queueEntry, expiryTime);
+    public synchronized void updateQueueStats(TransactionAware transaction, Boolean more, List<QueueIdAndStatisticsMap> list) {
+        if (msgManager.isExpectedTransaction(transaction, more)) {
+            queueStats.updateStats(list);
         }
-
-        trans.commit();
     }
 
-    public synchronized void updateFlowTableStats(List<FlowTableAndStatisticsMap> list) {
-        final DataModificationTransaction trans = statisticsProvider.startChange();
-
-        for (FlowTableAndStatisticsMap ftStats : list) {
-
-            InstanceIdentifier<Table> tableRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey)
-                    .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(ftStats.getTableId().getValue())).toInstance();
-
-            FlowTableStatisticsDataBuilder statisticsDataBuilder = new FlowTableStatisticsDataBuilder();
-
-            FlowTableStatisticsBuilder statisticsBuilder = new FlowTableStatisticsBuilder();
-            statisticsBuilder.setActiveFlows(ftStats.getActiveFlows());
-            statisticsBuilder.setPacketsLookedUp(ftStats.getPacketsLookedUp());
-            statisticsBuilder.setPacketsMatched(ftStats.getPacketsMatched());
-
-            final FlowTableStatistics stats = statisticsBuilder.build();
-            statisticsDataBuilder.setFlowTableStatistics(stats);
-
-            logger.debug("Augment flow table statistics: {} for table {} on Node {}",
-                    stats,ftStats.getTableId(), targetNodeKey);
-
-            TableBuilder tableBuilder = new TableBuilder();
-            tableBuilder.setKey(new TableKey(ftStats.getTableId().getValue()));
-            tableBuilder.addAugmentation(FlowTableStatisticsData.class, statisticsDataBuilder.build());
-            trans.putOperationalData(tableRef, tableBuilder.build());
-
-            // FIXME: should we be tracking this data?
+    public synchronized void updateFlowTableStats(TransactionAware transaction, Boolean more, List<FlowTableAndStatisticsMap> list) {
+        if (msgManager.isExpectedTransaction(transaction, more)) {
+            flowTableStats.updateStats(list);
         }
-
-        trans.commit();
     }
 
-    public synchronized void updateNodeConnectorStats(List<NodeConnectorStatisticsAndPortNumberMap> list) {
-        final DataModificationTransaction trans = statisticsProvider.startChange();
-
-        for(NodeConnectorStatisticsAndPortNumberMap portStats : list) {
-
-            FlowCapableNodeConnectorStatisticsBuilder statisticsBuilder
-                                            = new FlowCapableNodeConnectorStatisticsBuilder();
-            statisticsBuilder.setBytes(portStats.getBytes());
-            statisticsBuilder.setCollisionCount(portStats.getCollisionCount());
-            statisticsBuilder.setDuration(portStats.getDuration());
-            statisticsBuilder.setPackets(portStats.getPackets());
-            statisticsBuilder.setReceiveCrcError(portStats.getReceiveCrcError());
-            statisticsBuilder.setReceiveDrops(portStats.getReceiveDrops());
-            statisticsBuilder.setReceiveErrors(portStats.getReceiveErrors());
-            statisticsBuilder.setReceiveFrameError(portStats.getReceiveFrameError());
-            statisticsBuilder.setReceiveOverRunError(portStats.getReceiveOverRunError());
-            statisticsBuilder.setTransmitDrops(portStats.getTransmitDrops());
-            statisticsBuilder.setTransmitErrors(portStats.getTransmitErrors());
-
-            //Augment data to the node-connector
-            FlowCapableNodeConnectorStatisticsDataBuilder statisticsDataBuilder =
-                    new FlowCapableNodeConnectorStatisticsDataBuilder();
-
-            statisticsDataBuilder.setFlowCapableNodeConnectorStatistics(statisticsBuilder.build());
-
-            InstanceIdentifier<NodeConnector> nodeConnectorRef = InstanceIdentifier.builder(Nodes.class)
-                    .child(Node.class, targetNodeKey)
-                    .child(NodeConnector.class, new NodeConnectorKey(portStats.getNodeConnectorId())).toInstance();
-
-            // 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);
-                trans.putOperationalData(nodeConnectorRef, nodeConnectorBuilder.build());
-            }
-
-            // FIXME: should we be tracking this data?
+    public synchronized void updateNodeConnectorStats(TransactionAware transaction, Boolean more, List<NodeConnectorStatisticsAndPortNumberMap> list) {
+        if (msgManager.isExpectedTransaction(transaction, more)) {
+            nodeConnectorStats.updateStats(list);
         }
-
-        trans.commit();
     }
 
-    public synchronized void updateAggregateFlowStats(Short tableId, AggregateFlowStatistics flowStats) {
+    public synchronized void updateAggregateFlowStats(TransactionAware transaction, Boolean more, AggregateFlowStatistics flowStats) {
+        final Short tableId = msgManager.isExpectedTableTransaction(transaction, more);
         if (tableId != null) {
-            final DataModificationTransaction trans = statisticsProvider.startChange();
-
-
+            final DataModificationTransaction trans = dps.beginTransaction();
             InstanceIdentifier<Table> tableRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey)
                     .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId)).toInstance();
 
@@ -476,13 +199,18 @@ public class NodeStatisticsHandler {
             tableBuilder.addAugmentation(AggregateFlowStatisticsData.class, aggregateFlowStatisticsDataBuilder.build());
             trans.putOperationalData(tableRef, tableBuilder.build());
 
-            // FIXME: should we be tracking this data?
             trans.commit();
         }
     }
 
+    public synchronized void updateFlowStats(TransactionAware transaction, Boolean more, List<FlowAndStatisticsMapList> list) {
+        if (msgManager.isExpectedTransaction(transaction, more)) {
+            flowStats.updateStats(list);
+        }
+    }
+
     public synchronized void updateGroupFeatures(GroupFeatures notification) {
-        final DataModificationTransaction trans = statisticsProvider.startChange();
+        final DataModificationTransaction trans = dps.beginTransaction();
 
         final NodeBuilder nodeData = new NodeBuilder();
         nodeData.setKey(targetNodeKey);
@@ -500,7 +228,7 @@ public class NodeStatisticsHandler {
     }
 
     public synchronized void updateMeterFeatures(MeterFeatures features) {
-        final DataModificationTransaction trans = statisticsProvider.startChange();
+        final DataModificationTransaction trans = dps.beginTransaction();
 
         final NodeBuilder nodeData = new NodeBuilder();
         nodeData.setKey(targetNodeKey);
@@ -517,254 +245,82 @@ public class NodeStatisticsHandler {
         trans.commit();
     }
 
-    public synchronized void updateFlowStats(List<FlowAndStatisticsMapList> list) {
-        final Long expiryTime = getExpiryTime();
-        final DataModificationTransaction trans = statisticsProvider.startChange();
-
-        for(FlowAndStatisticsMapList map : list) {
-            short tableId = map.getTableId();
-            boolean foundOriginalFlow = false;
-
-            FlowBuilder flowBuilder = new FlowBuilder();
-
-            FlowStatisticsDataBuilder flowStatisticsData = new FlowStatisticsDataBuilder();
-
-            FlowBuilder flow = new FlowBuilder();
-            flow.setContainerName(map.getContainerName());
-            flow.setBufferId(map.getBufferId());
-            flow.setCookie(map.getCookie());
-            flow.setCookieMask(map.getCookieMask());
-            flow.setFlags(map.getFlags());
-            flow.setFlowName(map.getFlowName());
-            flow.setHardTimeout(map.getHardTimeout());
-            if(map.getFlowId() != null)
-                flow.setId(new FlowId(map.getFlowId().getValue()));
-            flow.setIdleTimeout(map.getIdleTimeout());
-            flow.setInstallHw(map.isInstallHw());
-            flow.setInstructions(map.getInstructions());
-            if(map.getFlowId()!= null)
-                flow.setKey(new FlowKey(new FlowId(map.getKey().getFlowId().getValue())));
-            flow.setMatch(map.getMatch());
-            flow.setOutGroup(map.getOutGroup());
-            flow.setOutPort(map.getOutPort());
-            flow.setPriority(map.getPriority());
-            flow.setStrict(map.isStrict());
-            flow.setTableId(tableId);
-
-            Flow flowRule = flow.build();
-
-            FlowAndStatisticsMapListBuilder stats = new FlowAndStatisticsMapListBuilder();
-            stats.setByteCount(map.getByteCount());
-            stats.setPacketCount(map.getPacketCount());
-            stats.setDuration(map.getDuration());
-
-            GenericStatistics flowStats = stats.build();
-
-            //Augment the data to the flow node
-
-            FlowStatisticsBuilder flowStatistics = new FlowStatisticsBuilder();
-            flowStatistics.setByteCount(flowStats.getByteCount());
-            flowStatistics.setPacketCount(flowStats.getPacketCount());
-            flowStatistics.setDuration(flowStats.getDuration());
-            flowStatistics.setContainerName(map.getContainerName());
-            flowStatistics.setBufferId(map.getBufferId());
-            flowStatistics.setCookie(map.getCookie());
-            flowStatistics.setCookieMask(map.getCookieMask());
-            flowStatistics.setFlags(map.getFlags());
-            flowStatistics.setFlowName(map.getFlowName());
-            flowStatistics.setHardTimeout(map.getHardTimeout());
-            flowStatistics.setIdleTimeout(map.getIdleTimeout());
-            flowStatistics.setInstallHw(map.isInstallHw());
-            flowStatistics.setInstructions(map.getInstructions());
-            flowStatistics.setMatch(map.getMatch());
-            flowStatistics.setOutGroup(map.getOutGroup());
-            flowStatistics.setOutPort(map.getOutPort());
-            flowStatistics.setPriority(map.getPriority());
-            flowStatistics.setStrict(map.isStrict());
-            flowStatistics.setTableId(tableId);
-
-            flowStatisticsData.setFlowStatistics(flowStatistics.build());
-
-            logger.debug("Flow : {}",flowRule.toString());
-            logger.debug("Statistics to augment : {}",flowStatistics.build().toString());
-
-            InstanceIdentifier<Table> tableRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey)
-                    .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId)).toInstance();
+    public synchronized void cleanStaleStatistics() {
+        final DataModificationTransaction trans = dps.beginTransaction();
+        final long now = System.nanoTime();
 
-            Table table= (Table)trans.readConfigurationData(tableRef);
-
-            //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
-            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 = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey)
-                                .augmentation(FlowCapableNode.class)
-                                .child(Table.class, new TableKey(tableId))
-                                .child(Flow.class,existingFlow.getKey()).toInstance();
-                        flowBuilder.setKey(existingFlow.getKey());
-                        flowBuilder.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
-                        logger.debug("Found matching flow in the datastore, augmenting statistics");
-                        foundOriginalFlow = true;
-                        // Update entry with timestamp of latest response
-                        flow.setKey(existingFlow.getKey());
-                        FlowEntry flowStatsEntry = new FlowEntry(tableId,flow.build());
-                        flowStatsUpdate.put(flowStatsEntry, expiryTime);
-
-                        trans.putOperationalData(flowRef, flowBuilder.build());
-                    }
-                }
-            }
-
-            table = (Table)trans.readOperationalData(tableRef);
-            if(!foundOriginalFlow && 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 = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey)
-                                    .augmentation(FlowCapableNode.class)
-                                    .child(Table.class, new TableKey(tableId))
-                                    .child(Flow.class,existingFlow.getKey()).toInstance();
-                            flowBuilder.setKey(existingFlow.getKey());
-                            flowBuilder.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
-                            logger.debug("Found matching unaccounted flow in the operational datastore, augmenting statistics");
-                            foundOriginalFlow = true;
-
-                            // Update entry with timestamp of latest response
-                            flow.setKey(existingFlow.getKey());
-                            FlowEntry flowStatsEntry = new FlowEntry(tableId,flow.build());
-                            flowStatsUpdate.put(flowStatsEntry, expiryTime);
-                            trans.putOperationalData(flowRef, flowBuilder.build());
-                            break;
-                        }
-                    }
-                }
-            }
-            if(!foundOriginalFlow){
-                String flowKey = "#UF$TABLE*"+Short.toString(tableId)+"*"+Integer.toString(this.unaccountedFlowsCounter);
-                this.unaccountedFlowsCounter++;
-                FlowKey newFlowKey = new FlowKey(new FlowId(flowKey));
-                InstanceIdentifier<Flow> flowRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey)
-                        .augmentation(FlowCapableNode.class)
-                        .child(Table.class, new TableKey(tableId))
-                        .child(Flow.class,newFlowKey).toInstance();
-                flowBuilder.setKey(newFlowKey);
-                flowBuilder.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
-                logger.debug("Flow {} is not present in config data store, augmenting statistics as an unaccounted flow",
-                        flowBuilder.build());
-
-                // Update entry with timestamp of latest response
-                flow.setKey(newFlowKey);
-                FlowEntry flowStatsEntry = new FlowEntry(tableId,flow.build());
-                flowStatsUpdate.put(flowStatsEntry, expiryTime);
-                trans.putOperationalData(flowRef, flowBuilder.build());
-            }
-        }
+        flowStats.cleanup(trans, now);
+        groupDescStats.cleanup(trans, now);
+        groupStats.cleanup(trans, now);
+        meterConfigStats.cleanup(trans, now);
+        meterStats.cleanup(trans, now);
+        nodeConnectorStats.cleanup(trans, now);
+        queueStats.cleanup(trans, now);
+        msgManager.cleanStaleTransactionIds();
 
         trans.commit();
     }
 
-    private static Long getExpiryTime(){
-        final long now = System.nanoTime();
-        return now + TimeUnit.MILLISECONDS.toNanos(StatisticsProvider.STATS_THREAD_EXECUTION_TIME * NUMBER_OF_WAIT_CYCLES);
-    }
+    public synchronized void requestPeriodicStatistics() {
+        logger.debug("Send requests for statistics collection to node : {}", targetNodeKey);
 
-    public synchronized void cleanStaleStatistics(){
-        final DataModificationTransaction trans = this.statisticsProvider.startChange();
-        final long now = System.nanoTime();
+        flowTableStats.request();
 
-        //Clean stale statistics related to group
-        for (Iterator<Entry<GroupDescStats, Long>> it = this.groupDescStatsUpdate.entrySet().iterator();it.hasNext();){
-            Entry<GroupDescStats, Long> e = it.next();
-            if (now > e.getValue()) {
-                cleanGroupStatsFromDataStore(trans, e.getKey());
-                it.remove();
-            }
+        // 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)", targetNodeKey, tables.size());
+        for (final TableKey key : tables) {
+            logger.debug("Send aggregate stats request for flow table {} to node {}", key.getId(), targetNodeKey);
+            flowStats.requestAggregateFlows(key);
         }
 
-        //Clean stale statistics related to meter
-        for (Iterator<Entry<MeterConfigStats, Long>> it = this.meterConfigStatsUpdate.entrySet().iterator();it.hasNext();){
-            Entry<MeterConfigStats, Long> e = it.next();
-            if (now > e.getValue()) {
-                cleanMeterStatsFromDataStore(trans, e.getKey());
-                it.remove();
-            }
-        }
+        flowStats.requestAllFlowsAllTables();
+        nodeConnectorStats.request();
+        groupStats.request();
+        groupDescStats.request();
+        meterStats.request();
+        meterConfigStats.request();
+        queueStats.request();
+    }
 
-        //Clean stale statistics related to flow
-        for (Iterator<Entry<FlowEntry, Long>> it = this.flowStatsUpdate.entrySet().iterator();it.hasNext();){
-            Entry<FlowEntry, Long> e = it.next();
-            if (now > e.getValue()) {
-                cleanFlowStatsFromDataStore(trans, e.getKey());
-                it.remove();
-            }
-        }
+    public synchronized void start(final Timer timer) {
+        flowStats.start(dps);
+        groupDescStats.start(dps);
+        groupStats.start(dps);
+        meterConfigStats.start(dps);
+        meterStats.start(dps);
+        queueStats.start(dps);
 
-        //Clean stale statistics related to queue
-        for (Iterator<Entry<QueueEntry, Long>> it = this.queuesStatsUpdate.entrySet().iterator();it.hasNext();){
-            Entry<QueueEntry, Long> e = it.next();
-            if (now > e.getValue()) {
-                cleanQueueStatsFromDataStore(trans, e.getKey());
-                it.remove();
-            }
-        }
+        timer.schedule(task, (long) (Math.random() * FIRST_COLLECTION_MILLIS), STATS_COLLECTION_MILLIS);
 
-        trans.commit();
-    }
+        logger.debug("Statistics handler for node started with base interval {}ms", STATS_COLLECTION_MILLIS);
 
-    private void cleanQueueStatsFromDataStore(DataModificationTransaction trans, QueueEntry queueEntry) {
-        InstanceIdentifier<?> queueRef
-                        = InstanceIdentifier.builder(Nodes.class)
-                                            .child(Node.class, this.targetNodeKey)
-                                            .child(NodeConnector.class, new NodeConnectorKey(queueEntry.getNodeConnectorId()))
-                                            .augmentation(FlowCapableNodeConnector.class)
-                                            .child(Queue.class, new QueueKey(queueEntry.getQueueId()))
-                                            .augmentation(FlowCapableNodeConnectorQueueStatisticsData.class).toInstance();
-        trans.removeOperationalData(queueRef);
+        requestPeriodicStatistics();
     }
 
-    private void cleanFlowStatsFromDataStore(DataModificationTransaction trans, FlowEntry flowEntry) {
-        InstanceIdentifier<?> flowRef
-                        = InstanceIdentifier.builder(Nodes.class).child(Node.class, this.targetNodeKey)
-                                            .augmentation(FlowCapableNode.class)
-                                            .child(Table.class, new TableKey(flowEntry.getTableId()))
-                                            .child(Flow.class,flowEntry.getFlow().getKey())
-                                            .augmentation(FlowStatisticsData.class).toInstance();
-        trans.removeOperationalData(flowRef);
+    @Override
+    public synchronized void close() {
+        task.cancel();
+        flowStats.close();
+        groupDescStats.close();
+        groupStats.close();
+        meterConfigStats.close();
+        meterStats.close();
+        queueStats.close();
+
+        logger.debug("Statistics handler for {} shut down", targetNodeKey.getId());
     }
 
-    private void cleanMeterStatsFromDataStore(DataModificationTransaction trans, MeterConfigStats meterConfigStats) {
-        InstanceIdentifierBuilder<Meter> meterRef
-                        = InstanceIdentifier.builder(Nodes.class).child(Node.class,this.targetNodeKey)
-                                            .augmentation(FlowCapableNode.class)
-                                            .child(Meter.class,new MeterKey(meterConfigStats.getMeterId()));
-
-        InstanceIdentifier<?> nodeMeterConfigStatsAugmentation = meterRef.augmentation(NodeMeterConfigStats.class).toInstance();
-        trans.removeOperationalData(nodeMeterConfigStatsAugmentation);
-
-        InstanceIdentifier<?> nodeMeterStatisticsAugmentation = meterRef.augmentation(NodeMeterStatistics.class).toInstance();
-        trans.removeOperationalData(nodeMeterStatisticsAugmentation);
+    @Override
+    public void registerTransaction(TransactionId id) {
+        msgManager.recordExpectedTransaction(id);
+        logger.debug("Transaction {} for node {} sent successfully", id, targetNodeKey);
     }
 
-    private void cleanGroupStatsFromDataStore(DataModificationTransaction trans, GroupDescStats groupDescStats) {
-        InstanceIdentifierBuilder<Group> groupRef
-                        = InstanceIdentifier.builder(Nodes.class).child(Node.class,this.targetNodeKey)
-                                            .augmentation(FlowCapableNode.class)
-                                            .child(Group.class,new GroupKey(groupDescStats.getGroupId()));
-
-        InstanceIdentifier<?> nodeGroupDescStatsAugmentation = groupRef.augmentation(NodeGroupDescStats.class).toInstance();
-        trans.removeOperationalData(nodeGroupDescStatsAugmentation);
-
-        InstanceIdentifier<?> nodeGroupStatisticsAugmentation = groupRef.augmentation(NodeGroupStatistics.class).toInstance();
-        trans.removeOperationalData(nodeGroupStatisticsAugmentation);
+    @Override
+    public void registerTableTransaction(final TransactionId id, final Short table) {
+        msgManager.recordExpectedTableTransaction(id, table);
+        logger.debug("Transaction {} for node {} table {} sent successfully", id, targetNodeKey, table);
     }
 }
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/QueueStatsEntry.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/QueueStatsEntry.java
new file mode 100644 (file)
index 0000000..d1f2529
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright IBM Corporation, 2013.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.statistics.manager;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.queue.rev130925.QueueId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+
+final class QueueStatsEntry {
+    private final NodeConnectorId nodeConnectorId;
+    private final QueueId queueId;
+    public QueueStatsEntry(NodeConnectorId ncId, QueueId queueId){
+        this.nodeConnectorId = ncId;
+        this.queueId = queueId;
+    }
+    public NodeConnectorId getNodeConnectorId() {
+        return nodeConnectorId;
+    }
+    public QueueId getQueueId() {
+        return queueId;
+    }
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((nodeConnectorId == null) ? 0 : nodeConnectorId.hashCode());
+        result = prime * result + ((queueId == null) ? 0 : queueId.hashCode());
+        return result;
+    }
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof QueueStatsEntry)) {
+            return false;
+        }
+        QueueStatsEntry other = (QueueStatsEntry) obj;
+        if (nodeConnectorId == null) {
+            if (other.nodeConnectorId != null) {
+                return false;
+            }
+        } else if (!nodeConnectorId.equals(other.nodeConnectorId)) {
+            return false;
+        }
+        if (queueId == null) {
+            if (other.queueId != null) {
+                return false;
+            }
+        } else if (!queueId.equals(other.queueId)) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/QueueStatsTracker.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/QueueStatsTracker.java
new file mode 100644 (file)
index 0000000..f187c70
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright IBM Corporation, 2013.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.statistics.manager;
+
+import 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.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.queue.rev130925.QueueId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetAllQueuesStatisticsFromAllPortsInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetQueueStatisticsFromGivenPortInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.flow.capable.node.connector.queue.statistics.FlowCapableNodeConnectorQueueStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMap;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class QueueStatsTracker extends AbstractListeningStatsTracker<QueueIdAndStatisticsMap, QueueStatsEntry> {
+    private static final Logger logger = LoggerFactory.getLogger(QueueStatsTracker.class);
+    private final OpendaylightQueueStatisticsService queueStatsService;
+
+    QueueStatsTracker(OpendaylightQueueStatisticsService queueStatsService, final FlowCapableContext context, long lifetimeNanos) {
+        super(context, lifetimeNanos);
+        this.queueStatsService = queueStatsService;
+    }
+
+    @Override
+    protected void cleanupSingleStat(DataModificationTransaction trans, QueueStatsEntry item) {
+        InstanceIdentifier<?> queueRef
+                            = getNodeIdentifierBuilder().child(NodeConnector.class, new NodeConnectorKey(item.getNodeConnectorId()))
+                                                .augmentation(FlowCapableNodeConnector.class)
+                                                .child(Queue.class, new QueueKey(item.getQueueId()))
+                                                .augmentation(FlowCapableNodeConnectorQueueStatisticsData.class).build();
+        trans.removeOperationalData(queueRef);
+    }
+
+    @Override
+    protected QueueStatsEntry updateSingleStat(DataModificationTransaction trans, QueueIdAndStatisticsMap item) {
+
+        QueueStatsEntry queueEntry = new QueueStatsEntry(item.getNodeConnectorId(), item.getQueueId());
+
+        FlowCapableNodeConnectorQueueStatisticsDataBuilder queueStatisticsDataBuilder = new FlowCapableNodeConnectorQueueStatisticsDataBuilder();
+
+        FlowCapableNodeConnectorQueueStatisticsBuilder queueStatisticsBuilder = new FlowCapableNodeConnectorQueueStatisticsBuilder();
+
+        queueStatisticsBuilder.fieldsFrom(item);
+
+        queueStatisticsDataBuilder.setFlowCapableNodeConnectorQueueStatistics(queueStatisticsBuilder.build());
+
+        InstanceIdentifier<Queue> queueRef = getNodeIdentifierBuilder().child(NodeConnector.class, new NodeConnectorKey(item.getNodeConnectorId()))
+                                    .augmentation(FlowCapableNodeConnector.class)
+                                    .child(Queue.class, new QueueKey(item.getQueueId())).toInstance();
+
+        QueueBuilder queueBuilder = new QueueBuilder();
+        FlowCapableNodeConnectorQueueStatisticsData qsd = queueStatisticsDataBuilder.build();
+        queueBuilder.addAugmentation(FlowCapableNodeConnectorQueueStatisticsData.class, qsd);
+        queueBuilder.setKey(new QueueKey(item.getQueueId()));
+
+        logger.debug("Augmenting queue statistics {} of queue {} to port {}",
+                                    qsd,
+                                    item.getQueueId(),
+                                    item.getNodeConnectorId());
+
+        trans.putOperationalData(queueRef, queueBuilder.build());
+        return queueEntry;
+    }
+
+    public void request() {
+        if (queueStatsService != null) {
+            GetAllQueuesStatisticsFromAllPortsInputBuilder input = new GetAllQueuesStatisticsFromAllPortsInputBuilder();
+            input.setNode(getNodeRef());
+
+            requestHelper(queueStatsService.getAllQueuesStatisticsFromAllPorts(input.build()));
+        }
+    }
+
+    public void request(NodeConnectorId nodeConnectorId, QueueId queueId) {
+        if (queueStatsService != null) {
+            GetQueueStatisticsFromGivenPortInputBuilder input = new GetQueueStatisticsFromGivenPortInputBuilder();
+
+            input.setNode(getNodeRef());
+            input.setNodeConnectorId(nodeConnectorId);
+            input.setQueueId(queueId);
+
+            requestHelper(queueStatsService.getQueueStatisticsFromGivenPort(input.build()));
+        }
+    }
+
+    @Override
+    public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        for (Entry<InstanceIdentifier<?>, DataObject> e : change.getCreatedConfigurationData().entrySet()) {
+            if (Queue.class.equals(e.getKey().getTargetType())) {
+                final Queue queue = (Queue) e.getValue();
+                final NodeConnectorKey key = e.getKey().firstKeyOf(NodeConnector.class, NodeConnectorKey.class);
+                logger.debug("Key {} triggered request for connector {} queue {}", key.getId(), queue.getQueueId());
+                request(key.getId(), queue.getQueueId());
+            } else {
+                logger.debug("Ignoring key {}", e.getKey());
+            }
+        }
+
+        final DataModificationTransaction trans = startTransaction();
+        for (InstanceIdentifier<?> key : change.getRemovedConfigurationData()) {
+            if (Queue.class.equals(key.getTargetType())) {
+                @SuppressWarnings("unchecked")
+                final InstanceIdentifier<Queue> queue = (InstanceIdentifier<Queue>)key;
+                final InstanceIdentifier<?> del = InstanceIdentifier.builder(queue)
+                        .augmentation(FlowCapableNodeConnectorQueueStatisticsData.class).build();
+                logger.debug("Key {} triggered remove of augmentation {}", key, del);
+
+                trans.removeOperationalData(del);
+            }
+        }
+        trans.commit();
+    }
+
+    @Override
+    protected InstanceIdentifier<?> listenPath() {
+        return getNodeIdentifierBuilder().child(NodeConnector.class)
+                .augmentation(FlowCapableNodeConnector.class).child(Queue.class).build();
+    }
+
+    @Override
+    protected String statName() {
+        return "Queue";
+    }
+
+    @Override
+    public void start(final DataBrokerService dbs) {
+        if (queueStatsService == null) {
+            logger.debug("No Queue Statistics service, not subscribing to queues on node {}", getNodeIdentifier());
+            return;
+        }
+
+        super.start(dbs);
+    }
+}
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/RPCFailedException.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/RPCFailedException.java
new file mode 100644 (file)
index 0000000..308c6dd
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.statistics.manager;
+
+import java.util.Collection;
+
+import org.opendaylight.yangtools.yang.common.RpcError;
+
+final class RPCFailedException extends RuntimeException {
+    private static final long serialVersionUID = 1L;
+    private final Collection<RpcError> errors;
+
+    public RPCFailedException(final String message, final Collection<RpcError> errors) {
+        super(message);
+        this.errors = errors;
+    }
+
+    @Override
+    public String toString() {
+        return "RPCFailedException [errors=" + errors + ", message=" + getMessage() + ']';
+    }
+}
index 155815dc8802e70b09015d6590f7957e85a44492..bd9f96c875fe2faa6846eb5f2c4f1b076fa5827d 100644 (file)
@@ -44,7 +44,6 @@ public class StatisticsListener implements OpendaylightGroupStatisticsListener,
 
     private final static Logger sucLogger = LoggerFactory.getLogger(StatisticsListener.class);
     private final StatisticsProvider statisticsManager;
-    private final MultipartMessageManager messageManager;
 
     /**
      * default ctor
@@ -52,56 +51,37 @@ public class StatisticsListener implements OpendaylightGroupStatisticsListener,
      */
     public StatisticsListener(final StatisticsProvider manager){
         this.statisticsManager = manager;
-        this.messageManager = this.statisticsManager.getMultipartMessageManager();
     }
 
     @Override
     public void onMeterConfigStatsUpdated(final MeterConfigStatsUpdated notification) {
-        //Check if response is for the request statistics-manager sent.
-        if(!messageManager.isRequestTxIdExist(notification.getId(),notification.getTransactionId(),notification.isMoreReplies()))
-            return;
-
-        //Add statistics to local cache
         final NodeStatisticsHandler handler = this.statisticsManager.getStatisticsHandler(notification.getId());
         if (handler != null) {
-            handler.updateMeterConfigStats(notification.getMeterConfigStats());
+            handler.updateMeterConfigStats(notification, notification.isMoreReplies(), notification.getMeterConfigStats());
         }
     }
 
     @Override
     public void onMeterStatisticsUpdated(MeterStatisticsUpdated notification) {
-        //Check if response is for the request statistics-manager sent.
-        if(!messageManager.isRequestTxIdExist(notification.getId(),notification.getTransactionId(),notification.isMoreReplies()))
-            return;
-
-        //Add statistics to local cache
         final NodeStatisticsHandler handler = this.statisticsManager.getStatisticsHandler(notification.getId());
         if (handler != null) {
-            handler.updateMeterStats(notification.getMeterStats());
+            handler.updateMeterStats(notification, notification.isMoreReplies(), notification.getMeterStats());
         }
     }
 
     @Override
     public void onGroupDescStatsUpdated(GroupDescStatsUpdated notification) {
-        //Check if response is for the request statistics-manager sent.
-        if(!messageManager.isRequestTxIdExist(notification.getId(),notification.getTransactionId(),notification.isMoreReplies()))
-            return;
-
         final NodeStatisticsHandler handler = statisticsManager.getStatisticsHandler(notification.getId());
         if (handler != null) {
-            handler.updateGroupDescStats(notification.getGroupDescStats());
+            handler.updateGroupDescStats(notification, notification.isMoreReplies(), notification.getGroupDescStats());
         }
     }
 
     @Override
     public void onGroupStatisticsUpdated(GroupStatisticsUpdated notification) {
-        //Check if response is for the request statistics-manager sent.
-        if(!messageManager.isRequestTxIdExist(notification.getId(),notification.getTransactionId(),notification.isMoreReplies()))
-            return;
-
         final NodeStatisticsHandler handler = statisticsManager.getStatisticsHandler(notification.getId());
         if (handler != null) {
-            handler.updateGroupStats(notification.getGroupStats());
+            handler.updateGroupStats(notification, notification.isMoreReplies(), notification.getGroupStats());
         }
     }
 
@@ -123,65 +103,42 @@ public class StatisticsListener implements OpendaylightGroupStatisticsListener,
 
     @Override
     public void onFlowsStatisticsUpdate(final FlowsStatisticsUpdate notification) {
-        //Check if response is for the request statistics-manager sent.
-        if(!messageManager.isRequestTxIdExist(notification.getId(),notification.getTransactionId(),notification.isMoreReplies()))
-            return;
-
         sucLogger.debug("Received flow stats update : {}",notification.toString());
         final NodeStatisticsHandler sna = this.statisticsManager.getStatisticsHandler(notification.getId());
         if (sna != null) {
-            sna.updateFlowStats(notification.getFlowAndStatisticsMapList());
+            sna.updateFlowStats(notification, notification.isMoreReplies(), notification.getFlowAndStatisticsMapList());
         }
     }
 
     @Override
     public void onAggregateFlowStatisticsUpdate(AggregateFlowStatisticsUpdate notification) {
-        //Check if response is for the request statistics-manager sent.
-        if(!messageManager.isRequestTxIdExist(notification.getId(),notification.getTransactionId(),notification.isMoreReplies()))
-            return;
-
         final NodeStatisticsHandler handler = this.statisticsManager.getStatisticsHandler(notification.getId());
         if (handler != null) {
-            final Short tableId = messageManager.getTableIdForTxId(notification.getId(),notification.getTransactionId());
-            handler.updateAggregateFlowStats(tableId, notification);
+            handler.updateAggregateFlowStats(notification, notification.isMoreReplies(), notification);
         }
     }
 
     @Override
     public void onNodeConnectorStatisticsUpdate(NodeConnectorStatisticsUpdate notification) {
-        //Check if response is for the request statistics-manager sent.
-        if(!messageManager.isRequestTxIdExist(notification.getId(),notification.getTransactionId(),notification.isMoreReplies()))
-            return;
-
         final NodeStatisticsHandler handler = this.statisticsManager.getStatisticsHandler(notification.getId());
         if (handler != null) {
-            handler.updateNodeConnectorStats(notification.getNodeConnectorStatisticsAndPortNumberMap());
+            handler.updateNodeConnectorStats(notification, notification.isMoreReplies(), notification.getNodeConnectorStatisticsAndPortNumberMap());
         }
     }
 
     @Override
     public void onFlowTableStatisticsUpdate(FlowTableStatisticsUpdate notification) {
-        //Check if response is for the request statistics-manager sent.
-        if(!messageManager.isRequestTxIdExist(notification.getId(),notification.getTransactionId(),notification.isMoreReplies()))
-            return;
-
         final NodeStatisticsHandler handler = this.statisticsManager.getStatisticsHandler(notification.getId());
         if (handler != null) {
-            handler.updateFlowTableStats(notification.getFlowTableAndStatisticsMap());
+            handler.updateFlowTableStats(notification, notification.isMoreReplies(), notification.getFlowTableAndStatisticsMap());
         }
     }
 
     @Override
     public void onQueueStatisticsUpdate(QueueStatisticsUpdate notification) {
-        //Check if response is for the request statistics-manager sent.
-        if(!messageManager.isRequestTxIdExist(notification.getId(),notification.getTransactionId(),notification.isMoreReplies()))
-            return;
-
-        //Add statistics to local cache
         final NodeStatisticsHandler handler = this.statisticsManager.getStatisticsHandler(notification.getId());
         if (handler != null) {
-            handler.updateQueueStats(notification.getQueueIdAndStatisticsMap());
+            handler.updateQueueStats(notification, notification.isMoreReplies(), notification.getQueueIdAndStatisticsMap());
         }
     }
 }
-
index b59482e96b0feb8f75890b5d51d185cb459f5ef6..5bcbef119a8c332442d405681dd018dc1368c9c7 100644 (file)
@@ -11,7 +11,6 @@ package org.opendaylight.controller.md.statistics.manager;
 import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.osgi.framework.BundleContext;
 
@@ -20,12 +19,11 @@ public class StatisticsManagerActivator extends AbstractBindingAwareProvider {
 
     @Override
     public void onSessionInitiated(ProviderContext session) {
-        final DataBrokerService dbs = session.getSALService(DataBrokerService.class);
         final DataProviderService dps = session.getSALService(DataProviderService.class);
         final NotificationProviderService nps = session.getSALService(NotificationProviderService.class);
 
         statsProvider = new StatisticsProvider(dps);
-        statsProvider.start(dbs, nps, session);
+        statsProvider.start(nps, session);
     }
 
     @Override
index ab5d20a951dd279a26b4abdc8068be958f339c21..892d304daa8d6cd20c7010082f2698cb8de90266 100644 (file)
@@ -7,68 +7,30 @@
  */
 package org.opendaylight.controller.md.statistics.manager;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Collection;
+import java.util.Timer;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
 
-import org.eclipse.xtext.xbase.lib.Exceptions;
-import org.opendaylight.controller.md.statistics.manager.MultipartMessageManager.StatsRequestType;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
 import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 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.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.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.queue.rev130925.QueueId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetAllGroupStatisticsInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetAllGroupStatisticsOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupDescriptionInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupDescriptionOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 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.node.NodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterConfigStatisticsInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterConfigStatisticsOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterStatisticsInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterStatisticsOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllNodeConnectorsStatisticsInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllNodeConnectorsStatisticsOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetAllQueuesStatisticsFromAllPortsInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetAllQueuesStatisticsFromAllPortsOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetQueueStatisticsFromGivenPortInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetQueueStatisticsFromGivenPortOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.NotificationListener;
-import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -87,17 +49,12 @@ import com.google.common.base.Preconditions;
  *
  */
 public class StatisticsProvider implements AutoCloseable {
-    public static final int STATS_THREAD_EXECUTION_TIME= 15000;
-
     private static final Logger spLogger = LoggerFactory.getLogger(StatisticsProvider.class);
 
-    private final MultipartMessageManager multipartMessageManager = new MultipartMessageManager();
-    private final InstanceIdentifier<Nodes> nodesIdentifier = InstanceIdentifier.builder(Nodes.class).toInstance();
+    private final ConcurrentMap<NodeId, NodeStatisticsHandler> handlers = new ConcurrentHashMap<>();
+    private final Timer timer = new Timer("statistics-manager", true);
     private final DataProviderService dps;
 
-    //Local caching of stats
-    private final ConcurrentMap<NodeId,NodeStatisticsHandler> statisticsCache = new ConcurrentHashMap<>();
-
     private OpendaylightGroupStatisticsService groupStatsService;
 
     private OpendaylightMeterStatisticsService meterStatsService;
@@ -110,33 +67,19 @@ public class StatisticsProvider implements AutoCloseable {
 
     private OpendaylightQueueStatisticsService queueStatsService;
 
-    private StatisticsUpdateHandler statsUpdateHandler;
-
-    private Thread statisticsRequesterThread;
-
-    private Thread statisticsAgerThread;
-
-
     public StatisticsProvider(final DataProviderService dataService) {
         this.dps = Preconditions.checkNotNull(dataService);
     }
 
-    public MultipartMessageManager getMultipartMessageManager() {
-        return multipartMessageManager;
-    }
-
     private final StatisticsListener updateCommiter = new StatisticsListener(StatisticsProvider.this);
 
     private Registration<NotificationListener> listenerRegistration;
 
-    public void start(final DataBrokerService dbs, final NotificationProviderService nps, final RpcConsumerRegistry rpcRegistry) {
-
-        this.listenerRegistration = nps.registerNotificationListener(this.updateCommiter);
+    private ListenerRegistration<DataChangeListener> flowCapableTrackerRegistration;
 
-        statsUpdateHandler = new StatisticsUpdateHandler(StatisticsProvider.this);
-        registerDataStoreUpdateListener(dbs);
+    public void start(final NotificationProviderService nps, final RpcConsumerRegistry rpcRegistry) {
 
-        // Get Group/Meter statistics service instance
+        // Get Group/Meter statistics service instances
         groupStatsService = rpcRegistry.getRpcService(OpendaylightGroupStatisticsService.class);
         meterStatsService = rpcRegistry.getRpcService(OpendaylightMeterStatisticsService.class);
         flowStatsService = rpcRegistry.getRpcService(OpendaylightFlowStatisticsService.class);
@@ -144,310 +87,19 @@ public class StatisticsProvider implements AutoCloseable {
         flowTableStatsService = rpcRegistry.getRpcService(OpendaylightFlowTableStatisticsService.class);
         queueStatsService = rpcRegistry.getRpcService(OpendaylightQueueStatisticsService.class);
 
-        statisticsRequesterThread = new Thread( new Runnable(){
-
-            @Override
-            public void run() {
-                while(true){
-                    try {
-                        statsRequestSender();
-
-                        Thread.sleep(STATS_THREAD_EXECUTION_TIME);
-                    }catch (Exception e){
-                        spLogger.error("Exception occurred while sending stats request : {}",e);
-                    }
-                }
-            }
-        });
-
-        spLogger.debug("Statistics requester thread started with timer interval : {}",STATS_THREAD_EXECUTION_TIME);
-
-        statisticsRequesterThread.start();
-
-        statisticsAgerThread = new Thread( new Runnable(){
-
-            @Override
-            public void run() {
-                while(true){
-                    try {
-                        for(NodeStatisticsHandler nodeStatisticsAger : statisticsCache.values()){
-                            nodeStatisticsAger.cleanStaleStatistics();
-                        }
-                        multipartMessageManager.cleanStaleTransactionIds();
-
-                        Thread.sleep(STATS_THREAD_EXECUTION_TIME);
-                    }catch (Exception e){
-                        spLogger.error("Exception occurred while sending stats request : {}",e);
-                    }
-                }
-            }
-        });
-
-        spLogger.debug("Statistics ager thread started with timer interval : {}",STATS_THREAD_EXECUTION_TIME);
+        // Start receiving notifications
+        this.listenerRegistration = nps.registerNotificationListener(this.updateCommiter);
 
-        statisticsAgerThread.start();
+        // Register for switch connect/disconnect notifications
+        final InstanceIdentifier<FlowCapableNode> fcnId = InstanceIdentifier.builder(Nodes.class)
+                .child(Node.class).augmentation(FlowCapableNode.class).build();
+        spLogger.debug("Registering FlowCapable tracker to {}", fcnId);
+        this.flowCapableTrackerRegistration = dps.registerDataChangeListener(fcnId,
+                new FlowCapableTracker(this, fcnId));
 
         spLogger.info("Statistics Provider started.");
     }
 
-    private void registerDataStoreUpdateListener(DataBrokerService dbs) {
-        //Register for Node updates
-        InstanceIdentifier<? extends DataObject> pathNode = InstanceIdentifier.builder(Nodes.class)
-                                                                        .child(Node.class).toInstance();
-        dbs.registerDataChangeListener(pathNode, statsUpdateHandler);
-
-        //Register for flow updates
-        InstanceIdentifier<? extends DataObject> pathFlow = InstanceIdentifier.builder(Nodes.class).child(Node.class)
-                                                                    .augmentation(FlowCapableNode.class)
-                                                                    .child(Table.class)
-                                                                    .child(Flow.class).toInstance();
-        dbs.registerDataChangeListener(pathFlow, statsUpdateHandler);
-
-        //Register for meter updates
-        InstanceIdentifier<? extends DataObject> pathMeter = InstanceIdentifier.builder(Nodes.class).child(Node.class)
-                                                    .augmentation(FlowCapableNode.class)
-                                                    .child(Meter.class).toInstance();
-
-        dbs.registerDataChangeListener(pathMeter, statsUpdateHandler);
-
-        //Register for group updates
-        InstanceIdentifier<? extends DataObject> pathGroup = InstanceIdentifier.builder(Nodes.class).child(Node.class)
-                                                    .augmentation(FlowCapableNode.class)
-                                                    .child(Group.class).toInstance();
-        dbs.registerDataChangeListener(pathGroup, statsUpdateHandler);
-
-        //Register for queue updates
-        InstanceIdentifier<? extends DataObject> pathQueue = InstanceIdentifier.builder(Nodes.class).child(Node.class)
-                                                                    .child(NodeConnector.class)
-                                                                    .augmentation(FlowCapableNodeConnector.class)
-                                                                    .child(Queue.class).toInstance();
-        dbs.registerDataChangeListener(pathQueue, statsUpdateHandler);
-    }
-
-    protected DataModificationTransaction startChange() {
-        return dps.beginTransaction();
-    }
-
-    private void statsRequestSender(){
-
-        List<Node> targetNodes = getAllConnectedNodes();
-
-        if(targetNodes == null)
-            return;
-
-
-        for (Node targetNode : targetNodes){
-
-            if(targetNode.getAugmentation(FlowCapableNode.class) != null){
-                sendStatisticsRequestsToNode(targetNode);
-            }
-        }
-    }
-
-    public void sendStatisticsRequestsToNode(Node targetNode){
-
-        spLogger.debug("Send requests for statistics collection to node : {})",targetNode.getId());
-
-        InstanceIdentifier<Node> targetInstanceId = InstanceIdentifier.builder(Nodes.class).child(Node.class,targetNode.getKey()).toInstance();
-
-        NodeRef targetNodeRef = new NodeRef(targetInstanceId);
-
-        try{
-            if(flowStatsService != null){
-                sendAggregateFlowsStatsFromAllTablesRequest(targetNode.getKey());
-                sendAllFlowsStatsFromAllTablesRequest(targetNodeRef);
-            }
-            if(flowTableStatsService != null){
-                sendAllFlowTablesStatisticsRequest(targetNodeRef);
-            }
-            if(portStatsService != null){
-                sendAllNodeConnectorsStatisticsRequest(targetNodeRef);
-            }
-            if(groupStatsService != null){
-                sendAllGroupStatisticsRequest(targetNodeRef);
-                sendGroupDescriptionRequest(targetNodeRef);
-            }
-            if(meterStatsService != null){
-                sendAllMeterStatisticsRequest(targetNodeRef);
-                sendMeterConfigStatisticsRequest(targetNodeRef);
-            }
-            if(queueStatsService != null){
-                sendAllQueueStatsFromAllNodeConnector (targetNodeRef);
-            }
-        }catch(Exception e){
-            spLogger.error("Exception occured while sending statistics requests : {}", e);
-        }
-    }
-
-
-    public void sendAllFlowTablesStatisticsRequest(NodeRef targetNodeRef) throws InterruptedException, ExecutionException {
-        final GetFlowTablesStatisticsInputBuilder input =
-                new GetFlowTablesStatisticsInputBuilder();
-
-        input.setNode(targetNodeRef);
-
-        Future<RpcResult<GetFlowTablesStatisticsOutput>> response =
-                flowTableStatsService.getFlowTablesStatistics(input.build());
-
-        this.multipartMessageManager.addTxIdToRequestTypeEntry(getNodeId(targetNodeRef),response.get().getResult().getTransactionId()
-                , StatsRequestType.ALL_FLOW_TABLE);
-
-    }
-
-    public void sendAllFlowsStatsFromAllTablesRequest(NodeRef targetNode) throws InterruptedException, ExecutionException{
-        final GetAllFlowsStatisticsFromAllFlowTablesInputBuilder input =
-                new GetAllFlowsStatisticsFromAllFlowTablesInputBuilder();
-
-        input.setNode(targetNode);
-
-        Future<RpcResult<GetAllFlowsStatisticsFromAllFlowTablesOutput>> response =
-                flowStatsService.getAllFlowsStatisticsFromAllFlowTables(input.build());
-
-        this.multipartMessageManager.addTxIdToRequestTypeEntry(getNodeId(targetNode), response.get().getResult().getTransactionId()
-                , StatsRequestType.ALL_FLOW);
-
-    }
-
-    public void sendFlowStatsFromTableRequest(NodeRef targetNode,Flow flow) throws InterruptedException, ExecutionException{
-        final GetFlowStatisticsFromFlowTableInputBuilder input =
-                new GetFlowStatisticsFromFlowTableInputBuilder();
-
-        input.setNode(targetNode);
-        input.fieldsFrom(flow);
-
-        Future<RpcResult<GetFlowStatisticsFromFlowTableOutput>> response =
-                flowStatsService.getFlowStatisticsFromFlowTable(input.build());
-
-        this.multipartMessageManager.addTxIdToRequestTypeEntry(getNodeId(targetNode), response.get().getResult().getTransactionId()
-                , StatsRequestType.ALL_FLOW);
-
-    }
-
-    public void sendAggregateFlowsStatsFromAllTablesRequest(NodeKey targetNodeKey) throws InterruptedException, ExecutionException{
-
-        List<Short> tablesId = getTablesFromNode(targetNodeKey);
-
-        if(tablesId.size() != 0){
-            for(Short id : tablesId){
-
-                sendAggregateFlowsStatsFromTableRequest(targetNodeKey,id);
-            }
-        }else{
-            spLogger.debug("No details found in data store for flow tables associated with Node {}",targetNodeKey);
-        }
-    }
-
-    public void sendAggregateFlowsStatsFromTableRequest(NodeKey targetNodeKey,Short tableId) throws InterruptedException, ExecutionException{
-
-        spLogger.debug("Send aggregate stats request for flow table {} to node {}",tableId,targetNodeKey);
-        GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder input =
-                new GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder();
-
-        input.setNode(new NodeRef(InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey).toInstance()));
-        input.setTableId(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId(tableId));
-        Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput>> response =
-                flowStatsService.getAggregateFlowStatisticsFromFlowTableForAllFlows(input.build());
-
-        multipartMessageManager.setTxIdAndTableIdMapEntry(targetNodeKey.getId(), response.get().getResult().getTransactionId(), tableId);
-        this.multipartMessageManager.addTxIdToRequestTypeEntry(targetNodeKey.getId(), response.get().getResult().getTransactionId()
-                , StatsRequestType.AGGR_FLOW);
-    }
-
-    public void sendAllNodeConnectorsStatisticsRequest(NodeRef targetNode) throws InterruptedException, ExecutionException{
-
-        final GetAllNodeConnectorsStatisticsInputBuilder input = new GetAllNodeConnectorsStatisticsInputBuilder();
-
-        input.setNode(targetNode);
-
-        Future<RpcResult<GetAllNodeConnectorsStatisticsOutput>> response =
-                portStatsService.getAllNodeConnectorsStatistics(input.build());
-        this.multipartMessageManager.addTxIdToRequestTypeEntry(getNodeId(targetNode), response.get().getResult().getTransactionId()
-                , StatsRequestType.ALL_PORT);
-
-    }
-
-    public void sendAllGroupStatisticsRequest(NodeRef targetNode) throws InterruptedException, ExecutionException{
-
-        final GetAllGroupStatisticsInputBuilder input = new GetAllGroupStatisticsInputBuilder();
-
-        input.setNode(targetNode);
-
-        Future<RpcResult<GetAllGroupStatisticsOutput>> response =
-                groupStatsService.getAllGroupStatistics(input.build());
-
-        this.multipartMessageManager.addTxIdToRequestTypeEntry(getNodeId(targetNode), response.get().getResult().getTransactionId()
-                , StatsRequestType.ALL_GROUP);
-
-    }
-
-    public void sendGroupDescriptionRequest(NodeRef targetNode) throws InterruptedException, ExecutionException{
-        final GetGroupDescriptionInputBuilder input = new GetGroupDescriptionInputBuilder();
-
-        input.setNode(targetNode);
-
-        Future<RpcResult<GetGroupDescriptionOutput>> response =
-                groupStatsService.getGroupDescription(input.build());
-
-        this.multipartMessageManager.addTxIdToRequestTypeEntry(getNodeId(targetNode), response.get().getResult().getTransactionId()
-                , StatsRequestType.GROUP_DESC);
-
-    }
-
-    public void sendAllMeterStatisticsRequest(NodeRef targetNode) throws InterruptedException, ExecutionException{
-
-        GetAllMeterStatisticsInputBuilder input = new GetAllMeterStatisticsInputBuilder();
-
-        input.setNode(targetNode);
-
-        Future<RpcResult<GetAllMeterStatisticsOutput>> response =
-                meterStatsService.getAllMeterStatistics(input.build());
-
-        this.multipartMessageManager.addTxIdToRequestTypeEntry(getNodeId(targetNode), response.get().getResult().getTransactionId()
-                , StatsRequestType.ALL_METER);;
-
-    }
-
-    public void sendMeterConfigStatisticsRequest(NodeRef targetNode) throws InterruptedException, ExecutionException{
-
-        GetAllMeterConfigStatisticsInputBuilder input = new GetAllMeterConfigStatisticsInputBuilder();
-
-        input.setNode(targetNode);
-
-        Future<RpcResult<GetAllMeterConfigStatisticsOutput>> response =
-                meterStatsService.getAllMeterConfigStatistics(input.build());
-
-        this.multipartMessageManager.addTxIdToRequestTypeEntry(getNodeId(targetNode), response.get().getResult().getTransactionId()
-                , StatsRequestType.METER_CONFIG);;
-
-    }
-
-    public void sendAllQueueStatsFromAllNodeConnector(NodeRef targetNode) throws InterruptedException, ExecutionException {
-        GetAllQueuesStatisticsFromAllPortsInputBuilder input = new GetAllQueuesStatisticsFromAllPortsInputBuilder();
-
-        input.setNode(targetNode);
-
-        Future<RpcResult<GetAllQueuesStatisticsFromAllPortsOutput>> response =
-                queueStatsService.getAllQueuesStatisticsFromAllPorts(input.build());
-
-        this.multipartMessageManager.addTxIdToRequestTypeEntry(getNodeId(targetNode), response.get().getResult().getTransactionId()
-                , StatsRequestType.ALL_QUEUE_STATS);;
-
-    }
-
-    public void sendQueueStatsFromGivenNodeConnector(NodeRef targetNode,NodeConnectorId nodeConnectorId, QueueId queueId) throws InterruptedException, ExecutionException {
-        GetQueueStatisticsFromGivenPortInputBuilder input = new GetQueueStatisticsFromGivenPortInputBuilder();
-
-        input.setNode(targetNode);
-        input.setNodeConnectorId(nodeConnectorId);
-        input.setQueueId(queueId);
-        Future<RpcResult<GetQueueStatisticsFromGivenPortOutput>> response =
-                queueStatsService.getQueueStatisticsFromGivenPort(input.build());
-
-        this.multipartMessageManager.addTxIdToRequestTypeEntry(getNodeId(targetNode), response.get().getResult().getTransactionId()
-                , StatsRequestType.ALL_QUEUE_STATS);;
-
-    }
-
     /**
      * Get the handler for a particular node.
      *
@@ -457,63 +109,61 @@ public class StatisticsProvider implements AutoCloseable {
      */
     public final NodeStatisticsHandler getStatisticsHandler(final NodeId nodeId) {
         Preconditions.checkNotNull(nodeId);
-        NodeStatisticsHandler ager = statisticsCache.get(nodeId);
-        if (ager == null) {
-            ager = new NodeStatisticsHandler(this, new NodeKey(nodeId));
-            statisticsCache.put(nodeId, ager);
-        }
-
-        return ager;
-    }
-
-    private List<Node> getAllConnectedNodes(){
-        Nodes nodes = (Nodes) dps.readOperationalData(nodesIdentifier);
-        if(nodes == null)
-            return null;
-
-        spLogger.debug("Number of connected nodes : {}",nodes.getNode().size());
-        return nodes.getNode();
-    }
-
-    private List<Short> getTablesFromNode(NodeKey nodeKey){
-        InstanceIdentifier<FlowCapableNode> nodesIdentifier = InstanceIdentifier.builder(Nodes.class).child(Node.class,nodeKey).augmentation(FlowCapableNode.class).toInstance();
-
-        FlowCapableNode node = (FlowCapableNode)dps.readOperationalData(nodesIdentifier);
-        List<Short> tablesId = new ArrayList<Short>();
-        if(node != null && node.getTable()!=null){
-            spLogger.debug("Number of tables {} supported by node {}",node.getTable().size(),nodeKey);
-            for(Table table: node.getTable()){
-                tablesId.add(table.getId());
-            }
+        NodeStatisticsHandler handler = handlers.get(nodeId);
+        if (handler == null) {
+            spLogger.info("Attempted to get non-existing handler for {}", nodeId);
         }
-        return tablesId;
-    }
-
-    @SuppressWarnings("unchecked")
-    private NodeId getNodeId(NodeRef nodeRef){
-        InstanceIdentifier<Node> nodeII = (InstanceIdentifier<Node>) nodeRef.getValue();
-        NodeKey nodeKey = InstanceIdentifier.keyOf(nodeII);
-        return nodeKey.getId();
+        return handler;
     }
 
-    @SuppressWarnings("deprecation")
     @Override
-    public void close(){
-
+    public void close() {
         try {
-            spLogger.info("Statistics Provider stopped.");
             if (this.listenerRegistration != null) {
-
                 this.listenerRegistration.close();
+                this.listenerRegistration = null;
+            }
+            if (this.flowCapableTrackerRegistration != null) {
+                this.flowCapableTrackerRegistration.close();
+                this.flowCapableTrackerRegistration = null;
+            }
+            timer.cancel();
+        } catch (Exception e) {
+            spLogger.warn("Failed to stop Statistics Provider completely", e);
+        } finally {
+            spLogger.info("Statistics Provider stopped.");
+        }
+    }
 
-                this.statisticsRequesterThread.destroy();
-
-                this.statisticsAgerThread.destroy();
+    void startNodeHandlers(final Collection<NodeKey> addedNodes) {
+        for (NodeKey key : addedNodes) {
+            if (handlers.containsKey(key.getId())) {
+                spLogger.warn("Attempted to start already-existing handler for {}, very strange", key.getId());
+                continue;
+            }
 
+            final NodeStatisticsHandler h = new NodeStatisticsHandler(dps, key,
+                    flowStatsService, flowTableStatsService, groupStatsService,
+                    meterStatsService, portStatsService, queueStatsService);
+            final NodeStatisticsHandler old = handlers.putIfAbsent(key.getId(), h);
+            if (old == null) {
+                spLogger.debug("Started node handler for {}", key.getId());
+                h.start(timer);
+            } else {
+                spLogger.debug("Prevented race on handler for {}", key.getId());
             }
-          } catch (Throwable e) {
-            throw Exceptions.sneakyThrow(e);
-          }
+        }
     }
 
+    void stopNodeHandlers(final Collection<NodeKey> removedNodes) {
+        for (NodeKey key : removedNodes) {
+            final NodeStatisticsHandler s = handlers.remove(key.getId());
+            if (s != null) {
+                spLogger.debug("Stopping node handler for {}", key.getId());
+                s.close();
+            } else {
+                spLogger.warn("Attempted to remove non-existing handler for {}, very strange", key.getId());
+            }
+        }
+    }
 }
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateHandler.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateHandler.java
deleted file mode 100644 (file)
index acf182a..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright IBM Corporation, 2013.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.statistics.manager;
-
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
-import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
-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.meters.Meter;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupDescStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics;
-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.node.NodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterConfigStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsData;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Following are two main responsibilities of the class
- * 1) Listen for the create changes in config data store for tree nodes (Flow,Group,Meter,Queue)
- * and send statistics request to the switch to fetch the statistics
- *
- * 2)Listen for the remove changes in config data store for tree nodes (Flow,Group,Meter,Queue)
- * and remove the relative statistics data from operational data store.
- *
- * @author avishnoi@in.ibm.com
- *
- */
-public class StatisticsUpdateHandler implements DataChangeListener {
-
-    private static final Logger suhLogger = LoggerFactory.getLogger(StatisticsUpdateHandler.class);
-    private final StatisticsProvider statisticsManager;
-
-    public StatisticsUpdateHandler(final StatisticsProvider manager){
-        this.statisticsManager = manager;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
-
-        Map<InstanceIdentifier<?>, DataObject> nodeAdditions = change.getCreatedOperationalData();
-        for (InstanceIdentifier<? extends DataObject> dataObjectInstance : nodeAdditions.keySet()) {
-            DataObject dataObject = nodeAdditions.get(dataObjectInstance);
-            if(dataObject instanceof Node){
-
-                Node node = (Node) dataObject;
-                if(node.getAugmentation(FlowCapableNode.class) != null){
-                    this.statisticsManager.sendStatisticsRequestsToNode(node);
-                }
-            }
-        }
-
-        Map<InstanceIdentifier<?>, DataObject> additions = change.getCreatedConfigurationData();
-        for (InstanceIdentifier<? extends DataObject> dataObjectInstance : additions.keySet()) {
-            DataObject dataObject = additions.get(dataObjectInstance);
-            InstanceIdentifier<Node> nodeII = dataObjectInstance.firstIdentifierOf(Node.class);
-            NodeRef nodeRef = new NodeRef(nodeII);
-            if(dataObject instanceof Flow){
-                Flow flow = (Flow) dataObject;
-                try {
-                    this.statisticsManager.sendFlowStatsFromTableRequest(nodeRef, flow);
-                } catch (InterruptedException | ExecutionException e) {
-                    suhLogger.warn("Following exception occured while sending flow statistics request newly added flow: {}", e);
-                }
-            }
-            if(dataObject instanceof Meter){
-                try {
-                    this.statisticsManager.sendMeterConfigStatisticsRequest(nodeRef);
-                } catch (InterruptedException | ExecutionException e) {
-                    suhLogger.warn("Following exception occured while sending meter statistics request for newly added meter: {}", e);
-                }
-            }
-            if(dataObject instanceof Group){
-                try {
-                    this.statisticsManager.sendGroupDescriptionRequest(nodeRef);
-                } catch (InterruptedException | ExecutionException e) {
-                    suhLogger.warn("Following exception occured while sending group description request for newly added group: {}", e);
-                }
-            }
-            if(dataObject instanceof Queue){
-                Queue queue = (Queue) dataObject;
-                InstanceIdentifier<NodeConnector> nodeConnectorII = dataObjectInstance.firstIdentifierOf(NodeConnector.class);
-                NodeConnectorKey nodeConnectorKey = InstanceIdentifier.keyOf(nodeConnectorII);
-                try {
-                    this.statisticsManager.sendQueueStatsFromGivenNodeConnector(nodeRef, nodeConnectorKey.getId(), queue.getQueueId());
-                } catch (InterruptedException | ExecutionException e) {
-                    suhLogger.warn("Following exception occured while sending queue statistics request for newly added group: {}", e);
-                }
-            }
-        }
-
-        DataModificationTransaction it = this.statisticsManager.startChange();
-        Set<InstanceIdentifier<? extends DataObject>> removals = change.getRemovedConfigurationData();
-        for (InstanceIdentifier<? extends DataObject> dataObjectInstance : removals) {
-            DataObject dataObject = change.getOriginalConfigurationData().get(dataObjectInstance);
-
-            if(dataObject instanceof Flow){
-                InstanceIdentifier<Flow> flowII = (InstanceIdentifier<Flow>)dataObjectInstance;
-                InstanceIdentifier<?> flowAugmentation =
-                        InstanceIdentifier.builder(flowII).augmentation(FlowStatisticsData.class).toInstance();
-                it.removeOperationalData(flowAugmentation);
-            }
-            if(dataObject instanceof Meter){
-                InstanceIdentifier<Meter> meterII = (InstanceIdentifier<Meter>)dataObjectInstance;
-
-                InstanceIdentifier<?> nodeMeterConfigStatsAugmentation =
-                        InstanceIdentifier.builder(meterII).augmentation(NodeMeterConfigStats.class).toInstance();
-                it.removeOperationalData(nodeMeterConfigStatsAugmentation);
-
-                InstanceIdentifier<?> nodeMeterStatisticsAugmentation =
-                        InstanceIdentifier.builder(meterII).augmentation(NodeMeterStatistics.class).toInstance();
-                it.removeOperationalData(nodeMeterStatisticsAugmentation);
-            }
-
-            if(dataObject instanceof Group){
-                InstanceIdentifier<Group> groupII = (InstanceIdentifier<Group>)dataObjectInstance;
-
-                InstanceIdentifier<?> nodeGroupDescStatsAugmentation =
-                        InstanceIdentifier.builder(groupII).augmentation(NodeGroupDescStats.class).toInstance();
-                it.removeOperationalData(nodeGroupDescStatsAugmentation);
-
-                InstanceIdentifier<?> nodeGroupStatisticsAugmentation =
-                        InstanceIdentifier.builder(groupII).augmentation(NodeGroupStatistics.class).toInstance();
-                it.removeOperationalData(nodeGroupStatisticsAugmentation);
-            }
-
-            if(dataObject instanceof Queue){
-                InstanceIdentifier<Queue> queueII = (InstanceIdentifier<Queue>)dataObjectInstance;
-
-                InstanceIdentifier<?> nodeConnectorQueueStatisticsDataAugmentation =
-                        InstanceIdentifier.builder(queueII).augmentation(FlowCapableNodeConnectorQueueStatisticsData.class).toInstance();
-                it.removeOperationalData(nodeConnectorQueueStatisticsDataAugmentation);
-            }
-        }
-        it.commit();
-    }
-}
index 53cf2bd5c1337220af34d01d9d87e59fddb8f9f6..590e8ea91a0349345124b3aa552942d036ca6352 100644 (file)
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-api</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
             <artifactId>model-flow-service</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>    
            <dependency>
              <groupId>org.opendaylight.controller.model</groupId>
              <artifactId>model-flow-base</artifactId>
-             <version>1.1-SNAPSHOT</version>
            </dependency>
           <dependency>
              <groupId>org.opendaylight.controller.model</groupId>
              <artifactId>model-flow-management</artifactId>
-             <version>1.1-SNAPSHOT</version>
            </dependency>    
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
             <artifactId>model-inventory</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.eclipse.xtend</groupId>
@@ -57,7 +52,6 @@
          <dependency>
                <groupId>equinoxSDK381</groupId>
                <artifactId>org.eclipse.osgi</artifactId>
-               <version>3.8.1.v20120830-144521</version>
              </dependency>
              <dependency>
             <groupId>commons-lang</groupId>
           <dependency>
                    <groupId>commons-codec</groupId>
                    <artifactId>commons-codec</artifactId>
-                   <version>1.7</version>
                  </dependency>
     <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal</artifactId>
-            <version>0.7.1-SNAPSHOT</version>
         </dependency>
              
     </dependencies>
index 3c676c8d8f1413eb14b42c7e056037195979a92d..525ab9e4fe1790ac438c73a822a583ad8bb38725 100644 (file)
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-api</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-util</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
             <artifactId>model-flow-service</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
             <artifactId>model-inventory</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
index e319d2cb679260718c9eade75234b9996170007c..2d89bbc55c03d59d3ad7e648426df91562fc6fde 100644 (file)
@@ -49,7 +49,7 @@ public class ConfigPersisterNotificationHandler implements Closeable {
     private static void registerAsJMXListener(MBeanServerConnection mBeanServerConnection, ConfigPersisterNotificationListener listener) {
         logger.trace("Called registerAsJMXListener");
         try {
-            mBeanServerConnection.addNotificationListener(DefaultCommitOperationMXBean.objectName, listener, null, null);
+            mBeanServerConnection.addNotificationListener(DefaultCommitOperationMXBean.OBJECT_NAME, listener, null, null);
         } catch (InstanceNotFoundException | IOException e) {
             throw new RuntimeException("Cannot register as JMX listener to netconf", e);
         }
@@ -58,7 +58,7 @@ public class ConfigPersisterNotificationHandler implements Closeable {
     @Override
     public synchronized void close() {
         // unregister from JMX
-        ObjectName on = DefaultCommitOperationMXBean.objectName;
+        ObjectName on = DefaultCommitOperationMXBean.OBJECT_NAME;
         try {
             if (mBeanServerConnection.isRegistered(on)) {
                 mBeanServerConnection.removeNotificationListener(on, listener);
index bd75c27dd6abf36c794f85459accdcaa2bb3b35d..f85d9b9f304f8cf8de63e90f185d63fb64e82811 100644 (file)
@@ -22,13 +22,13 @@ public abstract class AbstractNetconfSession<S extends NetconfSession, L extends
     private final long sessionId;
     private boolean up = false;
 
-    protected final Channel channel;
+    private final Channel channel;
 
     protected AbstractNetconfSession(L sessionListener, Channel channel, long sessionId) {
         this.sessionListener = sessionListener;
         this.channel = channel;
         this.sessionId = sessionId;
-        logger.debug("Session {} created", toString());
+        logger.debug("Session {} created", sessionId);
     }
 
     protected abstract S thisInstance();
index 1ec46c8d6f1e58912e76c57bd4674f7d70e8c37c..be3040802cdfdc4ab7eaf3ac266914e936de82b0 100644 (file)
@@ -9,7 +9,7 @@
 package org.opendaylight.controller.netconf.api;
 
 public class NetconfSessionPreferences {
-    protected final NetconfMessage helloMessage;
+    private final NetconfMessage helloMessage;
 
     public NetconfSessionPreferences(final NetconfMessage helloMessage) {
         this.helloMessage = helloMessage;
index 0c4174000fe80dc231efd9aeb5702a2832834580..74cd4a4e05a5186cf6c4df5543b03a106c61fa3e 100644 (file)
@@ -17,12 +17,12 @@ public class CommitJMXNotification extends NetconfJMXNotification {
 
     private final Element configSnapshot;
 
-    private static final String afterCommitMessageTemplate = "Commit successful: %s";
+    private static final String AFTER_COMMIT_MESSAGE_TEMPLATE = "Commit successful: %s";
     private final Set<String> capabilities;
 
     CommitJMXNotification(NotificationBroadcasterSupport source, String message, Element cfgSnapshot,
             Set<String> capabilities) {
-        super(TransactionProviderJMXNotificationType.commit, source, String.format(afterCommitMessageTemplate, message));
+        super(TransactionProviderJMXNotificationType.commit, source, String.format(AFTER_COMMIT_MESSAGE_TEMPLATE, message));
         this.configSnapshot = cfgSnapshot;
         this.capabilities = capabilities;
     }
index a170d2905fee69135ab904525d266aa638d61331..e45d3c38a209ee26f0ba2b92e63637ad155f6c01 100644 (file)
@@ -14,7 +14,7 @@ import javax.management.ObjectName;
 
 public interface DefaultCommitOperationMXBean {
 
-    static String typeName = "NetconfNotificationProvider";
-    public static ObjectName objectName = ObjectNameUtil.createONWithDomainAndType(typeName);
+    String TYPE_NAME = "NetconfNotificationProvider";
+    ObjectName OBJECT_NAME = ObjectNameUtil.createONWithDomainAndType(TYPE_NAME);
 
 }
index 693fc1378390abcd89c0f582e75a055d10580c98..4461054437ce61ef47fd2eea76a9b23ae15b5ef3 100644 (file)
@@ -31,7 +31,7 @@ public class DefaultCommitNotificationProducer extends NotificationBroadcasterSu
 
     private final MBeanServer mbeanServer;
 
-    private final ObjectName on = DefaultCommitOperationMXBean.objectName;
+    private final ObjectName on = DefaultCommitOperationMXBean.OBJECT_NAME;
 
     public DefaultCommitNotificationProducer(MBeanServer mBeanServer) {
         this.mbeanServer = mBeanServer;
index 1b4dfff42baeb0423597af3c90168592db146724..f8024922cfc5a5ba021e97b519493ae80a02c4d2 100644 (file)
@@ -49,7 +49,7 @@ public class NetconfServerSessionNegotiator extends
 
         logger.debug("Additional header from hello parsed as {} from {}", parsedHeader, additionalHeader);
 
-        return new NetconfServerSession(sessionListener, channel, sessionPreferences.getSessionId(), parsedHeader);
+        return new NetconfServerSession(sessionListener, channel, getSessionPreferences().getSessionId(), parsedHeader);
     }
 
    }
index 95f7353600fcfb67a5626a496d76642613c4bb5a..b8dc9550c7f1fff5b4a544d3be0bc68f07f6d235 100644 (file)
@@ -26,6 +26,7 @@ import java.lang.management.ManagementFactory;
 import java.net.InetSocketAddress;
 import java.util.Dictionary;
 import java.util.Hashtable;
+import java.util.concurrent.TimeUnit;
 
 public class NetconfImplActivator implements BundleActivator {
 
@@ -88,7 +89,7 @@ public class NetconfImplActivator implements BundleActivator {
         logger.info("Shutting down netconf because YangStoreService service was removed");
 
         commitNot.close();
-        eventLoopGroup.shutdownGracefully();
+        eventLoopGroup.shutdownGracefully(0, 1, TimeUnit.SECONDS);
         timer.stop();
 
         regMonitoring.unregister();
index aa3c5d4d9ba539167dd08aa3117dc45fbb7cc9b8..959e2ff144810c2017131e8041229e86b1cabd64 100644 (file)
@@ -8,33 +8,24 @@
 
 package org.opendaylight.controller.netconf.impl;
 
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.controller.netconf.util.messages.NetconfMessageHeader;
-
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 
-public class MessageHeaderTest {
-
-    private NetconfMessageHeader header = null;
-
-    @Before
-    public void setUp() {
-        this.header = new NetconfMessageHeader();
-    }
+import org.junit.Test;
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageHeader;
 
+public class MessageHeaderTest {
     @Test
     public void testFromBytes() {
         final byte[] raw = new byte[] { (byte) 0x0a, (byte) 0x23, (byte) 0x35, (byte) 0x38, (byte) 0x0a };
-        this.header.fromBytes(raw);
-        assertEquals(58, this.header.getLength());
+        NetconfMessageHeader header = NetconfMessageHeader.fromBytes(raw);
+        assertEquals(58, header.getLength());
     }
 
     @Test
     public void testToBytes() {
-        this.header.setLength(123);
+        NetconfMessageHeader header = new NetconfMessageHeader(123);
         assertArrayEquals(new byte[] { (byte) 0x0a, (byte) 0x23, (byte) 0x31, (byte) 0x32, (byte) 0x33, (byte) 0x0a },
-                this.header.toBytes());
+                header.toBytes());
     }
 }
index 85bccba14ff01da5d559ad83ff6080e0ef5b6b42..d1c0b066d7a0a5ef15399a0544deb380177b0b01 100644 (file)
@@ -22,9 +22,10 @@ import java.util.Queue;
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.util.handler.ChunkedFramingMechanismEncoder;
 import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageAggregator;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageChunkDecoder;
+import org.opendaylight.controller.netconf.util.handler.NetconfChunkAggregator;
+import org.opendaylight.controller.netconf.util.handler.NetconfEOMAggregator;
 import org.opendaylight.controller.netconf.util.handler.NetconfMessageToXMLEncoder;
 import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
 import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
@@ -47,7 +48,7 @@ public class MessageParserTest {
                 FramingMechanismHandlerFactory.createHandler(FramingMechanism.CHUNK),
                 new NetconfMessageToXMLEncoder(),
 
-                new NetconfMessageAggregator(FramingMechanism.CHUNK), new NetconfMessageChunkDecoder(),
+                new NetconfChunkAggregator(),
                 new NetconfXMLToMessageDecoder());
 
         testChunkChannel.writeOutbound(this.msg);
@@ -59,26 +60,25 @@ public class MessageParserTest {
         enc.encode(null, msg, out);
         int msgLength = out.readableBytes();
 
-        int chunkCount = msgLength / NetconfMessageConstants.MAX_CHUNK_SIZE;
-        if ((msgLength % NetconfMessageConstants.MAX_CHUNK_SIZE) != 0) {
+        int chunkCount = msgLength / ChunkedFramingMechanismEncoder.DEFAULT_CHUNK_SIZE;
+        if ((msgLength % ChunkedFramingMechanismEncoder.DEFAULT_CHUNK_SIZE) != 0) {
             chunkCount++;
         }
         for (int i = 1; i <= chunkCount; i++) {
             ByteBuf recievedOutbound = (ByteBuf) messages.poll();
-            int exptHeaderLength = NetconfMessageConstants.MAX_CHUNK_SIZE;
+            int exptHeaderLength = ChunkedFramingMechanismEncoder.DEFAULT_CHUNK_SIZE;
             if (i == chunkCount) {
-                exptHeaderLength = msgLength - (NetconfMessageConstants.MAX_CHUNK_SIZE * (i - 1));
-                byte[] eom = new byte[NetconfMessageConstants.endOfChunk.length];
-                recievedOutbound.getBytes(recievedOutbound.readableBytes() - NetconfMessageConstants.endOfChunk.length,
+                exptHeaderLength = msgLength - (ChunkedFramingMechanismEncoder.DEFAULT_CHUNK_SIZE * (i - 1));
+                byte[] eom = new byte[NetconfMessageConstants.END_OF_CHUNK.length];
+                recievedOutbound.getBytes(recievedOutbound.readableBytes() - NetconfMessageConstants.END_OF_CHUNK.length,
                         eom);
-                assertArrayEquals(NetconfMessageConstants.endOfChunk, eom);
+                assertArrayEquals(NetconfMessageConstants.END_OF_CHUNK, eom);
             }
 
             byte[] header = new byte[String.valueOf(exptHeaderLength).length()
                     + NetconfMessageConstants.MIN_HEADER_LENGTH - 1];
             recievedOutbound.getBytes(0, header);
-            NetconfMessageHeader messageHeader = new NetconfMessageHeader();
-            messageHeader.fromBytes(header);
+            NetconfMessageHeader messageHeader = NetconfMessageHeader.fromBytes(header);
             assertEquals(exptHeaderLength, messageHeader.getLength());
 
             testChunkChannel.writeInbound(recievedOutbound);
@@ -94,15 +94,14 @@ public class MessageParserTest {
     public void testEOMFramingMechanismOnPipeline() throws Exception {
         EmbeddedChannel testChunkChannel = new EmbeddedChannel(
                 FramingMechanismHandlerFactory.createHandler(FramingMechanism.EOM),
-                new NetconfMessageToXMLEncoder(), new NetconfMessageAggregator(
-                        FramingMechanism.EOM), new NetconfXMLToMessageDecoder());
+                new NetconfMessageToXMLEncoder(), new NetconfEOMAggregator(), new NetconfXMLToMessageDecoder());
 
         testChunkChannel.writeOutbound(this.msg);
         ByteBuf recievedOutbound = (ByteBuf) testChunkChannel.readOutbound();
 
-        byte[] eom = new byte[NetconfMessageConstants.endOfMessage.length];
-        recievedOutbound.getBytes(recievedOutbound.readableBytes() - NetconfMessageConstants.endOfMessage.length, eom);
-        assertArrayEquals(NetconfMessageConstants.endOfMessage, eom);
+        byte[] eom = new byte[NetconfMessageConstants.END_OF_MESSAGE.length];
+        recievedOutbound.getBytes(recievedOutbound.readableBytes() - NetconfMessageConstants.END_OF_MESSAGE.length, eom);
+        assertArrayEquals(NetconfMessageConstants.END_OF_MESSAGE, eom);
 
         testChunkChannel.writeInbound(recievedOutbound);
         NetconfMessage receivedMessage = (NetconfMessage) testChunkChannel.readInbound();
index 0037981a3e0103f95cd83a945af5aa83c11dd477..1035c9f9fe3afd9c8a0bda0e3b3709ff2800df1d 100644 (file)
@@ -7,9 +7,27 @@
  */
 package org.opendaylight.controller.netconf.it;
 
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
+import static junit.framework.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import io.netty.channel.ChannelFuture;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetSocketAddress;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+
 import org.apache.commons.lang3.StringUtils;
 import org.junit.After;
 import org.junit.Assert;
@@ -44,33 +62,13 @@ import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOper
 import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.w3c.dom.Element;
 
-import javax.management.InstanceNotFoundException;
-import javax.management.Notification;
-import javax.management.NotificationListener;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.InetSocketAddress;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-import static junit.framework.Assert.assertEquals;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 
 public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest {
 
-    private static final Logger logger =  LoggerFactory.getLogger(NetconfConfigPersisterITTest.class);
-
     private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023);
 
 
@@ -163,7 +161,7 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest {
 
     private VerifyingNotificationListener createCommitNotificationListener() throws InstanceNotFoundException {
         VerifyingNotificationListener listener = new VerifyingNotificationListener();
-        platformMBeanServer.addNotificationListener(DefaultCommitNotificationProducer.objectName, listener, null, null);
+        platformMBeanServer.addNotificationListener(DefaultCommitNotificationProducer.OBJECT_NAME, listener, null, null);
         return listener;
     }
 
@@ -230,7 +228,7 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest {
         public VerifyingPersister() throws IOException {
             Persister mockedAggregator = mock(Persister.class);
 
-            doAnswer(new Answer() {
+            doAnswer(new Answer<Object>() {
                 @Override
                 public Object answer(InvocationOnMock invocation) throws Throwable {
                     ConfigSnapshotHolder configSnapshot = (ConfigSnapshotHolder) invocation.getArguments()[0];
index be2c32e34fd8816b28ed1a844437b5d0c133ea56..7a840be02af697f1cd73dad423c8b610b2a664da 100644 (file)
@@ -7,11 +7,23 @@
  */
 package org.opendaylight.controller.netconf.it;
 
-import com.google.common.base.Charsets;
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import io.netty.channel.ChannelFuture;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
 import junit.framework.Assert;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.matchers.JUnitMatchers;
@@ -41,19 +53,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
+import com.google.common.base.Charsets;
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
 
 public class NetconfMonitoringITTest extends AbstractNetconfConfigTest {
 
@@ -162,6 +164,8 @@ public class NetconfMonitoringITTest extends AbstractNetconfConfigTest {
             }
         }
 
+        sock.close();
+
         org.junit.Assert.assertThat(responseBuilder.toString(), JUnitMatchers.containsString("<capability>urn:ietf:params:netconf:capability:candidate:1.0</capability>"));
         org.junit.Assert.assertThat(responseBuilder.toString(), JUnitMatchers.containsString("<username>tomas</username>"));
     }
index 3a9d3bacc23b49bf7475f03a070c21e387eb4cc1..200cd344a6617b995065b652efca10a6a2a35791 100644 (file)
@@ -9,10 +9,14 @@ package org.opendaylight.controller.netconf.monitoring;
 
 public class MonitoringConstants {
 
-    public static final String NAMESPACE = "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring";
     public static final String MODULE_NAME = "ietf-netconf-monitoring";
     public static final String MODULE_REVISION = "2010-10-04";
 
+    public static final String NAMESPACE = "urn:ietf:params:xml:ns:yang:" + MODULE_NAME;
+    public static final String EXTENSION_NAMESPACE = NAMESPACE + "-extension";
+
+    public static final String EXTENSION_NAMESPACE_PREFIX = "ncme";
+
     public static final String URI = String.format("%s?module=%s&revision=%s", NAMESPACE, MODULE_NAME, MODULE_REVISION);
 
     public static final String NETCONF_MONITORING_XML_ROOT_ELEMENT = "netconf-state";
index 55aee72fda98af82b894a8f6be83a1d339d904ac..8685ef72208b15fd77845b7486724846d67780a4 100644 (file)
@@ -10,6 +10,8 @@ package org.opendaylight.controller.netconf.monitoring.xml.model;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlTransient;
 
+import com.google.common.base.Joiner;
+import org.opendaylight.controller.netconf.monitoring.MonitoringConstants;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.Session1;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions.Session;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -69,13 +71,18 @@ final class MonitoringSession {
     public String getTransport() {
         try {
             QName qName = (QName) managementSession.getTransport().getField("QNAME").get(null);
-            return qName.getLocalName();
+            // Add extension prefix if transport type is from extension yang module
+            if (qName.getNamespace().toString().equals(MonitoringConstants.EXTENSION_NAMESPACE)) {
+                return Joiner.on(':').join(MonitoringConstants.EXTENSION_NAMESPACE_PREFIX, qName.getLocalName());
+            } else {
+                return qName.getLocalName();
+            }
         } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
             throw new IllegalArgumentException("Unknown transport type " + managementSession.getTransport(), e);
         }
     }
 
-    @XmlElement(name= "session-identifier")
+    @XmlElement(name= "session-identifier", namespace = MonitoringConstants.EXTENSION_NAMESPACE)
     public String getSessionType() {
         return managementSession.getAugmentation(Session1.class).getSessionIdentifier();
     }
index 85da5975d1f22caaf4485ebea88484e9ad1f242c..a96c3a3836e55309751011af56bcea32f39d069a 100644 (file)
@@ -7,14 +7,16 @@
  */
 @XmlSchema(
         elementFormDefault = XmlNsForm.QUALIFIED,
-//        xmlns = {
-//                @XmlNs(namespaceURI = MonitoringConstants.NAMESPACE, prefix = "")
-//        }
+        xmlns = {
+                @XmlNs(namespaceURI = MonitoringConstants.EXTENSION_NAMESPACE, prefix = MonitoringConstants.EXTENSION_NAMESPACE_PREFIX),
+                @XmlNs(namespaceURI = MonitoringConstants.NAMESPACE, prefix = "")
+        },
         namespace = MonitoringConstants.NAMESPACE
 )
 package org.opendaylight.controller.netconf.monitoring.xml.model;
 
 import org.opendaylight.controller.netconf.monitoring.MonitoringConstants;
 
+import javax.xml.bind.annotation.XmlNs;
 import javax.xml.bind.annotation.XmlNsForm;
 import javax.xml.bind.annotation.XmlSchema;
\ No newline at end of file
index d4462f85d99e2f3cf267b3e7cffca82670b9d0a3..02129574da40ec274a22b077614c38653a14770d 100644 (file)
@@ -13,8 +13,10 @@ import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringServi
 import org.opendaylight.controller.netconf.monitoring.xml.model.NetconfState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.DomainName;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Host;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.NetconfTcp;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.Session1;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfSsh;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.Transport;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.SchemasBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Sessions;
@@ -39,7 +41,7 @@ public class JaxBSerializerTest {
 
             @Override
             public Sessions getSessions() {
-                return new SessionsBuilder().setSession(Lists.newArrayList(getMockSession())).build();
+                return new SessionsBuilder().setSession(Lists.newArrayList(getMockSession(NetconfTcp.class), getMockSession(NetconfSsh.class))).build();
             }
 
             @Override
@@ -51,7 +53,7 @@ public class JaxBSerializerTest {
         Element xml = new JaxBSerializer().toXml(model);
     }
 
-    private Session getMockSession() {
+    private Session getMockSession(Class<? extends Transport> transportType) {
         Session mocked = mock(Session.class);
         Session1 mockedSession1 = mock(Session1.class);
         doReturn("client").when(mockedSession1).getSessionIdentifier();
@@ -62,7 +64,7 @@ public class JaxBSerializerTest {
         doReturn(new ZeroBasedCounter32(0L)).when(mocked).getInRpcs();
         doReturn(new ZeroBasedCounter32(0L)).when(mocked).getOutNotifications();
         doReturn(new ZeroBasedCounter32(0L)).when(mocked).getOutRpcErrors();
-        doReturn(NetconfSsh.class).when(mocked).getTransport();
+        doReturn(transportType).when(mocked).getTransport();
         doReturn("username").when(mocked).getUsername();
         doReturn(mockedSession1).when(mocked).getAugmentation(Session1.class);
         return mocked;
index 3b4125b386f46f12751ea9e9ce5db6de9679b002..efad2148e979ae697e0255833ec442928e73494e 100644 (file)
@@ -35,7 +35,6 @@
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>usermanager</artifactId>
-            <version>0.4.2-SNAPSHOT</version>
         </dependency>
     </dependencies>
 
index d904ad7f269a344600aa04bd2279b9590a0f91d7..3d5318073d8c0e7cc203fd80fa63b6a05ea71e3e 100644 (file)
@@ -30,14 +30,14 @@ public class AuthProvider implements AuthProviderInterface {
 
     public AuthProvider(IUserManager ium,InputStream privateKeyFileInputStream) throws Exception {
 
-        this.um = ium;
-        if (this.um  == null){
+        AuthProvider.um = ium;
+        if (AuthProvider.um  == null){
             throw new Exception("No usermanager service available.");
         }
 
         List<String> roles = new ArrayList<String>(1);
         roles.add(UserLevel.SYSTEMADMIN.toString());
-        this.um.addLocalUser(new UserConfig(DEFAULT_USER, DEFAULT_PASSWORD, roles));
+        AuthProvider.um.addLocalUser(new UserConfig(DEFAULT_USER, DEFAULT_PASSWORD, roles));
 
         try {
             PEM = IOUtils.toString(privateKeyFileInputStream);
@@ -48,10 +48,10 @@ public class AuthProvider implements AuthProviderInterface {
     }
     @Override
     public boolean authenticated(String username, String password)  throws Exception {
-        if (this.um  == null){
+        if (AuthProvider.um  == null){
             throw new Exception("No usermanager service available.");
         }
-        AuthResultEnum authResult = this.um.authenticate(username,password);
+        AuthResultEnum authResult = AuthProvider.um.authenticate(username,password);
         if (authResult.equals(AuthResultEnum.AUTH_ACCEPT) || authResult.equals(AuthResultEnum.AUTH_ACCEPT_LOC)){
             return true;
         }
@@ -69,12 +69,12 @@ public class AuthProvider implements AuthProviderInterface {
 
     @Override
     public void removeUserManagerService() {
-        this.um = null;
+        AuthProvider.um = null;
     }
 
     @Override
     public void addUserManagerService(IUserManager userManagerService) {
-        this.um = userManagerService;
+        AuthProvider.um = userManagerService;
     }
 
 
index b9c9c174dcb3fd10a626c080cca5d75479c3bd62..c53a625ad044b69cf6d5f52328e00d9080ee724c 100644 (file)
@@ -7,25 +7,27 @@
  */
 package org.opendaylight.controller.netconf.ssh.threads;
 
-import ch.ethz.ssh2.ServerConnection;
-import ch.ethz.ssh2.ServerSession;
 import java.io.InputStream;
 import java.io.OutputStream;
+
 import javax.annotation.concurrent.ThreadSafe;
+
 import org.apache.commons.io.IOUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import ch.ethz.ssh2.ServerConnection;
+import ch.ethz.ssh2.ServerSession;
+
 @ThreadSafe
 public class IOThread extends Thread {
 
     private static final Logger logger =  LoggerFactory.getLogger(IOThread.class);
 
-    private InputStream inputStream;
-    private OutputStream outputStream;
-    private String id;
-    private ServerSession servSession;
-    private ServerConnection servconnection;
+    private final InputStream inputStream;
+    private final OutputStream outputStream;
+    private final ServerSession servSession;
+    private final ServerConnection servconnection;
     private String customHeader;
 
 
@@ -37,6 +39,7 @@ public class IOThread extends Thread {
         super.setName(id);
         logger.trace("IOThread {} created", super.getName());
     }
+
     public IOThread (InputStream is, OutputStream os, String id,ServerSession ss, ServerConnection conn,String header){
         this.inputStream = is;
         this.outputStream = os;
@@ -53,7 +56,7 @@ public class IOThread extends Thread {
         try {
             if (this.customHeader!=null && !this.customHeader.equals("")){
                 this.outputStream.write(this.customHeader.getBytes());
-                logger.trace("adding  {} header", this.customHeader);
+                logger.trace("adding {} header", this.customHeader);
             }
             IOUtils.copy(this.inputStream, this.outputStream);
         } catch (Exception e) {
index d1b5213f6e07c0e6d9ef955963efa6d6d8b5e0a9..204bf1d13194800e8a9347e97e97c2959ce9417f 100644 (file)
@@ -8,6 +8,16 @@
 package org.opendaylight.controller.netconf.ssh.threads;
 
 
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import ch.ethz.ssh2.AuthenticationResult;
 import ch.ethz.ssh2.PtySettings;
 import ch.ethz.ssh2.ServerAuthenticationCallback;
@@ -16,25 +26,15 @@ import ch.ethz.ssh2.ServerConnectionCallback;
 import ch.ethz.ssh2.ServerSession;
 import ch.ethz.ssh2.ServerSessionCallback;
 import ch.ethz.ssh2.SimpleServerSessionCallback;
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import javax.annotation.concurrent.ThreadSafe;
-import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 @ThreadSafe
-public class SocketThread implements Runnable, ServerAuthenticationCallback, ServerConnectionCallback
-{
-
-    private Socket socket;
-    private static final String USER = "netconf";
-    private static final String PASSWORD = "netconf";
-    private InetSocketAddress clientAddress;
+public class SocketThread implements Runnable, ServerAuthenticationCallback, ServerConnectionCallback {
     private static final Logger logger =  LoggerFactory.getLogger(SocketThread.class);
+
+    private final Socket socket;
+    private final InetSocketAddress clientAddress;
     private ServerConnection conn = null;
-    private long sessionId;
+    private final long sessionId;
     private String currentUser;
     private final String remoteAddressWithPort;
     private final AuthProvider authProvider;
@@ -77,6 +77,7 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser
             logger.error("SocketThread error ",e);
         }
     }
+    @Override
     public ServerSessionCallback acceptSession(final ServerSession session)
     {
         SimpleServerSessionCallback cb = new SimpleServerSessionCallback()
@@ -85,6 +86,7 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser
             public Runnable requestSubsystem(final ServerSession ss, final String subsystem) throws IOException
             {
                 return new Runnable(){
+                    @Override
                     public void run()
                     {
                         if (subsystem.equals("netconf")){
@@ -145,6 +147,7 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser
             {
                 return new Runnable()
                 {
+                    @Override
                     public void run()
                     {
                         //noop
@@ -157,6 +160,7 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser
             {
                 return new Runnable()
                 {
+                    @Override
                     public void run()
                     {
                         //noop
@@ -168,22 +172,26 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser
         return cb;
     }
 
+    @Override
     public String initAuthentication(ServerConnection sc)
     {
         logger.trace("Established connection with host {}",remoteAddressWithPort);
         return "Established connection with host "+remoteAddressWithPort+"\r\n";
     }
 
+    @Override
     public String[] getRemainingAuthMethods(ServerConnection sc)
     {
         return new String[] { ServerAuthenticationCallback.METHOD_PASSWORD };
     }
 
+    @Override
     public AuthenticationResult authenticateWithNone(ServerConnection sc, String username)
     {
         return AuthenticationResult.FAILURE;
     }
 
+    @Override
     public AuthenticationResult authenticateWithPassword(ServerConnection sc, String username, String password)
     {
 
@@ -199,6 +207,7 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser
         return AuthenticationResult.FAILURE;
     }
 
+    @Override
     public AuthenticationResult authenticateWithPublicKey(ServerConnection sc, String username, String algorithm,
             byte[] publickey, byte[] signature)
     {
index 4a3a650ecd9436505e566b2085d4881603f665cf..6628310c970212a0d4f5fa4079ad8356225ed35e 100644 (file)
@@ -30,8 +30,8 @@ public class StubUserManager implements IUserManager{
     private static String password;
 
     public StubUserManager(String user, String password){
-        this.user = user;
-        this.password = password;
+        StubUserManager.user = user;
+        StubUserManager.password = password;
     }
     @Override
     public List<String> getUserRoles(String userName) {
@@ -40,7 +40,7 @@ public class StubUserManager implements IUserManager{
 
     @Override
     public AuthResultEnum authenticate(String username, String password) {
-        if (this.user.equals(username) && this.password.equals(password)){
+        if (StubUserManager.user.equals(username) && StubUserManager.password.equals(password)){
             return AuthResultEnum.AUTH_ACCEPT_LOC;
         }
         return AuthResultEnum.AUTH_REJECT_LOC;
index 0e06ab372f26a6761498fb76817a2020df74e839..e5bab5633ba023f1b5d78522007b4d7e937c06de 100644 (file)
@@ -45,7 +45,6 @@
         <dependency>
             <groupId>io.netty</groupId>
             <artifactId>netty-handler</artifactId>
-            <version>${netconf.netty.version}</version>
         </dependency>
         <!--dependency>
             <groupId>com.siemens.ct.exi</groupId>
index 0910d9403ad98af67427d9dc818e1ddcff216878..48a45845a4a6fe7f57a722bc5678d8fc8447b54d 100644 (file)
@@ -13,8 +13,8 @@ import io.netty.util.concurrent.Promise;
 
 import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
+import org.opendaylight.controller.netconf.util.handler.NetconfEOMAggregator;
 import org.opendaylight.controller.netconf.util.handler.NetconfHelloMessageToXMLEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageAggregator;
 import org.opendaylight.controller.netconf.util.handler.NetconfXMLToHelloMessageDecoder;
 import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
 
@@ -27,7 +27,7 @@ public abstract class AbstractChannelInitializer<S extends NetconfSession> {
     public static final String NETCONF_SESSION_NEGOTIATOR = "negotiator";
 
     public void initialize(SocketChannel ch, Promise<S> promise) {
-        ch.pipeline().addLast(NETCONF_MESSAGE_AGGREGATOR, new NetconfMessageAggregator(FramingMechanism.EOM));
+        ch.pipeline().addLast(NETCONF_MESSAGE_AGGREGATOR, new NetconfEOMAggregator());
         initializeMessageDecoder(ch);
         ch.pipeline().addLast(NETCONF_MESSAGE_FRAME_ENCODER, FramingMechanismHandlerFactory.createHandler(FramingMechanism.EOM));
         initializeMessageEncoder(ch);
index 9986b82bd8d6902a084e77a1a11a6421125ccb17..7f2d8c30f045fb6830458aa7fd461cc7885e8349 100644 (file)
@@ -8,19 +8,30 @@
 
 package org.opendaylight.controller.netconf.util;
 
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.ssl.SslHandler;
+import io.netty.util.Timeout;
+import io.netty.util.Timer;
+import io.netty.util.TimerTask;
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.GenericFutureListener;
+import io.netty.util.concurrent.Promise;
+
 import java.util.concurrent.TimeUnit;
 
+import io.netty.channel.ChannelInboundHandlerAdapter;
 import org.opendaylight.controller.netconf.api.AbstractNetconfSession;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.api.NetconfSessionListener;
 import org.opendaylight.controller.netconf.api.NetconfSessionPreferences;
 import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
-import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageAggregator;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageChunkDecoder;
+import org.opendaylight.controller.netconf.util.handler.NetconfChunkAggregator;
 import org.opendaylight.controller.netconf.util.handler.NetconfMessageToXMLEncoder;
 import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
 import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
+import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.protocol.framework.AbstractSessionNegotiator;
 import org.slf4j.Logger;
@@ -31,25 +42,13 @@ import org.w3c.dom.NodeList;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelHandler;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.ssl.SslHandler;
-import io.netty.util.Timeout;
-import io.netty.util.Timer;
-import io.netty.util.TimerTask;
-import io.netty.util.concurrent.Future;
-import io.netty.util.concurrent.GenericFutureListener;
-import io.netty.util.concurrent.Promise;
-
 public abstract class AbstractNetconfSessionNegotiator<P extends NetconfSessionPreferences, S extends AbstractNetconfSession<S, L>, L extends NetconfSessionListener<S>>
 extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
 
     private static final Logger logger = LoggerFactory.getLogger(AbstractNetconfSessionNegotiator.class);
     public static final String NAME_OF_EXCEPTION_HANDLER = "lastExceptionHandler";
-    public static final String CHUNK_DECODER_CHANNEL_HANDLER_KEY = "chunkDecoder";
 
-    protected final P sessionPreferences;
+    private final P sessionPreferences;
 
     private final L sessionListener;
     private Timeout timeout;
@@ -81,14 +80,15 @@ extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
             Future<Channel> future = sslHandler.get().handshakeFuture();
             future.addListener(new GenericFutureListener<Future<? super Channel>>() {
                 @Override
-                public void operationComplete(Future<? super Channel> future) throws Exception {
+                public void operationComplete(Future<? super Channel> future) {
                     Preconditions.checkState(future.isSuccess(), "Ssl handshake was not successful");
                     logger.debug("Ssl handshake complete");
                     start();
                 }
             });
-        } else
+        } else {
             start();
+        }
     }
 
     private static Optional<SslHandler> getSslHandler(Channel channel) {
@@ -96,31 +96,19 @@ extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
         return sslHandler == null ? Optional.<SslHandler> absent() : Optional.of(sslHandler);
     }
 
+    public P getSessionPreferences() {
+        return sessionPreferences;
+    }
+
     private void start() {
         final NetconfMessage helloMessage = this.sessionPreferences.getHelloMessage();
         logger.debug("Session negotiation started with hello message {}", XmlUtil.toString(helloMessage.getDocument()));
 
-        channel.pipeline().addLast(NAME_OF_EXCEPTION_HANDLER, new ChannelHandler() {
-            @Override
-            public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
-            }
-
-            @Override
-            public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
-            }
-
-            @Override
-            public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
-                logger.warn("An exception occurred during negotiation on channel {}", channel.localAddress(), cause);
-                cancelTimeout();
-                negotiationFailed(cause);
-                changeState(State.FAILED);
-            }
-        });
+        channel.pipeline().addLast(NAME_OF_EXCEPTION_HANDLER, new ExceptionHandlingInboundChannelHandler());
 
         timeout = this.timer.newTimeout(new TimerTask() {
             @Override
-            public void run(final Timeout timeout) throws Exception {
+            public void run(final Timeout timeout) {
                 synchronized (this) {
                     if (state != State.ESTABLISHED) {
                         logger.debug("Connection timeout after {}, session is in state {}", timeout, state);
@@ -140,8 +128,9 @@ extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
     }
 
     private void cancelTimeout() {
-        if(timeout!=null)
+        if(timeout!=null) {
             timeout.cancel();
+        }
     }
 
     private void sendMessage(NetconfMessage message) {
@@ -150,27 +139,20 @@ extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
 
     @Override
     protected void handleMessage(NetconfHelloMessage netconfMessage) {
-        final Document doc = netconfMessage.getDocument();
+        Preconditions.checkNotNull(netconfMessage != null, "netconfMessage");
 
-        // Only Hello message should arrive during negotiation
-        if (netconfMessage instanceof NetconfHelloMessage) {
+        final Document doc = netconfMessage.getDocument();
 
-            replaceHelloMessageHandlers();
+        replaceHelloMessageHandlers();
 
-            if (shouldUseChunkFraming(doc)) {
-                insertChunkFramingToPipeline();
-            }
+        if (shouldUseChunkFraming(doc)) {
+            insertChunkFramingToPipeline();
+        }
 
-            changeState(State.ESTABLISHED);
-            S session = getSession(sessionListener, channel, (NetconfHelloMessage)netconfMessage);
+        changeState(State.ESTABLISHED);
+        S session = getSession(sessionListener, channel, netconfMessage);
 
-            negotiationSuccessful(session);
-        } else {
-            final IllegalStateException cause = new IllegalStateException(
-                    "Received message was not hello as expected, but was " + XmlUtil.toString(doc));
-            logger.warn("Negotiation of netconf session failed", cause);
-            negotiationFailed(cause);
-        }
+        negotiationSuccessful(session);
     }
 
     /**
@@ -180,9 +162,7 @@ extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
         replaceChannelHandler(channel, AbstractChannelInitializer.NETCONF_MESSAGE_FRAME_ENCODER,
                 FramingMechanismHandlerFactory.createHandler(FramingMechanism.CHUNK));
         replaceChannelHandler(channel, AbstractChannelInitializer.NETCONF_MESSAGE_AGGREGATOR,
-                new NetconfMessageAggregator(FramingMechanism.CHUNK));
-        channel.pipeline().addAfter(AbstractChannelInitializer.NETCONF_MESSAGE_AGGREGATOR,
-                CHUNK_DECODER_CHANNEL_HANDLER_KEY, new NetconfMessageChunkDecoder());
+                new NetconfChunkAggregator());
     }
 
     private boolean shouldUseChunkFraming(Document doc) {
@@ -222,14 +202,31 @@ extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
     }
 
     private static boolean isStateChangePermitted(State state, State newState) {
-        if (state == State.IDLE && newState == State.OPEN_WAIT)
+        if (state == State.IDLE && newState == State.OPEN_WAIT) {
             return true;
-        if (state == State.OPEN_WAIT && newState == State.ESTABLISHED)
+        }
+        if (state == State.OPEN_WAIT && newState == State.ESTABLISHED) {
             return true;
-        if (state == State.OPEN_WAIT && newState == State.FAILED)
+        }
+        if (state == State.OPEN_WAIT && newState == State.FAILED) {
             return true;
+        }
 
         logger.debug("Transition from {} to {} is not allowed", state, newState);
         return false;
     }
+
+    /**
+     * Handler to catch exceptions in pipeline during negotiation
+     */
+    private final class ExceptionHandlingInboundChannelHandler extends ChannelInboundHandlerAdapter {
+
+        @Override
+        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
+            logger.warn("An exception occurred during negotiation on channel {}", channel.localAddress(), cause);
+            cancelTimeout();
+            negotiationFailed(cause);
+            changeState(State.FAILED);
+        }
+    }
 }
index aae2f71b86b6f67aa08d57bd374407c59d17651d..796ab91a504040e87197f9032d85e4699d4c80b5 100644 (file)
@@ -27,10 +27,12 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 
-public class NetconfUtil {
+public final class NetconfUtil {
 
     private static final Logger logger = LoggerFactory.getLogger(NetconfUtil.class);
 
+    private NetconfUtil() {}
+
     public static NetconfMessage createMessage(final File f) {
         Preconditions.checkNotNull(f, "File parameter was null");
         try {
index d8dd7881653b466b24886da068f1d6bab529027b..ccc80a7b71248758cc2ce9a3c00225a0dab3fc49 100644 (file)
@@ -8,36 +8,51 @@
 
 package org.opendaylight.controller.netconf.util.handler;
 
-import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
-import org.opendaylight.controller.netconf.util.messages.NetconfMessageHeader;
-
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.MessageToByteEncoder;
 
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageHeader;
+
+import com.google.common.base.Preconditions;
+
 public class ChunkedFramingMechanismEncoder extends MessageToByteEncoder<ByteBuf> {
+    public static final int DEFAULT_CHUNK_SIZE = 8192;
+    public static final int MIN_CHUNK_SIZE = 128;
+    public static final int MAX_CHUNK_SIZE = 16 * 1024 * 1024;
 
-    private NetconfMessageHeader messageHeader = new NetconfMessageHeader();
+    private final int chunkSize;
 
-    private final static int MAX_CHUNK_SIZE = NetconfMessageConstants.MAX_CHUNK_SIZE;
+    public ChunkedFramingMechanismEncoder() {
+        this(DEFAULT_CHUNK_SIZE);
+    }
+
+    public ChunkedFramingMechanismEncoder(int chunkSize) {
+        Preconditions.checkArgument(chunkSize > MIN_CHUNK_SIZE);
+        Preconditions.checkArgument(chunkSize < MAX_CHUNK_SIZE);
+        this.chunkSize = chunkSize;
+    }
+
+    public final int getChunkSize() {
+        return chunkSize;
+    }
 
     @Override
     protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception {
-        while (msg.readableBytes() > MAX_CHUNK_SIZE) {
-            ByteBuf chunk = Unpooled.buffer(MAX_CHUNK_SIZE);
-            chunk.writeBytes(createChunkHeader(MAX_CHUNK_SIZE));
-            chunk.writeBytes(msg.readBytes(MAX_CHUNK_SIZE));
+        while (msg.readableBytes() > chunkSize) {
+            ByteBuf chunk = Unpooled.buffer(chunkSize);
+            chunk.writeBytes(createChunkHeader(chunkSize));
+            chunk.writeBytes(msg.readBytes(chunkSize));
             ctx.write(chunk);
         }
         out.writeBytes(createChunkHeader(msg.readableBytes()));
         out.writeBytes(msg.readBytes(msg.readableBytes()));
-        out.writeBytes(NetconfMessageConstants.endOfChunk);
+        out.writeBytes(NetconfMessageConstants.END_OF_CHUNK);
     }
 
     private ByteBuf createChunkHeader(int chunkSize) {
-        messageHeader.setLength(chunkSize);
-        return Unpooled.wrappedBuffer(messageHeader.toBytes());
+        return Unpooled.wrappedBuffer(NetconfMessageHeader.toBytes(chunkSize));
     }
-
 }
index 7ec5a8f8dcd6c7304b8e7f5edbf7d292acb70199..a3efe8a16bd0c541971e7a4c0ca172b83144d3d5 100644 (file)
@@ -8,20 +8,16 @@
 
 package org.opendaylight.controller.netconf.util.handler;
 
-import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
-
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.MessageToByteEncoder;
 
-public class EOMFramingMechanismEncoder extends MessageToByteEncoder<ByteBuf> {
-
-    private byte[] eom = NetconfMessageConstants.endOfMessage;
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
 
+public class EOMFramingMechanismEncoder extends MessageToByteEncoder<ByteBuf> {
     @Override
     protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception {
         out.writeBytes(msg);
-        out.writeBytes(eom);
+        out.writeBytes(NetconfMessageConstants.END_OF_MESSAGE);
     }
-
 }
index 0d98084343a49355e22210868d5c08310dca460a..1f7a32dc704ca2698112b0e5e9d90c9cdb503a87 100644 (file)
@@ -17,7 +17,9 @@ import io.netty.handler.codec.MessageToByteEncoder;
 
 public class FramingMechanismHandlerFactory {
 
-    private final static Logger logger = LoggerFactory.getLogger(FramingMechanismHandlerFactory.class);
+    private static final Logger logger = LoggerFactory.getLogger(FramingMechanismHandlerFactory.class);
+
+    private FramingMechanismHandlerFactory() {}
 
     public static MessageToByteEncoder<ByteBuf> createHandler(FramingMechanism framingMechanism) {
         logger.debug("{} framing mechanism was selected.", framingMechanism);
diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfChunkAggregator.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfChunkAggregator.java
new file mode 100644 (file)
index 0000000..f7045c3
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * 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.util.handler;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.ByteToMessageDecoder;
+
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetconfChunkAggregator extends ByteToMessageDecoder {
+    private final static Logger logger = LoggerFactory.getLogger(NetconfChunkAggregator.class);
+    public static final int DEFAULT_MAXIMUM_CHUNK_SIZE = 16 * 1024 * 1024;
+
+    private static enum State {
+        HEADER_ONE, // \n
+        HEADER_TWO, // #
+        HEADER_LENGTH_FIRST, // [1-9]
+        HEADER_LENGTH_OTHER, // [0-9]*\n
+        DATA,
+        FOOTER_ONE, // \n
+        FOOTER_TWO, // #
+        FOOTER_THREE, // #
+        FOOTER_FOUR, // \n
+    }
+
+    private final int maxChunkSize = DEFAULT_MAXIMUM_CHUNK_SIZE;
+    private State state = State.HEADER_ONE;
+    private long chunkSize;
+    private ByteBuf chunk;
+
+    @Override
+    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
+        while (in.isReadable()) {
+            switch (state) {
+            case HEADER_ONE:
+            {
+                final byte b = in.readByte();
+                if (b != '\n') {
+                    logger.debug("Got byte {} while waiting for {}", b, (byte)'\n');
+                    throw new IllegalStateException("Malformed chunk header encountered (byte 0)");
+                }
+
+                state = State.HEADER_TWO;
+                break;
+            }
+            case HEADER_TWO:
+            {
+                final byte b = in.readByte();
+                if (b != '#') {
+                    logger.debug("Got byte {} while waiting for {}", b, (byte)'#');
+                    throw new IllegalStateException("Malformed chunk header encountered (byte 1)");
+                }
+
+                state = State.HEADER_LENGTH_FIRST;
+                break;
+            }
+            case HEADER_LENGTH_FIRST:
+            {
+                final byte b = in.readByte();
+                if (b < '1' || b > '9') {
+                    logger.debug("Got byte {} while waiting for {}-{}", b, (byte)'1', (byte)'9');
+                    throw new IllegalStateException("Invalid chunk size encountered (byte 0)");
+                }
+
+                chunkSize = b - '0';
+                state = State.HEADER_LENGTH_OTHER;
+                break;
+            }
+            case HEADER_LENGTH_OTHER:
+            {
+                final byte b = in.readByte();
+                if (b == '\n') {
+                    state = State.DATA;
+                    break;
+                }
+
+                if (b < '0' || b > '9') {
+                    logger.debug("Got byte {} while waiting for {}-{}", b, (byte)'0', (byte)'9');
+                    throw new IllegalStateException("Invalid chunk size encountered");
+                }
+
+                chunkSize *= 10;
+                chunkSize += b - '0';
+
+                if (chunkSize > maxChunkSize) {
+                    logger.debug("Parsed chunk size {}, maximum allowed is {}", chunkSize, maxChunkSize);
+                    throw new IllegalStateException("Maximum chunk size exceeded");
+                }
+                break;
+            }
+            case DATA:
+                /*
+                 * FIXME: this gathers all data into one big chunk before passing
+                 *        it on. Make sure the pipeline can work with partial data
+                 *        and then change this piece to pass the data on as it
+                 *        comes through.
+                 */
+                if (in.readableBytes() < chunkSize) {
+                    logger.debug("Buffer has {} bytes, need {} to complete chunk", in.readableBytes(), chunkSize);
+                    in.discardReadBytes();
+                    return;
+                }
+
+                chunk = in.readBytes((int)chunkSize);
+                state = State.FOOTER_ONE;
+                break;
+            case FOOTER_ONE:
+            {
+                final byte b = in.readByte();
+                if (b != '\n') {
+                    logger.debug("Got byte {} while waiting for {}", b, (byte)'\n');
+                    throw new IllegalStateException("Malformed chunk footer encountered (byte 0)");
+                }
+
+                state = State.FOOTER_TWO;
+                break;
+            }
+            case FOOTER_TWO:
+            {
+                final byte b = in.readByte();
+                if (b != '#') {
+                    logger.debug("Got byte {} while waiting for {}", b, (byte)'#');
+                    throw new IllegalStateException("Malformed chunk footer encountered (byte 1)");
+                }
+
+                state = State.FOOTER_THREE;
+                break;
+            }
+            case FOOTER_THREE:
+            {
+                final byte b = in.readByte();
+                if (b != '#') {
+                    logger.debug("Got byte {} while waiting for {}", b, (byte)'#');
+                    throw new IllegalStateException("Malformed chunk footer encountered (byte 2)");
+                }
+
+                state = State.FOOTER_FOUR;
+                break;
+            }
+            case FOOTER_FOUR:
+            {
+                final byte b = in.readByte();
+                if (b != '\n') {
+                    logger.debug("Got byte {} while waiting for {}", b, (byte)'\n');
+                    throw new IllegalStateException("Malformed chunk footer encountered (byte 3)");
+                }
+
+                state = State.HEADER_ONE;
+                out.add(chunk);
+                chunkSize = 0;
+                chunk = null;
+                break;
+            }
+            }
+        }
+
+        in.discardReadBytes();
+    }
+}
@@ -8,32 +8,24 @@
 
 package org.opendaylight.controller.netconf.util.handler;
 
-import com.google.common.base.Charsets;
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.ByteToMessageDecoder;
-import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
-import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import java.util.List;
 
-public class NetconfMessageAggregator extends ByteToMessageDecoder {
-
-    private final static Logger logger = LoggerFactory.getLogger(NetconfMessageAggregator.class);
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-    private byte[] eom = NetconfMessageConstants.endOfMessage;
+import com.google.common.base.Charsets;
 
-    public NetconfMessageAggregator(FramingMechanism framingMechanism) {
-        if (framingMechanism == FramingMechanism.CHUNK) {
-            eom = NetconfMessageConstants.endOfChunk;
-        }
-    }
+public class NetconfEOMAggregator extends ByteToMessageDecoder {
+    private final static Logger logger = LoggerFactory.getLogger(NetconfEOMAggregator.class);
 
     @Override
     protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
-        int index = indexOfSequence(in, eom);
+        int index = indexOfSequence(in, NetconfMessageConstants.END_OF_MESSAGE);
         if (index == -1) {
             logger.debug("Message is not complete, read again.");
             if (logger.isTraceEnabled()) {
@@ -43,7 +35,7 @@ public class NetconfMessageAggregator extends ByteToMessageDecoder {
             ctx.read();
         } else {
             ByteBuf msg = in.readBytes(index);
-            in.readBytes(eom.length);
+            in.readBytes(NetconfMessageConstants.END_OF_MESSAGE.length);
             in.discardReadBytes();
             logger.debug("Message is complete.");
             out.add(msg);
index a87d175d78e2f901d70de1efd5a7466223a21001..65d5b270254dcbd9503a98791c4c9f878d3442f9 100644 (file)
@@ -7,12 +7,18 @@
  */
 package org.opendaylight.controller.netconf.util.handler;
 
-import java.nio.ByteBuffer;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+
+import java.io.IOException;
+
+import javax.xml.transform.TransformerException;
 
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Charsets;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
@@ -39,9 +45,9 @@ import com.google.common.base.Preconditions;
  * </pre>
  */
 public final class NetconfHelloMessageToXMLEncoder extends NetconfMessageToXMLEncoder {
-
     @Override
-    protected ByteBuffer encodeMessage(NetconfMessage msg) {
+    @VisibleForTesting
+    public void encode(ChannelHandlerContext ctx, NetconfMessage msg, ByteBuf out) throws IOException, TransformerException {
         Preconditions.checkState(msg instanceof NetconfHelloMessage, "Netconf message of type %s expected, was %s",
                 NetconfHelloMessage.class, msg.getClass());
         Optional<NetconfHelloMessageAdditionalHeader> headerOptional = ((NetconfHelloMessage) msg)
@@ -50,15 +56,9 @@ public final class NetconfHelloMessageToXMLEncoder extends NetconfMessageToXMLEn
         // If additional header present, serialize it along with netconf hello
         // message
         if (headerOptional.isPresent()) {
-            byte[] bytesFromHeader = headerOptional.get().toFormattedString().getBytes(Charsets.UTF_8);
-            byte[] bytesFromMessage = xmlToString(msg.getDocument()).getBytes(Charsets.UTF_8);
-
-            ByteBuffer byteBuffer = ByteBuffer.allocate(bytesFromHeader.length + bytesFromMessage.length)
-                    .put(bytesFromHeader).put(bytesFromMessage);
-            byteBuffer.flip();
-            return byteBuffer;
+            out.writeBytes(headerOptional.get().toFormattedString().getBytes(Charsets.UTF_8));
         }
 
-        return super.encodeMessage(msg);
+        super.encode(ctx, msg, out);
     }
 }
diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageChunkDecoder.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageChunkDecoder.java
deleted file mode 100644 (file)
index 5c00b9b..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.netconf.util.handler;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.ByteToMessageDecoder;
-
-import java.nio.charset.Charset;
-import java.util.List;
-
-import org.opendaylight.controller.netconf.api.NetconfDeserializerException;
-import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class NetconfMessageChunkDecoder extends ByteToMessageDecoder {
-
-    private final static Logger logger = LoggerFactory.getLogger(NetconfMessageChunkDecoder.class);
-
-    @Override
-    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
-        ByteBuf byteBufMsg = Unpooled.buffer(in.readableBytes());
-        int chunkSize = -1;
-        boolean isParsed = false;
-        while (in.isReadable()) {
-            try {
-                if (!isParsed) {
-                    chunkSize = readHeader(in);
-                    isParsed = true;
-                }
-                if (chunkSize != -1 && isParsed) {
-                    in.readBytes(byteBufMsg, chunkSize);
-                    isParsed = false;
-                } else {
-                    throw new NetconfDeserializerException("Unable to parse chunked data or header.");
-                }
-            } catch (Exception e) {
-                logger.error("Failed to decode chunked message.", e);
-                this.exceptionCaught(ctx, e);
-            }
-        }
-        out.add(byteBufMsg);
-        isParsed = false;
-    }
-
-    private int readHeader(ByteBuf in) {
-        ByteBuf chunkSize = Unpooled.buffer(NetconfMessageConstants.MIN_HEADER_LENGTH,
-                NetconfMessageConstants.MAX_HEADER_LENGTH);
-        byte b = in.readByte();
-        if (b != 10)
-            return -1;
-        b = in.readByte();
-        if (b != 35)
-            return -1;
-        while ((b = in.readByte()) != 10) {
-            chunkSize.writeByte(b);
-        }
-        return Integer.parseInt(chunkSize.toString(Charset.forName("UTF-8")));
-    }
-
-}
index df0f7ef46a72b30318cfa2a75e5c8e8d6564c4b8..f9792a6c5bf0e2965bead5df9b1c8671ce7d600e 100644 (file)
@@ -8,24 +8,32 @@
 package org.opendaylight.controller.netconf.util.handler;
 
 import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufOutputStream;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.MessageToByteEncoder;
 
-import java.nio.ByteBuffer;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
 
 import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Comment;
-import org.w3c.dom.Document;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Charsets;
 import com.google.common.base.Optional;
 
 public class NetconfMessageToXMLEncoder extends MessageToByteEncoder<NetconfMessage> {
     private static final Logger LOG = LoggerFactory.getLogger(NetconfMessageToXMLEncoder.class);
+    private static final TransformerFactory FACTORY = TransformerFactory.newInstance();
 
     private final Optional<String> clientId;
 
@@ -39,7 +47,7 @@ public class NetconfMessageToXMLEncoder extends MessageToByteEncoder<NetconfMess
 
     @Override
     @VisibleForTesting
-    public void encode(ChannelHandlerContext ctx, NetconfMessage msg, ByteBuf out) throws Exception {
+    public void encode(ChannelHandlerContext ctx, NetconfMessage msg, ByteBuf out) throws IOException, TransformerException {
         LOG.debug("Sent to encode : {}", msg);
 
         if (clientId.isPresent()) {
@@ -47,17 +55,14 @@ public class NetconfMessageToXMLEncoder extends MessageToByteEncoder<NetconfMess
             msg.getDocument().appendChild(comment);
         }
 
-        final ByteBuffer msgBytes = encodeMessage(msg);
-
-        LOG.trace("Putting message \n{}", xmlToString(msg.getDocument()));
-        out.writeBytes(msgBytes);
-    }
-
-    protected ByteBuffer encodeMessage(NetconfMessage msg) {
-        return Charsets.UTF_8.encode(xmlToString(msg.getDocument()));
-    }
+        try (OutputStream os = new ByteBufOutputStream(out)) {
+            Transformer transformer = FACTORY.newTransformer();
+            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
 
-    protected String xmlToString(Document doc) {
-        return XmlUtil.toString(doc, false);
+            StreamResult result = new StreamResult(new OutputStreamWriter(os));
+            DOMSource source = new DOMSource(msg.getDocument());
+            transformer.transform(source, result);
+        }
     }
 }
index 42586a5ecc60433d28a8fa89bbe57d3e958fdee1..c4808e0868d0f59b1378f5900b5151933edf696e 100644 (file)
@@ -7,6 +7,12 @@
  */
 package org.opendaylight.controller.netconf.util.handler;
 
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.ByteToMessageDecoder;
+
+import java.io.ByteArrayInputStream;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.List;
@@ -14,8 +20,12 @@ import java.util.List;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Charsets;
 import com.google.common.collect.ImmutableList;
 
@@ -25,7 +35,8 @@ import com.google.common.collect.ImmutableList;
  * {@link org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage}
  * . Used by netconf server to retrieve information about session metadata.
  */
-public class NetconfXMLToHelloMessageDecoder extends NetconfXMLToMessageDecoder {
+public final class NetconfXMLToHelloMessageDecoder extends ByteToMessageDecoder {
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfXMLToHelloMessageDecoder.class);
 
     private static final List<byte[]> POSSIBLE_ENDS = ImmutableList.of(
             new byte[] { ']', '\n' },
@@ -35,34 +46,46 @@ public class NetconfXMLToHelloMessageDecoder extends NetconfXMLToMessageDecoder
             new byte[] { '\r', '\n', '[' },
             new byte[] { '\n', '[' });
 
-    private String additionalHeaderCache;
-
     @Override
-    protected byte[] preprocessMessageBytes(byte[] bytes) {
-        // Extract bytes containing header with additional metadata
-
-        if (startsWithAdditionalHeader(bytes)) {
-            // Auth information containing username, ip address... extracted for monitoring
-            int endOfAuthHeader = getAdditionalHeaderEndIndex(bytes);
-            if (endOfAuthHeader > -1) {
-                byte[] additionalHeaderBytes = Arrays.copyOfRange(bytes, 0, endOfAuthHeader + 2);
-                additionalHeaderCache = additionalHeaderToString(additionalHeaderBytes);
-                bytes = Arrays.copyOfRange(bytes, endOfAuthHeader + 2, bytes.length);
-            }
+    @VisibleForTesting
+    public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
+        if (in.readableBytes() == 0) {
+            LOG.debug("No more content in incoming buffer.");
+            return;
         }
 
-        return bytes;
-    }
+        in.markReaderIndex();
+        try {
+            LOG.trace("Received to decode: {}", ByteBufUtil.hexDump(in));
+            byte[] bytes = new byte[in.readableBytes()];
+            in.readBytes(bytes);
+
+            logMessage(bytes);
+
+            // Extract bytes containing header with additional metadata
+            String additionalHeader = null;
+            if (startsWithAdditionalHeader(bytes)) {
+                // Auth information containing username, ip address... extracted for monitoring
+                int endOfAuthHeader = getAdditionalHeaderEndIndex(bytes);
+                if (endOfAuthHeader > -1) {
+                    byte[] additionalHeaderBytes = Arrays.copyOfRange(bytes, 0, endOfAuthHeader + 2);
+                    additionalHeader = additionalHeaderToString(additionalHeaderBytes);
+                    bytes = Arrays.copyOfRange(bytes, endOfAuthHeader + 2, bytes.length);
+                }
+            }
 
-    @Override
-    protected void cleanUpAfterDecode() {
-        additionalHeaderCache = null;
-    }
+            Document doc = XmlUtil.readXmlToDocument(new ByteArrayInputStream(bytes));
 
-    @Override
-    protected NetconfMessage buildNetconfMessage(Document doc) {
-        return new NetconfHelloMessage(doc, additionalHeaderCache == null ? null
-                : NetconfHelloMessageAdditionalHeader.fromString(additionalHeaderCache));
+            final NetconfMessage message;
+            if (additionalHeader != null) {
+                message = new NetconfHelloMessage(doc, NetconfHelloMessageAdditionalHeader.fromString(additionalHeader));
+            } else {
+                message = new NetconfHelloMessage(doc);
+            }
+            out.add(message);
+        } finally {
+            in.discardReadBytes();
+        }
     }
 
     private int getAdditionalHeaderEndIndex(byte[] bytes) {
@@ -102,15 +125,23 @@ public class NetconfXMLToHelloMessageDecoder extends NetconfXMLToMessageDecoder
         return -1;
     }
 
+
+    private void logMessage(byte[] bytes) {
+        String s = Charsets.UTF_8.decode(ByteBuffer.wrap(bytes)).toString();
+        LOG.debug("Parsing message \n{}", s);
+    }
+
     private boolean startsWithAdditionalHeader(byte[] bytes) {
         for (byte[] possibleStart : POSSIBLE_STARTS) {
             int i = 0;
             for (byte b : possibleStart) {
-                if(bytes[i++] != b)
+                if(bytes[i++] != b) {
                     break;
+                }
 
-                if(i == possibleStart.length)
+                if(i == possibleStart.length) {
                     return true;
+                }
             }
         }
 
index b697edfb053229fd75f602798c10150f0152b86c..06a4dc7207204d573f5abb2cc28c32318fee891d 100644 (file)
@@ -7,73 +7,32 @@
  */
 package org.opendaylight.controller.netconf.util.handler;
 
-import java.io.ByteArrayInputStream;
-import java.nio.ByteBuffer;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufInputStream;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.ByteToMessageDecoder;
+
 import java.util.List;
 
-import org.opendaylight.controller.netconf.api.NetconfDeserializerException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Charsets;
 
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.ByteBufUtil;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.ByteToMessageDecoder;
-
-public class NetconfXMLToMessageDecoder extends ByteToMessageDecoder {
+public final class NetconfXMLToMessageDecoder extends ByteToMessageDecoder {
     private static final Logger LOG = LoggerFactory.getLogger(NetconfXMLToMessageDecoder.class);
 
     @Override
     @VisibleForTesting
     public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
-        if (in.readableBytes() == 0) {
-            LOG.debug("No more content in incoming buffer.");
-            return;
-        }
-
-        in.markReaderIndex();
-        try {
+        if (in.readableBytes() != 0) {
             LOG.trace("Received to decode: {}", ByteBufUtil.hexDump(in));
-            byte[] bytes = new byte[in.readableBytes()];
-            in.readBytes(bytes);
-
-            logMessage(bytes);
-
-            bytes = preprocessMessageBytes(bytes);
-            NetconfMessage message;
-            try {
-                Document doc = XmlUtil.readXmlToDocument(new ByteArrayInputStream(bytes));
-                message = buildNetconfMessage(doc);
-            } catch (Exception e) {
-                throw new NetconfDeserializerException("Could not parse message from " + new String(bytes), e);
-            }
-
-            out.add(message);
-        } finally {
-            in.discardReadBytes();
-            cleanUpAfterDecode();
+            out.add(new NetconfMessage(XmlUtil.readXmlToDocument(new ByteBufInputStream(in))));
+        } else {
+            LOG.debug("No more content in incoming buffer.");
         }
     }
-
-    protected void cleanUpAfterDecode() {}
-
-    protected NetconfMessage buildNetconfMessage(Document doc) {
-        return new NetconfMessage(doc);
-    }
-
-    protected byte[] preprocessMessageBytes(byte[] bytes) {
-        return bytes;
-    }
-
-    private void logMessage(byte[] bytes) {
-        String s = Charsets.UTF_8.decode(ByteBuffer.wrap(bytes)).toString();
-        LOG.debug("Parsing message \n{}", s);
-    }
-
 }
index 0d9096c02a3abd1b33204665cb72dc4cbd10e805..49d5a05ae22a6939f992c4637f123f550fb3a4e7 100644 (file)
@@ -29,6 +29,8 @@ import org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket.Virtua
  * stops at instance of this class. All downstream events are handed of to wrapped {@link org.opendaylight.controller.netconf.util.handler.ssh.client.SshClientAdapter};
  */
 public class SshHandler extends ChannelOutboundHandlerAdapter {
+    private static final String SOCKET = "socket";
+
     private final VirtualSocket virtualSocket = new VirtualSocket();
     private final SshClientAdapter sshClientAdapter;
 
@@ -39,20 +41,20 @@ public class SshHandler extends ChannelOutboundHandlerAdapter {
 
     @Override
     public void handlerAdded(ChannelHandlerContext ctx){
-        if (ctx.channel().pipeline().get("socket") == null) {
-            ctx.channel().pipeline().addFirst("socket", virtualSocket);
+        if (ctx.channel().pipeline().get(SOCKET) == null) {
+            ctx.channel().pipeline().addFirst(SOCKET, virtualSocket);
         }
     }
 
     @Override
-    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
-        if (ctx.channel().pipeline().get("socket") != null) {
-            ctx.channel().pipeline().remove("socket");
+    public void handlerRemoved(ChannelHandlerContext ctx) {
+        if (ctx.channel().pipeline().get(SOCKET) != null) {
+            ctx.channel().pipeline().remove(SOCKET);
         }
     }
 
     @Override
-    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
+    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws IOException {
         this.sshClientAdapter.write((ByteBuf) msg);
     }
 
@@ -60,18 +62,18 @@ public class SshHandler extends ChannelOutboundHandlerAdapter {
     public void connect(final ChannelHandlerContext ctx,
                         SocketAddress remoteAddress,
                         SocketAddress localAddress,
-                        ChannelPromise promise) throws Exception {
+                        ChannelPromise promise) {
         ctx.connect(remoteAddress, localAddress, promise);
 
         promise.addListener(new ChannelFutureListener() {
-            public void operationComplete(ChannelFuture channelFuture) throws Exception {
+            public void operationComplete(ChannelFuture channelFuture) {
                 sshClientAdapter.start(ctx);
             }}
         );
     }
 
     @Override
-    public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
+    public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) {
         sshClientAdapter.stop(promise);
     }
 }
index 2f1b260bd087fd0f48dccdb0af1911157395d7cf..4aa274c6df34f2f2e9d4151454c4b84f53a41bdb 100644 (file)
@@ -29,7 +29,8 @@ public class LoginPassword extends AuthenticationHandler {
     public void authenticate(Connection connection) throws IOException {
         boolean isAuthenticated = connection.authenticateWithPassword(username, password);
 
-        if (isAuthenticated == false)
+        if (isAuthenticated == false) {
             throw new IOException("Authentication failed.");
+        }
     }
 }
index 8636e5ecb5fe55f22ce01cf9a19fb537397c9b0e..fffb304d26be7b3b32787fa1ae43e5392023bbd8 100644 (file)
@@ -19,6 +19,7 @@ public abstract class Invoker {
     private Invoker(){}
 
     protected boolean isInvoked() {
+        // TODO invoked is always false
         return invoked;
     }
 
@@ -34,7 +35,9 @@ public abstract class Invoker {
         return new Invoker() {
             @Override
             void invoke(SshSession session) throws IOException {
-                if (isInvoked() == true) throw new IllegalStateException("Already invoked.");
+                if (isInvoked()) {
+                    throw new IllegalStateException("Already invoked.");
+                }
 
                 session.startSubSystem(subsystem);
             }
index 3cb608db6a87c3ef121cc6a4edf0f0676fab9912..7beee649abfe0501e60850fda0db79dd96c7bb86 100644 (file)
@@ -23,7 +23,7 @@ import java.util.Map;
  */
 public class SshClient {
     private final VirtualSocket socket;
-    private final Map<Integer, SshSession> openSessions = new HashMap();
+    private final Map<Integer, SshSession> openSessions = new HashMap<>();
     private final AuthenticationHandler authenticationHandler;
     private Connection connection;
 
@@ -33,8 +33,9 @@ public class SshClient {
     }
 
     public SshSession openSession() throws IOException {
-        if (connection == null)
+        if (connection == null) {
             connect();
+        }
 
         Session session = connection.openSession();
         SshSession sshSession = new SshSession(session);
@@ -52,7 +53,7 @@ public class SshClient {
 
     public void closeSession(SshSession session) {
         if (session.getState() == Channel.STATE_OPEN || session.getState() == Channel.STATE_OPENING) {
-            session.session.close();
+            session.close();
         }
     }
 
@@ -62,7 +63,8 @@ public class SshClient {
 
         openSessions.clear();
 
-        if (connection != null)
+        if (connection != null) {
             connection.close();
+        }
     }
 }
index 4213fe3e0642db6257b3e655c407a4394785fca3..6350dd154415b510515f919d94c88d06ecac5314 100644 (file)
@@ -27,16 +27,14 @@ import org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket.Virtua
  * pipeline.
  */
 public class SshClientAdapter implements Runnable {
+    private static final int BUFFER_SIZE = 1024;
+
     private final SshClient sshClient;
     private final Invoker invoker;
 
-    private SshSession session;
-    private InputStream stdOut;
-    private InputStream stdErr;
     private OutputStream stdIn;
 
-    private Queue<ByteBuf> postponned = new LinkedList<>();
-
+    private Queue<ByteBuf> postponed = new LinkedList<>();
 
     private ChannelHandlerContext ctx;
     private ChannelPromise disconnectPromise;
@@ -52,22 +50,22 @@ public class SshClientAdapter implements Runnable {
 
     public void run() {
         try {
-            session = sshClient.openSession();
+            SshSession session = sshClient.openSession();
             invoker.invoke(session);
-            stdOut = session.getStdout();
-            stdErr = session.getStderr();
+            InputStream stdOut = session.getStdout();
+            session.getStderr();
 
             synchronized (lock) {
 
                 stdIn = session.getStdin();
-                ByteBuf message = null;
-                while ((message = postponned.poll()) != null) {
+                ByteBuf message;
+                while ((message = postponed.poll()) != null) {
                     writeImpl(message);
                 }
             }
 
             while (stopRequested.get() == false) {
-                byte[] readBuff = new byte[1024];
+                byte[] readBuff = new byte[BUFFER_SIZE];
                 int c = stdOut.read(readBuff);
                 if (c == -1) {
                     continue;
@@ -89,8 +87,9 @@ public class SshClientAdapter implements Runnable {
             sshClient.close();
 
             synchronized (lock) {
-                if (disconnectPromise != null)
+                if (disconnectPromise != null) {
                     ctx.disconnect(disconnectPromise);
+                }
             }
         }
     }
@@ -99,7 +98,7 @@ public class SshClientAdapter implements Runnable {
     public void write(ByteBuf message) throws IOException {
         synchronized (lock) {
             if (stdIn == null) {
-                postponned.add(message);
+                postponed.add(message);
                 return;
             }
             writeImpl(message);
@@ -119,8 +118,10 @@ public class SshClientAdapter implements Runnable {
     }
 
     public void start(ChannelHandlerContext ctx) {
-        if (this.ctx != null)
-            return; // context is already associated.
+        if (this.ctx != null) {
+            // context is already associated.
+            return;
+        }
         this.ctx = ctx;
         new Thread(this).start();
     }
index df400aa1413e64108dab66190dd763b4778dc0ce..411036c975baf2f29b9f98e4c69b8956acf64474 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.controller.netconf.util.handler.ssh.client;
 import ch.ethz.ssh2.Session;
 import ch.ethz.ssh2.StreamGobbler;
 
+import java.io.Closeable;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -18,8 +19,8 @@ import java.io.OutputStream;
 /**
  * Wrapper class for proprietary SSH sessions implementations
  */
-public class SshSession {
-    final Session session;
+public class SshSession implements Closeable {
+    private final Session session;
 
     public SshSession(Session session) {
         this.session = session;
@@ -61,8 +62,8 @@ public class SshSession {
         return session.waitUntilDataAvailable(timeout);
     }
 
-    public int waitForCondition(int condition_set, long timeout) {
-        return session.waitForCondition(condition_set, timeout);
+    public int waitForCondition(int conditionSet, long timeout) {
+        return session.waitForCondition(conditionSet, timeout);
     }
 
     public Integer getExitStatus() {
@@ -72,4 +73,9 @@ public class SshSession {
     public String getExitSignal() {
         return session.getExitSignal();
     }
+
+    @Override
+    public void close() {
+        session.close();
+    }
 }
index 4b9bfbf5f826ee13c34127d902c2ad583d5f8eb4..313ea932413b63b36c5d20cc6cb1a9570205ab2a 100644 (file)
@@ -39,7 +39,9 @@ public class ChannelInputStream extends InputStream implements ChannelInboundHan
 
             b[off] = (byte)c;
 
-            if(this.bb.readableBytes() == 0) return bytesRead;
+            if(this.bb.readableBytes() == 0) {
+                return bytesRead;
+            }
 
             int ltr = len-1;
             ltr = (ltr <= bb.readableBytes()) ? ltr : bb.readableBytes();
@@ -72,28 +74,23 @@ public class ChannelInputStream extends InputStream implements ChannelInboundHan
         }
     }
 
-    public void channelRegistered(ChannelHandlerContext ctx)
-            throws Exception {
+    public void channelRegistered(ChannelHandlerContext ctx) {
         ctx.fireChannelRegistered();
     }
 
-    public void channelUnregistered(ChannelHandlerContext ctx)
-            throws Exception {
+    public void channelUnregistered(ChannelHandlerContext ctx) {
         ctx.fireChannelUnregistered();
     }
 
-    public void channelActive(ChannelHandlerContext ctx)
-            throws Exception {
+    public void channelActive(ChannelHandlerContext ctx) {
         ctx.fireChannelActive();
     }
 
-    public void channelInactive(ChannelHandlerContext ctx)
-            throws Exception {
+    public void channelInactive(ChannelHandlerContext ctx) {
         ctx.fireChannelInactive();
     }
 
-    public void channelRead(ChannelHandlerContext ctx, Object o)
-            throws Exception {
+    public void channelRead(ChannelHandlerContext ctx, Object o) {
         synchronized(lock) {
             this.bb.discardReadBytes();
             this.bb.writeBytes((ByteBuf) o);
@@ -101,31 +98,25 @@ public class ChannelInputStream extends InputStream implements ChannelInboundHan
         }
     }
 
-    public void channelReadComplete(ChannelHandlerContext ctx)
-            throws Exception {
+    public void channelReadComplete(ChannelHandlerContext ctx) {
         ctx.fireChannelReadComplete();
     }
 
-    public void userEventTriggered(ChannelHandlerContext ctx, Object o)
-            throws Exception {
+    public void userEventTriggered(ChannelHandlerContext ctx, Object o) {
         ctx.fireUserEventTriggered(o);
     }
 
-    public void channelWritabilityChanged(ChannelHandlerContext ctx)
-            throws Exception {
+    public void channelWritabilityChanged(ChannelHandlerContext ctx) {
         ctx.fireChannelWritabilityChanged();
     }
 
-    public void handlerAdded(ChannelHandlerContext ctx)
-            throws Exception {
+    public void handlerAdded(ChannelHandlerContext ctx) {
     }
 
-    public void handlerRemoved(ChannelHandlerContext ctx)
-            throws Exception {
+    public void handlerRemoved(ChannelHandlerContext ctx) {
     }
 
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable)
-            throws Exception {
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) {
         ctx.fireExceptionCaught(throwable);
     }
 }
index b1314a6eedfde68f71ccb26e27b0c6d73b8e51cd..cd7ec5439bc422e492b874b64e1be89211213d88 100644 (file)
@@ -14,7 +14,6 @@ import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelOutboundHandler;
 import io.netty.channel.ChannelPromise;
 
-import java.io.IOException;
 import java.io.OutputStream;
 import java.net.SocketAddress;
 
@@ -27,7 +26,7 @@ public class ChannelOutputStream extends OutputStream implements ChannelOutbound
     private ChannelHandlerContext ctx;
 
     @Override
-    public void flush() throws IOException {
+    public void flush() {
         synchronized(lock) {
             ctx.writeAndFlush(buff).awaitUninterruptibly();
             buff = Unpooled.buffer();
@@ -35,51 +34,44 @@ public class ChannelOutputStream extends OutputStream implements ChannelOutbound
     }
 
     @Override
-    public void write(int b) throws IOException {
+    public void write(int b) {
         synchronized(lock) {
             buff.writeByte(b);
         }
     }
 
     public void bind(ChannelHandlerContext ctx, SocketAddress localAddress,
-                     ChannelPromise promise) throws Exception {
+                     ChannelPromise promise) {
         ctx.bind(localAddress, promise);
     }
 
     public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress,
-                        SocketAddress localAddress, ChannelPromise promise)
-            throws Exception {
+                        SocketAddress localAddress, ChannelPromise promise) {
         this.ctx = ctx;
         ctx.connect(remoteAddress, localAddress, promise);
     }
 
-    public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise)
-            throws Exception {
+    public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) {
         ctx.disconnect(promise);
     }
 
-    public void close(ChannelHandlerContext ctx, ChannelPromise promise)
-            throws Exception {
+    public void close(ChannelHandlerContext ctx, ChannelPromise promise) {
         ctx.close(promise);
     }
 
-    public void deregister(ChannelHandlerContext ctx, ChannelPromise channelPromise)
-            throws Exception {
+    public void deregister(ChannelHandlerContext ctx, ChannelPromise channelPromise) {
         ctx.deregister(channelPromise);
     }
 
-    public void read(ChannelHandlerContext ctx)
-            throws Exception {
+    public void read(ChannelHandlerContext ctx) {
         ctx.read();
     }
 
-    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise)
-            throws Exception {
+    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
         // pass
     }
 
-    public void flush(ChannelHandlerContext ctx)
-            throws Exception {
+    public void flush(ChannelHandlerContext ctx) {
         // pass
     }
 
@@ -91,8 +83,7 @@ public class ChannelOutputStream extends OutputStream implements ChannelOutbound
             throws Exception {
     }
 
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
-            throws Exception {
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
         ctx.fireExceptionCaught(cause);
     }
 }
index 1011ca16be84803d4bfbe6f8f083335782de6538..36c2c1c3295736bf9cc183fbe53256ac847ff15b 100644 (file)
@@ -26,6 +26,9 @@ import java.nio.channels.SocketChannel;
  * are able to use full potential of NIO environment.
  */
 public class VirtualSocket extends Socket implements ChannelHandler {
+    private static final String INPUT_STREAM = "inputStream";
+    private static final String OUTPUT_STREAM = "outputStream";
+
     private final ChannelInputStream chis = new ChannelInputStream();
     private final ChannelOutputStream chos = new ChannelOutputStream();
     private ChannelHandlerContext ctx;
@@ -39,29 +42,30 @@ public class VirtualSocket extends Socket implements ChannelHandler {
         return this.chos;
     }
 
-    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
+    public void handlerAdded(ChannelHandlerContext ctx) {
         this.ctx = ctx;
 
-        if (ctx.channel().pipeline().get("outputStream") == null) {
-            ctx.channel().pipeline().addFirst("outputStream", chos);
+        if (ctx.channel().pipeline().get(OUTPUT_STREAM) == null) {
+            ctx.channel().pipeline().addFirst(OUTPUT_STREAM, chos);
         }
 
-        if (ctx.channel().pipeline().get("inputStream") == null) {
-            ctx.channel().pipeline().addFirst("inputStream", chis);
+        if (ctx.channel().pipeline().get(INPUT_STREAM) == null) {
+            ctx.channel().pipeline().addFirst(INPUT_STREAM, chis);
         }
     }
 
-    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
-        if (ctx.channel().pipeline().get("outputStream") != null) {
-            ctx.channel().pipeline().remove("outputStream");
+    public void handlerRemoved(ChannelHandlerContext ctx) {
+        if (ctx.channel().pipeline().get(OUTPUT_STREAM) != null) {
+            ctx.channel().pipeline().remove(OUTPUT_STREAM);
         }
 
-        if (ctx.channel().pipeline().get("inputStream") != null) {
-            ctx.channel().pipeline().remove("inputStream");
+        if (ctx.channel().pipeline().get(INPUT_STREAM) != null) {
+            ctx.channel().pipeline().remove(INPUT_STREAM);
         }
     }
 
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) throws Exception {
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) {
+        // TODO exceptionCaught is deprecated transform this handler
         ctx.fireExceptionCaught(throwable);
     }
 
@@ -80,7 +84,9 @@ public class VirtualSocket extends Socket implements ChannelHandler {
     public InetAddress getInetAddress() {
         InetSocketAddress isa = getInetSocketAddress();
 
-        if (isa == null) throw new VirtualSocketException();
+        if (isa == null) {
+            throw new VirtualSocketException();
+        }
 
         return getInetSocketAddress().getAddress();
     }
index f3ca30d2c40a4f924b0b35b5d196ba53295acb57..d1e064eaeb51cac6ed5462e11ccf0600214fd12d 100644 (file)
@@ -18,7 +18,7 @@ import java.util.regex.Pattern;
  * session's connection. Provided information can be reported via netconf
  * monitoring.
  * <pre>
- * It has pattern "[username; host-address:port; transport; session-identifier;]"
+ * It has PATTERN "[username; host-address:port; transport; session-identifier;]"
  * username - name of account on a remote
  * host-address - client's IP address
  * port - port number
@@ -92,20 +92,20 @@ public class NetconfHelloMessageAdditionalHeader {
     }
 
     // TODO IPv6
-    private static final Pattern pattern = Pattern
+    private static final Pattern PATTERN = Pattern
             .compile("\\[(?<username>[^;]+);(?<address>[0-9\\.]+)[:/](?<port>[0-9]+);(?<transport>[a-z]+)[^\\]]+\\]");
-    private static final Pattern customHeaderPattern = Pattern
+    private static final Pattern CUSTOM_HEADER_PATTERN = Pattern
             .compile("\\[(?<username>[^;]+);(?<address>[0-9\\.]+)[:/](?<port>[0-9]+);(?<transport>[a-z]+);(?<sessionIdentifier>[a-z]+)[^\\]]+\\]");
 
     /**
      * Parse additional header from a formatted string
      */
     public static NetconfHelloMessageAdditionalHeader fromString(String additionalHeader) {
-        additionalHeader = additionalHeader.trim();
-        Matcher matcher = pattern.matcher(additionalHeader);
-        Matcher matcher2 = customHeaderPattern.matcher(additionalHeader);
+        String additionalHeaderTrimmed = additionalHeader.trim();
+        Matcher matcher = PATTERN.matcher(additionalHeaderTrimmed);
+        Matcher matcher2 = CUSTOM_HEADER_PATTERN.matcher(additionalHeaderTrimmed);
         Preconditions.checkArgument(matcher.matches(), "Additional header in wrong format %s, expected %s",
-                additionalHeader, pattern);
+                additionalHeaderTrimmed, PATTERN);
 
         String username = matcher.group("username");
         String address = matcher.group("address");
index 0d83a72bd39b9f8e7fecdd7d9eb39d87f18ed6ef..8bd6b8865933d7191a063055834ce3fb98b0bbe4 100644 (file)
@@ -11,14 +11,19 @@ package org.opendaylight.controller.netconf.util.messages;
 import com.google.common.base.Charsets;
 
 public class NetconfMessageConstants {
+    /**
+     * The NETCONF 1.0 old-style message separator. This is framing mechanism
+     * is used by default.
+     */
+    public static final byte[] END_OF_MESSAGE = "]]>]]>".getBytes(Charsets.UTF_8);
 
-    public static final byte[] endOfMessage = "]]>]]>".getBytes(Charsets.UTF_8);
+    // bytes
 
-    public static final byte[] endOfChunk = "\n##\n".getBytes(Charsets.UTF_8);
+    public static final int MIN_HEADER_LENGTH = 4;
 
-    public static final int MAX_CHUNK_SIZE = 1024; // bytes
+    // bytes
 
-    public static final int MIN_HEADER_LENGTH = 4; // bytes
+    public static final int MAX_HEADER_LENGTH = 13;
 
-    public static final int MAX_HEADER_LENGTH = 13; // bytes
-}
\ No newline at end of file
+    public static final byte[] END_OF_CHUNK = "\n##\n".getBytes(Charsets.UTF_8);
+}
index a61541b9146556f7b71e0766e0c8b99a65a81fd9..fa26455c9875d7245429ef72f2ce11b57c56acac 100644 (file)
@@ -8,49 +8,29 @@
 
 package org.opendaylight.controller.netconf.util.messages;
 
+import java.nio.ByteBuffer;
+
 import com.google.common.base.Charsets;
 import com.google.common.base.Preconditions;
 
-import java.nio.ByteBuffer;
-
 /**
  * Netconf message header is used only when chunked framing mechanism is
  * supported. The header consists of only the length field.
  */
+@Deprecated
 public final class NetconfMessageHeader {
-
-    private long length;
-
     // \n#<length>\n
-    private static final byte[] headerBegin = new byte[] { (byte) 0x0a, (byte) 0x23 };
+    private static final byte[] HEADER_START = new byte[] { (byte) 0x0a, (byte) 0x23 };
+    private static final byte HEADER_END = (byte) 0x0a;
+    private final long length;
 
-    private static final byte headerEnd = (byte) 0x0a;
-
-    private boolean parsed = false;
-
-    public NetconfMessageHeader() {
-
-    }
-
-    public NetconfMessageHeader fromBytes(final byte[] bytes) {
-        // the length is variable therefore bytes between headerBegin and
-        // headerEnd mark the length
-        // the length should be only numbers and therefore easily parsed with
-        // ASCII
-        this.length = Long.parseLong(Charsets.US_ASCII.decode(
-                ByteBuffer.wrap(bytes, headerBegin.length, bytes.length - headerBegin.length - 1)).toString());
-        Preconditions.checkState(this.length < Integer.MAX_VALUE && this.length > 0);
-        this.parsed = true;
-        return this;
+    public NetconfMessageHeader(final long length) {
+        Preconditions.checkArgument(length < Integer.MAX_VALUE && length > 0);
+        this.length = length;
     }
 
     public byte[] toBytes() {
-        final byte[] l = String.valueOf(this.length).getBytes(Charsets.US_ASCII);
-        final byte[] h = new byte[headerBegin.length + l.length + 1];
-        System.arraycopy(headerBegin, 0, h, 0, headerBegin.length);
-        System.arraycopy(l, 0, h, headerBegin.length, l.length);
-        System.arraycopy(new byte[] { headerEnd }, 0, h, headerBegin.length + l.length, 1);
-        return h;
+        return toBytes(this.length);
     }
 
     // FIXME: improve precision to long
@@ -58,22 +38,23 @@ public final class NetconfMessageHeader {
         return (int) this.length;
     }
 
-    public void setLength(final int length) {
-        this.length = length;
-    }
+    public static NetconfMessageHeader fromBytes(final byte[] bytes) {
+        // the length is variable therefore bytes between headerBegin and
+        // headerEnd mark the length
+        // the length should be only numbers and therefore easily parsed with
+        // ASCII
+        long length = Long.parseLong(Charsets.US_ASCII.decode(
+                ByteBuffer.wrap(bytes, HEADER_START.length, bytes.length - HEADER_START.length - 1)).toString());
 
-    /**
-     * @return the parsed
-     */
-    public boolean isParsed() {
-        return this.parsed;
+        return new NetconfMessageHeader(length);
     }
 
-    /**
-     * @param parsed
-     *            the parsed to set
-     */
-    public void setParsed() {
-        this.parsed = false;
+    public static byte[] toBytes(final long length) {
+        final byte[] l = String.valueOf(length).getBytes(Charsets.US_ASCII);
+        final byte[] h = new byte[HEADER_START.length + l.length + 1];
+        System.arraycopy(HEADER_START, 0, h, 0, HEADER_START.length);
+        System.arraycopy(l, 0, h, HEADER_START.length, l.length);
+        System.arraycopy(new byte[] { HEADER_END }, 0, h, HEADER_START.length + l.length, 1);
+        return h;
     }
 }
index 46053e734ebf006154e26d5c8b7564ff6a36eedd..91eb86908b169ca9ecff8a77fb803b2d7ee60184 100644 (file)
@@ -13,7 +13,9 @@ import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.w3c.dom.Document;
 
-public class NetconfMessageUtil {
+public final class NetconfMessageUtil {
+
+    private NetconfMessageUtil() {}
 
     public static boolean isOKMessage(NetconfMessage message) {
         return isOKMessage(message.getDocument());
index 6dc00bb1509e97b0a485b89e90b0248a642e7a1a..de2d6d7e0c354ada3bcf1fb4f1b630b186c34e3c 100644 (file)
@@ -29,9 +29,11 @@ import javax.xml.xpath.XPathExpression;
 import java.io.InputStream;
 import java.util.Map.Entry;
 
-public class SendErrorExceptionUtil {
+public final class SendErrorExceptionUtil {
     private static final Logger logger = LoggerFactory.getLogger(SendErrorExceptionUtil.class);
 
+    private SendErrorExceptionUtil() {}
+
     public static void sendErrorMessage(final NetconfSession session,
             final NetconfDocumentedException sendErrorException) {
         logger.trace("Sending error {}", sendErrorException.getMessage(), sendErrorException);
@@ -68,8 +70,9 @@ public class SendErrorExceptionUtil {
             for (int i = 0; i < incomingAttributes.getLength(); i++) {
                 final Attr attr = (Attr) incomingAttributes.item(i);
                 // skip namespace
-                if (attr.getNodeName().equals(XmlUtil.XMLNS_ATTRIBUTE_KEY))
+                if (attr.getNodeName().equals(XmlUtil.XMLNS_ATTRIBUTE_KEY)) {
                     continue;
+                }
                 rpcReply.setAttributeNode((Attr) errorDocument.importNode(attr, true));
             }
         } catch (final Exception e) {
index 38563cba93eef1f727330b17ff72879a012f70ff..80eaa26de184ddc29993bd847d1c34b0e7becd09 100644 (file)
@@ -17,12 +17,12 @@ import java.net.InetSocketAddress;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
-public class NetconfConfigUtil {
+public final class NetconfConfigUtil {
     private static final Logger logger = LoggerFactory.getLogger(NetconfConfigUtil.class);
 
     private static final String PREFIX_PROP = "netconf.";
 
-
+    private NetconfConfigUtil() {}
 
     private enum InfixProp {
         tcp, ssh
index d9303228f95b55773c3a15e7ef6e0bc7b01cef71..3247e0f7a0e034402fcedda91b2b1e5ece7a1fe8 100644 (file)
@@ -13,7 +13,9 @@ import javax.xml.xpath.XPathExpression;
 import javax.xml.xpath.XPathExpressionException;
 import javax.xml.xpath.XPathFactory;
 
-public class XMLNetconfUtil {
+public final class XMLNetconfUtil {
+
+    private XMLNetconfUtil() {}
 
     public static XPathExpression compileXPath(String xPath) {
         final XPathFactory xPathfactory = XPathFactory.newInstance();
index 18a94c6d07ff7cf74289bfb5d3e057967a61e86c..1fbae1ee2d6e52c404742655ccd059e9038fd803 100644 (file)
@@ -31,9 +31,9 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-public class XmlElement {
+public final class XmlElement {
 
-    public final Element element;
+    private final Element element;
 
     private XmlElement(Element element) {
         this.element = element;
@@ -123,9 +123,6 @@ public class XmlElement {
 
     public void appendChild(Element element) {
         this.element.appendChild(element);
-        // Element newElement = (Element) element.cloneNode(true);
-        // newElement.appendChild(configElement);
-        // return XmlElement.fromDomElement(newElement);
     }
 
     public Element getDomElement() {
@@ -153,10 +150,12 @@ public class XmlElement {
         final List<XmlElement> result = new ArrayList<>();
         for (int i = 0; i < childNodes.getLength(); i++) {
             Node item = childNodes.item(i);
-            if (item instanceof Element == false)
+            if (item instanceof Element == false) {
                 continue;
-            if (strat.accept((Element) item))
+            }
+            if (strat.accept((Element) item)) {
                 result.add(new XmlElement((Element) item));
+            }
         }
 
         return result;
@@ -290,12 +289,12 @@ public class XmlElement {
     public String getNamespace() {
         String namespaceURI = element.getNamespaceURI();
         Preconditions.checkState(namespaceURI != null, "No namespace defined for %s", this);
-        return namespaceURI.toString();
+        return namespaceURI;
     }
 
     @Override
     public String toString() {
-        final StringBuffer sb = new StringBuffer("XmlElement{");
+        final StringBuilder sb = new StringBuilder("XmlElement{");
         sb.append("name='").append(getName()).append('\'');
         if (element.getNamespaceURI() != null) {
             sb.append(", namespace='").append(getNamespace()).append('\'');
@@ -320,7 +319,7 @@ public class XmlElement {
     public Map.Entry<String/* prefix */, String/* namespace */> findNamespaceOfTextContent() {
         Map<String, String> namespaces = extractNamespaces(element);
         String textContent = getTextContent();
-        int indexOfColon = textContent.indexOf(":");
+        int indexOfColon = textContent.indexOf(':');
         String prefix;
         if (indexOfColon > -1) {
             prefix = textContent.substring(0, indexOfColon);
@@ -360,15 +359,18 @@ public class XmlElement {
 
     @Override
     public boolean equals(Object o) {
-        if (this == o)
+        if (this == o) {
             return true;
-        if (o == null || getClass() != o.getClass())
+        }
+        if (o == null || getClass() != o.getClass()) {
             return false;
+        }
 
         XmlElement that = (XmlElement) o;
 
-        if (!element.isEqualNode(that.element))
+        if (!element.isEqualNode(that.element)) {
             return false;
+        }
 
         return true;
     }
@@ -392,7 +394,7 @@ public class XmlElement {
         return true;
     }
 
-    private static interface ElementFilteringStrategy {
+    private interface ElementFilteringStrategy {
         boolean accept(Element e);
     }
 }
index c410cf30b0abd00290bbc178c5ea3c9cbc7c0a21..4a6586cd1d8bf8ee0e9e4cbef66e62048cf1e5e6 100644 (file)
@@ -7,7 +7,9 @@
  */
 package org.opendaylight.controller.netconf.util.xml;
 
-public class XmlNetconfConstants {
+public final class XmlNetconfConstants {
+
+    private XmlNetconfConstants() {}
 
     public static final String MOUNTPOINTS = "mountpoints";
     public static final String MOUNTPOINT = "mountpoint";
index de0ebccdca428d8285d26d74b2f4e9fd54b5d353..8108c8e7402fac29469cf7804efd96e1dc6455df 100644 (file)
@@ -21,8 +21,11 @@ import org.xml.sax.SAXException;
 
 import com.google.common.base.Preconditions;
 
-public class XmlNetconfValidator {
-    static final Schema schema;
+public final class XmlNetconfValidator {
+
+    private static final Schema SCHEMA;
+
+    private XmlNetconfValidator() {}
 
     static {
         final InputStream xmlSchema = XmlNetconfValidator.class.getResourceAsStream("/xml.xsd");
@@ -30,11 +33,11 @@ public class XmlNetconfValidator {
 
         final InputStream rfc4714Schema = XmlNetconfValidator.class.getResourceAsStream("/rfc4741.xsd");
         Preconditions.checkNotNull(rfc4714Schema, "Cannot find rfc4741.xsd");
-        schema = XmlUtil.loadSchema(xmlSchema, rfc4714Schema);
+        SCHEMA = XmlUtil.loadSchema(xmlSchema, rfc4714Schema);
     }
 
     public static void validate(Document inputDocument) throws SAXException, IOException {
-        final Validator validator = schema.newValidator();
+        final Validator validator = SCHEMA.newValidator();
         final Source source = new DOMSource(inputDocument);
         validator.validate(source);
     }
index 137e215a31eb13423b6438671faed529a2fc7ce3..238249dbbd8d49086b38c1696cb6d0cb685909fe 100644 (file)
@@ -41,9 +41,21 @@ import org.xml.sax.SAXException;
 
 import com.google.common.base.Charsets;
 
-public class XmlUtil {
+public final class XmlUtil {
 
     public static final String XMLNS_ATTRIBUTE_KEY = "xmlns";
+    private static final DocumentBuilderFactory BUILDERFACTORY;
+
+    static {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        factory.setCoalescing(true);
+        factory.setIgnoringElementContentWhitespace(true);
+        factory.setIgnoringComments(true);
+        BUILDERFACTORY = factory;
+    }
+
+    private XmlUtil() {}
 
     public static Element readXmlToElement(String xmlContent) throws SAXException, IOException {
         Document doc = readXmlToDocument(xmlContent);
@@ -59,13 +71,15 @@ public class XmlUtil {
         return readXmlToDocument(new ByteArrayInputStream(xmlContent.getBytes(Charsets.UTF_8)));
     }
 
+    // TODO improve exceptions throwing
+    // along with XmlElement
+
     public static Document readXmlToDocument(InputStream xmlContent) throws SAXException, IOException {
-        DocumentBuilderFactory factory = getDocumentBuilderFactory();
         DocumentBuilder dBuilder;
         try {
-            dBuilder = factory.newDocumentBuilder();
+            dBuilder = BUILDERFACTORY.newDocumentBuilder();
         } catch (ParserConfigurationException e) {
-            throw new RuntimeException(e);
+            throw new RuntimeException("Failed to parse XML document", e);
         }
         Document doc = dBuilder.parse(xmlContent);
 
@@ -77,23 +91,13 @@ public class XmlUtil {
         return readXmlToDocument(new FileInputStream(xmlFile)).getDocumentElement();
     }
 
-    private static final DocumentBuilderFactory getDocumentBuilderFactory() {
-        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-        factory.setNamespaceAware(true);
-        factory.setCoalescing(true);
-        factory.setIgnoringElementContentWhitespace(true);
-        factory.setIgnoringComments(true);
-        return factory;
-    }
-
     public static Document newDocument() {
-        DocumentBuilderFactory factory = getDocumentBuilderFactory();
         try {
-            DocumentBuilder builder = factory.newDocumentBuilder();
+            DocumentBuilder builder = BUILDERFACTORY.newDocumentBuilder();
             Document document = builder.newDocument();
             return document;
         } catch (ParserConfigurationException e) {
-            throw new RuntimeException(e);
+            throw new RuntimeException("Failed to create document", e);
         }
     }
 
@@ -135,14 +139,13 @@ public class XmlUtil {
         try {
             Transformer transformer = TransformerFactory.newInstance().newTransformer();
             transformer.setOutputProperty(OutputKeys.INDENT, "yes");
-            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, addXmlDeclaration == true ? "no" : "yes");
+            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, addXmlDeclaration ? "no" : "yes");
 
             StreamResult result = new StreamResult(new StringWriter());
             DOMSource source = new DOMSource(xml);
             transformer.transform(source, result);
 
-            String xmlString = result.getWriter().toString();
-            return xmlString;
+            return result.getWriter().toString();
         } catch (IllegalArgumentException | TransformerFactoryConfigurationError | TransformerException e) {
             throw new RuntimeException("Unable to serialize xml element " + xml, e);
         }
index 6b7bffcd862394c678b1dfa69e65bbaad9481f89..18830f85ddcdc8595bc7be40dc8f439d1dc3bec4 100644 (file)
@@ -16,14 +16,13 @@ import java.util.List;
 
 import org.junit.Test;
 import org.opendaylight.controller.netconf.util.handler.NetconfXMLToHelloMessageDecoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
 
 import com.google.common.io.Files;
 
 public class NetconfMessageFactoryTest {
     @Test
     public void testAuth() throws Exception {
-        NetconfXMLToMessageDecoder parser = new NetconfXMLToHelloMessageDecoder();
+        NetconfXMLToHelloMessageDecoder parser = new NetconfXMLToHelloMessageDecoder();
         File authHelloFile = new File(getClass().getResource("/netconfMessages/client_hello_with_auth.xml").getFile());
 
         final List<Object> out = new ArrayList<>();
index c62f4bab717e49992ca1a97f9a6b302943f439a1..fc620a99eef336baa5f5d54c98fcdf694db9d1a8 100644 (file)
@@ -22,7 +22,6 @@
       <plugin>
         <groupId>org.codehaus.enunciate</groupId>
         <artifactId>maven-enunciate-plugin</artifactId>
-        <version>${enunciate.version}</version>
         <dependencies>
           <dependency>
             <groupId>org.opendaylight.controller</groupId>
index 48dee485ae7437e80c5e7deafa0f346759db57b8..89cb7446faeb8048bbd15c81c4455de3ce0cebf2 100644 (file)
@@ -23,7 +23,6 @@
       <plugin>
         <groupId>org.codehaus.enunciate</groupId>
         <artifactId>maven-enunciate-plugin</artifactId>
-        <version>${enunciate.version}</version>
        </plugin>
       <plugin>
         <groupId>org.apache.felix</groupId>
index 33926af0c880ffa003202819c6d4dca2918925d3..2fcc2a593a025b984b6368b9f69720ce11c46d81 100644 (file)
@@ -22,7 +22,6 @@
       <plugin>
         <groupId>org.codehaus.enunciate</groupId>
         <artifactId>maven-enunciate-plugin</artifactId>
-        <version>${enunciate.version}</version>
         <dependencies>
           <dependency>
             <groupId>org.opendaylight.controller</groupId>
index ce91d672888e93e493b010b6476da5be032a44b3..6d2060ef73928f86af0e446d37fa2069f4f90dab 100644 (file)
@@ -22,7 +22,6 @@
       <plugin>
         <groupId>org.codehaus.enunciate</groupId>
         <artifactId>maven-enunciate-plugin</artifactId>
-        <version>${enunciate.version}</version>
         <dependencies>
           <dependency>
             <groupId>org.opendaylight.controller</groupId>
index 1dd6371ee0ad5b3851fe06683da4b1231d9a5098..bc0248d98e0e69b6d1ab77c113d33d623b010d06 100644 (file)
@@ -22,7 +22,6 @@
       <plugin>
         <groupId>org.codehaus.enunciate</groupId>
         <artifactId>maven-enunciate-plugin</artifactId>
-        <version>${enunciate.version}</version>
         <dependencies>
           <dependency>
             <groupId>org.opendaylight.controller</groupId>
index 7ec7afa0457e725532fd86e1fcb0d1f5f7914904..4aa4e0328be3d9051e2cbb4f6f798b1992fd53bd 100644 (file)
@@ -31,7 +31,6 @@
       <plugin>
         <groupId>org.codehaus.enunciate</groupId>
         <artifactId>maven-enunciate-plugin</artifactId>
-        <version>${enunciate.version}</version>
       </plugin>
 
       <plugin>
index 9d2818365f2d835151ddd1f46589e61967493b59..551d3b4877f79b6e29e71f67d9513c923dc0e51d 100644 (file)
@@ -22,7 +22,6 @@
       <plugin>
         <groupId>org.codehaus.enunciate</groupId>
         <artifactId>maven-enunciate-plugin</artifactId>
-        <version>${enunciate.version}</version>
         <dependencies>
           <dependency>
             <groupId>org.opendaylight.controller</groupId>
index 63332f4d22dec483301dc537eccacd610ff6860c..1a3388a796cd7c6c4749bf28024e6d569e5eb20f 100644 (file)
@@ -22,7 +22,6 @@
       <plugin>
         <groupId>org.codehaus.enunciate</groupId>
         <artifactId>maven-enunciate-plugin</artifactId>
-        <version>${enunciate.version}</version>
         <dependencies>
           <dependency>
             <groupId>org.opendaylight.controller</groupId>
index fe0de36554f7d98982b92cfcfad2f1369f52b3f8..71a714717ec630367acf796527b73dcce25d38f7 100644 (file)
@@ -22,7 +22,6 @@
       <plugin>
         <groupId>org.codehaus.enunciate</groupId>
         <artifactId>maven-enunciate-plugin</artifactId>
-        <version>${enunciate.version}</version>
         <dependencies>
           <dependency>
             <groupId>org.opendaylight.controller</groupId>
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
-      <version>${junit.version}</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
index dca8c2f06098cd8d6853337116f0229f4a70f486..3abb5dd0b43967586d594ba81883c1670abee494 100644 (file)
@@ -22,7 +22,6 @@
       <plugin>
         <groupId>org.codehaus.enunciate</groupId>
         <artifactId>maven-enunciate-plugin</artifactId>
-        <version>${enunciate.version}</version>
         <dependencies>
           <dependency>
             <groupId>org.opendaylight.controller</groupId>
index a24f087b75b0dca07e16f6cbe4471f8621b1cb08..c27a68e45b2f9cdd32301f86ceab490f1fca0d1c 100644 (file)
@@ -23,7 +23,6 @@
       <plugin>
         <groupId>org.codehaus.enunciate</groupId>
         <artifactId>maven-enunciate-plugin</artifactId>
-        <version>${enunciate.version}</version>
         <dependencies>
           <dependency>
             <groupId>org.opendaylight.controller</groupId>
index 9c5626cd2049685493e77f56c2525e9e632d6ccf..e20dea437c5983bd1bc3b83617681f481bd67ce3 100644 (file)
@@ -22,7 +22,6 @@
       <plugin>
         <groupId>org.codehaus.enunciate</groupId>
         <artifactId>maven-enunciate-plugin</artifactId>
-        <version>${enunciate.version}</version>
       </plugin>
       <plugin>
         <groupId>org.apache.felix</groupId>
index 554260a3b484cdd496c47dd006d0221088213128..16eafa251ac0f74ae681085f128e678e1d39c61a 100644 (file)
@@ -58,7 +58,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.7.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>equinoxSDK381</groupId>
index 00551a1ce71a115ffa11123eb77fcecd13acc26e..d90559372d4d23715dfcfa0852ef09a7ebc4f78b 100644 (file)
@@ -23,7 +23,6 @@
       <plugin>
         <groupId>org.codehaus.enunciate</groupId>
         <artifactId>maven-enunciate-plugin</artifactId>
-        <version>${enunciate.version}</version>
         <dependencies>
           <dependency>
             <groupId>org.opendaylight.controller</groupId>
index fec6bbe6b466519f9c5e8ed3cc5d89aa2558b66e..d2016b1f6337b6923662268ae7d8029d34ae85b0 100644 (file)
@@ -48,7 +48,7 @@ public class SimpleBroadcastHandlerImpl implements IBroadcastHandler, IListenDat
 
     protected ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
 
-    BroadcastMode mode = BroadcastMode.BROADCAST_TO_NONINTERNAL;
+    BroadcastMode mode = BroadcastMode.DISABLED;
 
     @Override
     public PacketResult receiveDataPacket(RawPacket inPkt) {
index 5cd47f2f20a48cbf75774055267d0f2f90f6b751..2376b8752f1e5d675277024cb98cdc4c25a77b0c 100644 (file)
@@ -314,9 +314,9 @@ public class StatisticsManager implements IStatisticsManager, IReadServiceListen
             try {
                 boolean retStatus;
                 if(oldLatch != null) {
-                    retStatus = oldLatch.await(this.latchTimeout, TimeUnit.SECONDS);
+                    retStatus = oldLatch.await(StatisticsManager.latchTimeout, TimeUnit.SECONDS);
                 } else {
-                    retStatus = newLatch.await(this.latchTimeout, TimeUnit.SECONDS);
+                    retStatus = newLatch.await(StatisticsManager.latchTimeout, TimeUnit.SECONDS);
                 }
                 // log the return code as it will give us, if
                 // the latch timed out.
index 19f45e63c591dbde396e0929141c5c042a55adf5..e457fecfedf9b75d5ec1f59f006d64775472e144 100644 (file)
@@ -1004,7 +1004,8 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
             }
         }
 
-        boolean proactiveForwarding = false;
+        boolean forwardingModeChanged = false;
+
         // copy node properties from config
         if (nodeConfigList != null) {
             String nodeId = node.toString();
@@ -1014,7 +1015,7 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
                 propMap.putAll(nodeProperties);
                 if (nodeProperties.get(ForwardingMode.name) != null) {
                     ForwardingMode mode = (ForwardingMode) nodeProperties.get(ForwardingMode.name);
-                    proactiveForwarding = mode.isProactive();
+                    forwardingModeChanged = mode.isProactive();
                 }
             }
         }
@@ -1023,28 +1024,35 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
             Property defaultMode = new ForwardingMode(ForwardingMode.REACTIVE_FORWARDING);
             propMap.put(ForwardingMode.name, defaultMode);
         }
-        boolean result = false;
-        if (propMapCurr == null) {
-            if (nodeProps.putIfAbsent(node, propMap) == null) {
-                result = true;
-            }
+
+        boolean propsAdded = false;
+        // Attempt initial add
+        if (nodeProps.putIfAbsent(node, propMap) == null) {
+                propsAdded = true;
+
+                /* Notify listeners only for initial node addition
+                 * to avoid expensive tasks triggered by redundant notifications
+                 */
+                notifyNode(node, UpdateType.ADDED, propMap);
         } else {
-            result = nodeProps.replace(node, propMapCurr, propMap);
+
+            propsAdded = nodeProps.replace(node, propMapCurr, propMap);
+
+            // check whether forwarding mode changed
+            if (propMapCurr.get(ForwardingMode.name) != null) {
+                ForwardingMode mode = (ForwardingMode) propMapCurr.get(ForwardingMode.name);
+                forwardingModeChanged ^= mode.isProactive();
+            }
         }
-        if (!result) {
-            log.debug("Cluster conflict: Conflict while adding the node properties. Node: {}  Properties: {}",
-                    node.getID(), props);
+        if (!propsAdded) {
+            log.debug("Cluster conflict while adding node {}. Overwriting with latest props: {}", node.getID(), props);
             addNodeProps(node, propMap);
         }
 
-        // check if span ports are configed
+        // check if span ports are configured
         addSpanPorts(node);
-
-        // notify node listeners
-        notifyNode(node, UpdateType.ADDED, propMap);
-
         // notify proactive mode forwarding
-        if (proactiveForwarding) {
+        if (forwardingModeChanged) {
             notifyModeChange(node, true);
         }
     }
@@ -1054,7 +1062,12 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
         if (nodeProps == null) {
             return;
         }
-        nodeProps.remove(node);
+
+        if (nodeProps.remove(node) == null) {
+            log.debug("Received redundant node REMOVED udate for {}. Skipping..", node);
+            return;
+        }
+
         nodeConnectorNames.remove(node);
         Set<NodeConnector> removeNodeConnectorSet = new HashSet<NodeConnector>();
         for (Map.Entry<NodeConnector, Map<String, Property>> entry : nodeConnectorProps.entrySet()) {
@@ -1149,6 +1162,13 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
 
         switch (type) {
         case ADDED:
+            // Skip redundant ADDED update (e.g. cluster switch-over)
+            if (nodeConnectorProps.containsKey(nodeConnector)) {
+                log.debug("Redundant nodeconnector ADDED for {}, props {} for container {}",
+                        nodeConnector, props, containerName);
+                update = false;
+            }
+
             if (props != null) {
                 for (Property prop : props) {
                     addNodeConnectorProp(nodeConnector, prop);
@@ -1158,6 +1178,7 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
                 addNodeConnectorProp(nodeConnector, null);
             }
 
+
             addSpanPort(nodeConnector);
             break;
         case CHANGED:
@@ -2026,9 +2047,9 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
         // only add if span is configured on this nodeConnector
         for (SpanConfig conf : getSpanConfigList(nodeConnector.getNode())) {
             if (conf.getPortArrayList().contains(nodeConnector)) {
-                List<NodeConnector> ncLists = new ArrayList<NodeConnector>();
-                ncLists.add(nodeConnector);
-                addSpanPorts(nodeConnector.getNode(), ncLists);
+                List<NodeConnector> ncList = new ArrayList<NodeConnector>();
+                ncList.add(nodeConnector);
+                addSpanPorts(nodeConnector.getNode(), ncList);
                 return;
             }
         }
@@ -2149,7 +2170,7 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
     public Set<Switch> getConfiguredNotConnectedSwitches() {
         Set<Switch> configuredNotConnectedSwitches = new HashSet<Switch>();
         if (this.inventoryService == null) {
-            log.trace("inventory service not avaiable");
+            log.trace("inventory service not available");
             return configuredNotConnectedSwitches;
         }
 
index 75fcec5b3cc5e4d9e2804a0bc74da9dd5ae2456f..ea9e599d83c06ef9af96493935f7ebe53081ef97 100644 (file)
@@ -136,6 +136,10 @@ public class UserConfig extends ConfigurationObject implements Serializable {
         return new ArrayList<String>(roles);
     }
 
+    public byte[] getSalt() {
+        return salt.clone();
+    }
+
     @Override
     public int hashCode() {
         final int prime = 31;
index 4c8a6b8439f2b18482a848605e1f5e234a27f8cd..b6a4d0dd543479881d86bc60eac3420ee1e7ce05 100644 (file)
@@ -212,10 +212,12 @@ public class DaylightWebAdmin {
         UserConfig newConfig = gson.fromJson(json, UserConfig.class);
         List<UserConfig> currentUserConfig = userManager.getLocalUserList();
         String password = null;
+        byte[] salt = null;
         String user = newConfig.getUser();
         for (UserConfig userConfig : currentUserConfig) {
             if(userConfig.getUser().equals(user)){
                 password = userConfig.getPassword();
+                salt = userConfig.getSalt();
                 break;
             }
         }
@@ -228,8 +230,9 @@ public class DaylightWebAdmin {
         //The password is stored in hash mode, hence it cannot be retrieved and added to UserConfig object
         //The hashed password is injected below to the json string containing username and new roles before
         //converting to UserConfig object.
-        json = json.replace("\"roles\"", "\"password\":\""+ password + "\",\"roles\"");
         Gson gson = new Gson();
+        json = json.replace("\"roles\"", "\"salt\":" + gson.toJson(salt, salt.getClass()) + ",\"password\":\""+ password + "\",\"roles\"");
+
         newConfig = gson.fromJson(json, UserConfig.class);
 
         Status result = userManager.modifyLocalUser(newConfig);
index b601eef4b5ef134423d563c86327aabd201bd495..f67828bdab68fb678a67c038568b34d3a87321af 100644 (file)
     <version>1.1-SNAPSHOT</version>
     <packaging>bundle</packaging>
 
-    <properties>
-        <ganymed.version>build209</ganymed.version>
-    </properties>
-
     <dependencies>
         <dependency>
             <groupId>org.osgi</groupId>