Add single layer deserialization support 04/51304/35
authordeathbeam <tomas.slusny@pantheon.tech>
Mon, 30 Jan 2017 18:16:45 +0000 (19:16 +0100)
committerTomas Slusny <tomas.slusny@pantheon.tech>
Wed, 22 Feb 2017 12:51:50 +0000 (13:51 +0100)
  - Update MultiMsgCollector to support multiple reply types
  - Update DeviceContext to support mulyiple reply types
  - Update AbstractService and MultipartService* implementations
    to support multiple reply types
  - Update GroupDirectStatisticsService
  - Update FlowDirectStatisticsService
  - Update MeterDirectStatisticsService
  - Update PortDirectStatisticsService
  - Update QueueDirectStatisticsService
  - Update SalExperimenterMpMessageService
  - Update SalTableService
  - Change giant StatisticsGatheringUtils to separate statistics
    writers and add support for writing both deserialization paths
  - Refactor structure of services because of a lot of new classes
    added, it became mess
  - Create new initialization chain for device that supports both
    deserialization paths

Resolves: bug 7141

Change-Id: I21b9b894d89db220ccf20ebb031fcb9e039b184a
Signed-off-by: Tomas Slusny <tomas.slusny@pantheon.tech>
186 files changed:
model/model-flow-statistics/src/main/yang/opendaylight-flow-table-statistics.yang
model/model-flow-statistics/src/main/yang/opendaylight-port-statistics.yang
model/model-flow-statistics/src/main/yang/opendaylight-queue-statistics.yang
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceContext.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/handlers/DeviceReplyProcessor.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/handlers/MultiMsgCollector.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/statistics/ofpspecific/StatisticsGatherer.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/common/MultipartReplyTranslatorUtil.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/SinglePurposeMultipartReplyTranslator.java with 54% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/common/NodeConnectorTranslatorUtil.java [deleted file]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/common/NodeStaticReplyTranslatorUtil.java [deleted file]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/MultipartWriterProvider.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/MultipartWriterProviderFactory.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/AbstractMultipartWriter.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/DescMultipartWriter.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/FlowStatsMultipartWriter.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/GroupDescMultipartWriter.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/GroupFeaturesMultipartWriter.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/GroupStatsMultipartWriter.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/MeterConfigMultipartWriter.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/MeterFeaturesMultipartWriter.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/MeterStatsMultipartWriter.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/PortDescMultipartWriter.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/PortStatsMultipartWriter.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/QueueStatsMultipartWriter.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/TableFeaturesMultipartWriter.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/TableStatsMultipartWriter.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/AbstractDeviceInitializer.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/DeviceInitializerProvider.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/DeviceInitializerProviderFactory.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/OF10DeviceInitializer.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/OF13DeviceInitializer.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/listener/MultiMsgCollectorImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/DeserializerInjector.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyGroupDescDeserializer.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractAggregateFlowMultipartService.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/MatchingFlowsInTableService.java with 78% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractExperimenterMultipartService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractMessageService.java [deleted file]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractMultipartCollectorService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractMultipartOnTheFlyService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractMultipartRequestCallback.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/MultipartRequestCallback.java with 50% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractMultipartRequestOnTheFlyCallback.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractMultipartService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractRequestCallback.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractSilentErrorService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractTableMultipartService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractVoidService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/EchoService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/MultipartRequestOnTheFlyCallback.java [deleted file]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/RoleService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalTableServiceImpl.java [deleted file]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SimpleRequestCallback.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/VoidRequestCallback.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerAggregateFlowMultipartService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerExperimenterMultipartService.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalExperimenterMpMessageServiceImpl.java with 68% similarity, mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerFlowMultipartRequestOnTheFlyCallback.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerFlowService.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/FlowService.java with 83% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerGroupService.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/GroupService.java with 75% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerMeterService.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/MeterService.java with 74% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerMultipartCollectorService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerMultipartRequestCallback.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerTableMultipartService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/FlowCapableTransactionServiceImpl.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/FlowCapableTransactionServiceImpl.java with 89% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/NodeConfigServiceImpl.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/NodeConfigServiceImpl.java with 91% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/PacketProcessingServiceImpl.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/PacketProcessingServiceImpl.java with 91% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalEchoServiceImpl.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalEchoServiceImpl.java with 96% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalExperimenterMessageServiceImpl.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalExperimenterMessageServiceImpl.java with 94% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalExperimenterMpMessageServiceImpl.java [new file with mode: 0755]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalFlatBatchServiceImpl.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalFlatBatchServiceImpl.java with 99% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalFlowServiceImpl.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalFlowServiceImpl.java with 91% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalFlowsBatchServiceImpl.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalFlowsBatchServiceImpl.java with 99% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalGroupServiceImpl.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalGroupServiceImpl.java with 76% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalGroupsBatchServiceImpl.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalGroupsBatchServiceImpl.java with 99% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalMeterServiceImpl.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalMeterServiceImpl.java with 76% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalMetersBatchServiceImpl.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalMetersBatchServiceImpl.java with 99% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalPortServiceImpl.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalPortServiceImpl.java with 84% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalRoleServiceImpl.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalRoleServiceImpl.java with 96% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalTableServiceImpl.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerAggregateFlowMultipartService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerExperimenterMultipartService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerFlowMultipartRequestOnTheFlyCallback.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerFlowService.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/FlowMessageService.java with 82% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerGroupService.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/GroupMessageService.java with 76% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerMeterService.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/MeterMessageService.java with 72% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerMultipartCollectorService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerMultipartRequestCallback.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerPortService.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/PortMessageService.java with 68% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerTableMultipartService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/util/RequestContextUtil.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/RequestContextUtil.java with 96% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/util/RequestInputUtils.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/RequestInputUtils.java with 95% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/util/ServiceException.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/ServiceException.java with 91% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsGatheringUtils.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsManagerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/AggregateFlowsInTableService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/AllFlowsInAllTablesService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/AllFlowsInTableService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/AllGroupsStatsService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/AllMeterConfigStatsService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/AllMeterStatsService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/AllPortStatsService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/AllQueuesAllPortsService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/AllQueuesOnePortService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/FlowsInTableService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/GroupDescriptionService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/GroupFeaturesService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/GroupStatsService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/MeterFeaturesService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/MeterStatsService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/OneQueueOnePortService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/OpendaylightFlowStatisticsServiceImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/OpendaylightFlowTableStatisticsServiceImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/PortStatsService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/compatibility/AbstractCompatibleStatService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/dedicated/StatisticsGatheringOnTheFlyService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/dedicated/StatisticsGatheringService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractDirectStatisticsService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractFlowDirectStatisticsService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractGroupDirectStatisticsService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractMeterDirectStatisticsService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractPortDirectStatisticsService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractQueueDirectStatisticsService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/FlowDirectStatisticsService.java [deleted file]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/GroupDirectStatisticsService.java [deleted file]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/MeterDirectStatisticsService.java [deleted file]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/NodeConnectorDirectStatisticsService.java [deleted file]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/OpendaylightDirectStatisticsServiceImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/OpendaylightDirectStatisticsServiceProvider.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/QueueDirectStatisticsService.java [deleted file]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/FlowDirectStatisticsService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/GroupDirectStatisticsService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/MeterDirectStatisticsService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/MultiLayerDirectStatisticsProviderInitializer.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/PortDirectStatisticsService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/QueueDirectStatisticsService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/singlelayer/FlowDirectStatisticsService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/singlelayer/GroupDirectStatisticsService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/singlelayer/MeterDirectStatisticsService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/singlelayer/PortDirectStatisticsService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/singlelayer/QueueDirectStatisticsService.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/singlelayer/SingleLayerDirectStatisticsProviderInitializer.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtil.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtils.java [deleted file]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/MdSalRegistrationUtils.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/common/NodeConnectorTranslatorUtilTest.java [deleted file]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/listener/MultiMsgCollectorImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/AbstractDeserializerTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/MultipartRequestCallbackTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/MultipartRequestOnTheFlyCallbackTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalExperimenterMpMessageServiceImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/FlowCapableTransactionServiceImplTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/FlowCapableTransactionServiceImplTest.java with 83% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/NodeConfigServiceImplTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/NodeConfigServiceImplTest.java with 87% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/PacketProcessingServiceImplTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/PacketProcessingServiceImplTest.java with 93% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalEchoServiceImplTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalEchoServiceImplTest.java with 90% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalExperimenterMessageServiceImplTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalExperimenterMessageServiceImplTest.java with 92% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalFlatBatchServiceImplTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalFlatBatchServiceImplTest.java with 99% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalFlowServiceImplTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalFlowServiceImplTest.java with 98% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalFlowsBatchServiceImplTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalFlowsBatchServiceImplTest.java with 98% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalGroupServiceImplTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalGroupServiceImplTest.java with 96% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalGroupsBatchServiceImplTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalGroupsBatchServiceImplTest.java with 98% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalMeterServiceImplTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalMeterServiceImplTest.java with 96% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalMetersBatchServiceImplTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalMetersBatchServiceImplTest.java with 98% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalPortServiceImplTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalPortServiceImplTest.java with 93% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalRoleServiceImplTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalRoleServiceImplTest.java with 97% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalTableServiceImplTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalTableServiceImplTest.java with 95% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/MultipartReplyTranslatorTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/SinglePurposeMultipartReplyTranslatorTest.java with 80% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsContextImpMockInitiation.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsContextImplParamTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsContextImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsGatheringUtilsTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/AbstractSingleStatsServiceTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/compatibility/AbstractCompatibleStatServiceTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/dedicated/StatisticsGatheringOnTheFlyServiceTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractDirectStatisticsServiceTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/OpendaylightDirectStatisticsServiceImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/FlowDirectStatisticsServiceTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/FlowDirectStatisticsServiceTest.java with 92% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/GroupDirectStatisticsServiceTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/GroupDirectStatisticsServiceTest.java with 91% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/MeterDirectStatisticsServiceTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/MeterDirectStatisticsServiceTest.java with 91% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/NodeConnectorDirectStatisticsServiceTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/NodeConnectorDirectStatisticsServiceTest.java with 90% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/QueueDirectStatisticsServiceTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/QueueDirectStatisticsServiceTest.java with 91% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtilsTest.java [deleted file]

index 025b9a4b31531abc8e2249b4e897b033f5129809..96e4e8d55a7ed3cf454665e44f73902cbfc73953 100644 (file)
@@ -34,8 +34,7 @@ module opendaylight-flow-table-statistics {
     }
 
     grouping flow-table-and-statistics-map {
-        status deprecated;
-        description "RPC calls to fetch flow table statistics.";
+        description "List of flow table and statistic map.";
 
         list flow-table-and-statistics-map {
             key "table-id";
index e23467031a118d3a097d75aef8f573277a84dc12..e63f1bd7af3e94d9e9eb4a03cb9fe97841a8e127 100644 (file)
@@ -64,8 +64,6 @@ module opendaylight-port-statistics {
 
     //Notification for node connector statistics update
     grouping node-connector-statistics-and-port-number-map {
-        status deprecated;
-
         description "List of map - node connectors and their statistics";
         list node-connector-statistics-and-port-number-map {
             key "node-connector-id";
index 2bd06816196cfd0bd9f944d20f7f08ffc42273fc..0768119a88089e6cd049e5a94e5bef2286715df2 100644 (file)
@@ -36,8 +36,6 @@ module opendaylight-queue-statistics {
 
     //RPC calls to fetch queue statistics
     grouping queue-id-and-statistics-map {
-        status deprecated;
-
         list queue-id-and-statistics-map {
             key "queue-id node-connector-id";
             leaf queue-id {
index b26a7addb87910cff8cd3f944e1d0efcf44b4d89..efd6fe4e7a3bf3d6c12da669f22c75e03ffecdac 100644 (file)
@@ -21,7 +21,7 @@ import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgColl
 import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
 import org.opendaylight.openflowplugin.api.openflow.registry.ItemLifeCycleRegistry;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SalRoleService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleOutput;
 import org.opendaylight.yangtools.yang.common.RpcResult;
@@ -107,7 +107,7 @@ public interface DeviceContext extends
 
     MessageSpy getMessageSpy();
 
-    MultiMsgCollector getMultiMsgCollector(final RequestContext<List<MultipartReply>> requestContext);
+    <T extends OfHeader> MultiMsgCollector<T> getMultiMsgCollector(final RequestContext<List<T>> requestContext);
 
     /**
      * indicates that device context is fully published (e.g.: packetIn messages should be passed)
@@ -146,6 +146,6 @@ public interface DeviceContext extends
      */
     ListenableFuture<RpcResult<SetRoleOutput>> makeDeviceSlave();
 
-    boolean isUseSingleLayerSerialization();
+    boolean canUseSingleLayerSerialization();
 }
 
index e6f581f7060a99d5e9df1db22e857e40c3c152db..90f138d0b7961adc4ead9c6b88cc481ad647f775 100644 (file)
@@ -12,7 +12,6 @@ import java.util.List;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemoved;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
@@ -32,36 +31,36 @@ public interface DeviceReplyProcessor {
     /**
      * Method that set future to context in Map
      *
-     * @param xid,
-     * @param ofHeaderList
+     * @param xid xid
+     * @param ofHeaderList openflow header list
      */
-    void processReply(Xid xid, List<MultipartReply> ofHeaderList);
+    void processReply(Xid xid, List<? extends OfHeader> ofHeaderList);
 
     /**
      * Method process async flow removed from device
      *
-     * @param flowRemoved
+     * @param flowRemoved flow removed
      */
     void processFlowRemovedMessage(FlowRemoved flowRemoved);
 
     /**
      * Method process async port status from device
      *
-     * @param portStatus
+     * @param portStatus port status
      */
     void processPortStatusMessage(PortStatusMessage portStatus);
 
     /**
      * Method process async packet in from device
      *
-     * @param packetInMessage
+     * @param packetInMessage packet in message
      */
     void processPacketInMessage(PacketInMessage packetInMessage);
 
     /**
      * Processing of experimenter symmetric message from device
      *
-     * @param notification
+     * @param notification notification
      */
     void processExperimenterMessage(ExperimenterMessage notification);
 }
index 6d597eb931a184e6db0bc20c7338f36f12e552de..de21d2575e63f7515a595e57f34f60343556efd3 100644 (file)
@@ -9,8 +9,9 @@
 package org.opendaylight.openflowplugin.api.openflow.device.handlers;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 
 /**
  * <p>
@@ -24,24 +25,24 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
  *         </p>
  *         Created: Mar 23, 2015
  */
-public interface MultiMsgCollector {
+public interface MultiMsgCollector<T extends OfHeader> {
     /**
      * Method adds a reply multipart message to the collection and if the message has marker
      * "I'M A LAST" method set whole Collection to Future object and remove from cache.
      *
-     * @param reply
+     * @param reply reply
+     * @param reqMore request more replies
+     * @param eventIdentifier event identifier
      */
-    void addMultipartMsg(@Nonnull MultipartReply reply);
-
-    void addMultipartMsg(@Nonnull MultipartReply reply, @Nonnull EventIdentifier eventIdentifier);
+    void addMultipartMsg(@Nonnull T reply, boolean reqMore, @Nullable EventIdentifier eventIdentifier);
 
     /**
      * Null response could be a valid end multipart collecting event for barrier response scenario.
      * We are not able to resolve an issue (it is or it isn't barrier scenario) so we have to finish
      * collecting multipart messages successfully.
+     *
+     * @param eventIdentifier event identifier
      */
-    void endCollecting();
-
-    void endCollecting(EventIdentifier eventIdentifier);
+    void endCollecting(@Nullable EventIdentifier eventIdentifier);
 
 }
index b7733ad2deafe0236b59a5a7617199d81d2e565e..d9157d2ec3b5caddfd3e46daf30114b2c6cd5d5a 100644 (file)
@@ -8,15 +8,12 @@
 
 package org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific;
 
+import com.google.common.util.concurrent.ListenableFuture;
 import java.util.List;
-import java.util.concurrent.Future;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 
-/**
- * Created by mirehak on 6/2/15.
- */
-public interface StatisticsGatherer {
-    Future<RpcResult<List<MultipartReply>>> getStatisticsOfType(EventIdentifier eventIdentifier, MultipartType type);
+public interface StatisticsGatherer<T extends OfHeader> {
+    ListenableFuture<RpcResult<List<T>>> getStatisticsOfType(EventIdentifier eventIdentifier, MultipartType type);
 }
index 2b647610c993542039c474fe07fa9c252f26b9c5..1864a2c38fe93b90cc94715cf0f6afaed127698d 100644 (file)
@@ -45,6 +45,8 @@ import org.opendaylight.openflowplugin.extension.api.OpenFlowPluginExtensionRegi
 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterManager;
 import org.opendaylight.openflowplugin.impl.connection.ConnectionManagerImpl;
 import org.opendaylight.openflowplugin.impl.device.DeviceManagerImpl;
+import org.opendaylight.openflowplugin.impl.device.initialization.DeviceInitializerProvider;
+import org.opendaylight.openflowplugin.impl.device.initialization.DeviceInitializerProviderFactory;
 import org.opendaylight.openflowplugin.impl.protocol.deserialization.DeserializerInjector;
 import org.opendaylight.openflowplugin.impl.protocol.serialization.SerializerInjector;
 import org.opendaylight.openflowplugin.impl.rpc.RpcManagerImpl;
@@ -98,6 +100,7 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF
     private long basicTimerDelay;
     private long maximumTimerDelay;
     private boolean useSingleLayerSerialization = false;
+    private final DeviceInitializerProvider deviceInitializerProvider;
 
     private final ThreadPoolExecutor threadPool;
     private ClusterSingletonServiceProvider singletonServicesProvider;
@@ -119,7 +122,9 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF
                 Preconditions.checkNotNull(threadPoolMaxThreads),
                 Preconditions.checkNotNull(threadPoolTimeout), TimeUnit.SECONDS,
                 new SynchronousQueue<>(), "ofppool");
+
         convertorManager = ConvertorManagerFactory.createDefaultManager();
+        deviceInitializerProvider = DeviceInitializerProviderFactory.createDefaultProvider();
     }
 
     @Override
@@ -253,7 +258,8 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF
                 hashedWheelTimer,
                 convertorManager,
                 skipTableFeatures,
-                useSingleLayerSerialization);
+                useSingleLayerSerialization,
+                deviceInitializerProvider);
 
         ((ExtensionConverterProviderKeeper) deviceManager).setExtensionConverterProvider(extensionConverterManager);
 
@@ -1,37 +1,53 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics;
+
+package org.opendaylight.openflowplugin.impl.common;
 
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
+import java.util.stream.Collectors;
+import javax.annotation.Nullable;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
+import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
+import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
+import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
 import org.opendaylight.openflowplugin.extension.api.path.MatchPath;
 import org.opendaylight.openflowplugin.impl.util.GroupUtil;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.FlowStatsResponseConvertorData;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionDatapathIdConvertorData;
 import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsUpdateBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.multipart.reply.multipart.reply.body.MultipartReplyDescBuilder;
 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.table.statistics.rev131215.FlowTableStatisticsUpdateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.multipart.reply.multipart.reply.body.MultipartReplyFlowAggregateStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.multipart.reply.multipart.reply.body.MultipartReplyFlowAggregateStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.multipart.reply.multipart.reply.body.MultipartReplyFlowStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.multipart.reply.multipart.reply.body.MultipartReplyFlowStatsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMapBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.multipart.reply.multipart.reply.body.MultipartReplyFlowTableStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.multipart.reply.multipart.reply.body.MultipartReplyFlowTableStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.multipart.reply.multipart.reply.body.MultipartReplyPortDesc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.multipart.reply.multipart.reply.body.MultipartReplyPortDescBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.multipart.reply.multipart.reply.body.multipart.reply.port.desc.PortsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.queue.rev130925.QueueId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupDescStatsUpdatedBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupFeaturesUpdatedBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyGroupDescBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyGroupFeaturesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyGroupStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyGroupStatsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Chaining;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.ChainingChecks;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupAll;
@@ -44,10 +60,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Selec
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.SelectWeight;
 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.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterConfigStatsUpdatedBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterFeaturesUpdatedBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterStatisticsUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyMeterConfigBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyMeterFeaturesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyMeterStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyMeterStatsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBand;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBandDrop;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBandDscpRemark;
@@ -60,10 +76,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.duration.DurationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.BytesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.PacketsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortGrouping;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyAggregateCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyFlowCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupDescCase;
@@ -71,10 +89,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterConfigCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterFeaturesCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortDescCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortStatsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyQueueCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyTableCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyTableFeaturesCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.aggregate._case.MultipartReplyAggregate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDesc;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.MultipartReplyFlow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.MultipartReplyGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.desc._case.MultipartReplyGroupDesc;
@@ -88,134 +109,174 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.multipart.reply.queue.QueueStats;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table._case.MultipartReplyTable;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table._case.multipart.reply.table.TableStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table.features._case.MultipartReplyTableFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.multipart.reply.multipart.reply.body.MultipartReplyPortStatsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.QueueStatisticsUpdateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.multipart.reply.multipart.reply.body.MultipartReplyQueueStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.multipart.reply.multipart.reply.body.MultipartReplyQueueStatsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.multipart.reply.multipart.reply.body.MultipartReplyTableFeaturesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Class converts multipart reply messages to the notification objects defined
- * by statistics provider (manager ). It is ment to be replaced by translators
- * and to be used for translating statistics data only.
- *
- * @author avishnoi@in.ibm.com
+ * Class converts multipart reply messages to the objects that can be then written to datastore using
+ * multipart writers
  */
-@Deprecated
-public class SinglePurposeMultipartReplyTranslator {
-
-    protected static final Logger logger = LoggerFactory
-            .getLogger(SinglePurposeMultipartReplyTranslator.class);
-    private final ConvertorExecutor convertorExecutor;
+public class MultipartReplyTranslatorUtil {
+    private static final Logger LOG = LoggerFactory.getLogger(MultipartReplyTranslatorUtil.class);
+
+    public static Optional<? extends MultipartReplyBody> translate(final OfHeader message,
+                                                                   final DeviceInfo deviceInfo,
+                                                                   @Nullable final ConvertorExecutor convertorExecutor,
+                                                                   @Nullable final TranslatorLibrary translatorLibrary) {
+        if (message instanceof MultipartReply) {
+            final Optional<ConvertorExecutor> convertor = Optional.ofNullable(convertorExecutor);
+            final Optional<TranslatorLibrary> translator = Optional.ofNullable(translatorLibrary);
+            final MultipartReply msg = MultipartReply.class.cast(message);
+            final OpenflowVersion ofVersion = OpenflowVersion.get(deviceInfo.getVersion());
+            final VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(deviceInfo.getVersion());
+            data.setDatapathId(deviceInfo.getDatapathId());
+
+            switch (msg.getType()) {
+                case OFPMPFLOW:
+                    return convertor.flatMap(c -> Optional.of(translateFlow(msg, data, c)));
+                case OFPMPAGGREGATE:
+                    return Optional.of(translateAggregate(msg));
+                case OFPMPPORTSTATS:
+                    return Optional.of(translatePortStats(msg, ofVersion, deviceInfo.getDatapathId()));
+                case OFPMPGROUP:
+                    return convertor.flatMap(c -> Optional.of(translateGroup(msg, data, c)));
+                case OFPMPGROUPDESC:
+                    return convertor.flatMap(c -> Optional.of(translateGroupDesc(msg, data, c)));
+                case OFPMPGROUPFEATURES:
+                    return Optional.of(translateGroupFeatures(msg));
+                case OFPMPMETER:
+                    return convertor.flatMap(c -> Optional.of(translateMeter(msg, data, c)));
+                case OFPMPMETERCONFIG:
+                    return convertor.flatMap(c -> Optional.of(translateMeterConfig(msg, data, c)));
+                case OFPMPMETERFEATURES:
+                    return Optional.of(translateMeterFeatures(msg));
+                case OFPMPTABLE:
+                    return Optional.of(translateTable(msg));
+                case OFPMPQUEUE:
+                    return Optional.of(translateQueue(msg, ofVersion, deviceInfo.getDatapathId()));
+                case OFPMPDESC:
+                    return Optional.of(translateDesc(msg));
+                case OFPMPTABLEFEATURES:
+                    return convertor.flatMap(c -> Optional.of(translateTableFeatures(msg, deviceInfo.getVersion(), c)));
+                case OFPMPPORTDESC:
+                    return translator.flatMap(t -> Optional.of(translatePortDesc(msg, deviceInfo, t)));
+            }
+        } else if (message instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112
+            .MultipartReply) {
+            return Optional.of(org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112
+                .MultipartReply.class.cast(message).getMultipartReplyBody());
+        }
 
-    public SinglePurposeMultipartReplyTranslator(ConvertorExecutor convertorExecutor) {
-        this.convertorExecutor = convertorExecutor;
+        LOG.debug("Failed to translate {} for node {}.", message.getImplementedInterface(), deviceInfo.getLOGValue());
+        return Optional.empty();
     }
 
-    public List<DataObject> translate(final BigInteger datapathId, final short version, final OfHeader msg) {
-
-        List<DataObject> listDataObject = new ArrayList<>();
-
-        if (msg instanceof MultipartReplyMessage) {
-            MultipartReplyMessage mpReply = (MultipartReplyMessage) msg;
-            OpenflowVersion ofVersion = OpenflowVersion.get(version);
-            NodeId node = nodeIdFromDatapathId(datapathId);
-            VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(version);
-            data.setDatapathId(datapathId);
-
-            translateFlow(listDataObject, mpReply, node, data);
-            translateAggregate(listDataObject, mpReply, node);
-            translatePortStats(listDataObject, mpReply, node, ofVersion, datapathId);
-            translateGroup(listDataObject, mpReply, node, data);
-            translateGroupDesc(listDataObject, mpReply, node, data);
-            translateGroupFeatures(listDataObject, mpReply, node);
-            translateMeter(listDataObject, mpReply, node, data);
-            translateMeterConfig(listDataObject, mpReply, node, data);
-            translateMeterFeatures(listDataObject, mpReply, node);
-            translateTable(listDataObject, mpReply, node);
-            translateQueue(listDataObject, mpReply, node, ofVersion, datapathId);
-        }
+    private static MultipartReplyPortDesc translatePortDesc(final MultipartReply msg,
+                                                            final DeviceInfo deviceInfo,
+                                                            final TranslatorLibrary translatorLibrary) {
+        return new MultipartReplyPortDescBuilder()
+            .setPorts(((MultipartReplyPortDescCase) msg.getMultipartReplyBody())
+                .getMultipartReplyPortDesc()
+                .getPorts()
+                .stream()
+                .map(port -> {
+                    final TranslatorKey translatorKey = new TranslatorKey(
+                        deviceInfo.getVersion(),
+                        PortGrouping.class.getName());
+
+                    final MessageTranslator<PortGrouping, FlowCapableNodeConnector> translator = translatorLibrary
+                        .lookupTranslator(translatorKey);
+
+                    return new PortsBuilder(translator
+                        .translate(port, deviceInfo, null))
+                        .build();
+                })
+                .collect(Collectors.toList()))
+            .build();
+    }
 
-        return listDataObject;
+    private static org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.multipart.reply.multipart.reply.body
+        .MultipartReplyTableFeatures translateTableFeatures(final MultipartReply msg,
+                                                            final short version,
+                                                            final ConvertorExecutor convertorExecutor) {
+        MultipartReplyTableFeaturesCase caseBody = (MultipartReplyTableFeaturesCase) msg.getMultipartReplyBody();
+        final MultipartReplyTableFeatures multipartReplyTableFeatures = caseBody.getMultipartReplyTableFeatures();
+        final Optional<List<org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features
+            .TableFeatures>> tableFeaturesList = convertorExecutor
+            .convert(multipartReplyTableFeatures, new VersionConvertorData(version));
+
+        return new MultipartReplyTableFeaturesBuilder()
+            .setTableFeatures(tableFeaturesList.orElse(Collections.emptyList()))
+            .build();
     }
 
-    private void translateFlow(final List<DataObject> listDataObject,
-                               final MultipartReplyMessage mpReply,
-                               final NodeId node, VersionDatapathIdConvertorData data) {
-        if (!MultipartType.OFPMPFLOW.equals(mpReply.getType())) {
-            return;
-        }
+    private static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.multipart.reply.multipart.reply.body
+        .MultipartReplyDesc translateDesc(final MultipartReply msg) {
+        final MultipartReplyDesc desc = ((MultipartReplyDescCase) msg.getMultipartReplyBody()).getMultipartReplyDesc();
+
+        return new MultipartReplyDescBuilder()
+            .setDescription(desc.getDpDesc())
+            .setHardware(desc.getHwDesc())
+            .setManufacturer(desc.getMfrDesc())
+            .setSoftware(desc.getSwDesc())
+            .setSerialNumber(desc.getSerialNum())
+            .build();
+    }
 
+    private static MultipartReplyFlowStats translateFlow(final MultipartReply msg,
+                                                         final VersionDatapathIdConvertorData data,
+                                                         final ConvertorExecutor convertorExecutor) {
         FlowStatsResponseConvertorData flowData = new FlowStatsResponseConvertorData(data.getVersion());
         flowData.setDatapathId(data.getDatapathId());
         flowData.setMatchPath(MatchPath.FLOWSSTATISTICSUPDATE_FLOWANDSTATISTICSMAPLIST_MATCH);
-        FlowsStatisticsUpdateBuilder message = new FlowsStatisticsUpdateBuilder();
-        message.setId(node);
-        message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
-        message.setTransactionId(generateTransactionId(mpReply.getXid()));
-        MultipartReplyFlowCase caseBody = (MultipartReplyFlowCase) mpReply.getMultipartReplyBody();
+        MultipartReplyFlowStatsBuilder message = new MultipartReplyFlowStatsBuilder();
+        MultipartReplyFlowCase caseBody = (MultipartReplyFlowCase) msg.getMultipartReplyBody();
         MultipartReplyFlow replyBody = caseBody.getMultipartReplyFlow();
         final Optional<List<FlowAndStatisticsMapList>> flowAndStatisticsMapLists =
-                convertorExecutor.convert(replyBody.getFlowStats(), flowData);
+            convertorExecutor.convert(replyBody.getFlowStats(), flowData);
 
         message.setFlowAndStatisticsMapList(flowAndStatisticsMapLists.orElse(Collections.emptyList()));
-
-        listDataObject.add(message.build());
+        return message.build();
     }
 
-    private void translateAggregate(final List<DataObject> listDataObject,
-                                    final MultipartReplyMessage mpReply,
-                                    final NodeId node) {
-        if (!MultipartType.OFPMPAGGREGATE.equals(mpReply.getType())) {
-            return;
-        }
-
-        AggregateFlowStatisticsUpdateBuilder message = new AggregateFlowStatisticsUpdateBuilder();
-        message.setId(node);
-        message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
-        message.setTransactionId(generateTransactionId(mpReply.getXid()));
-
-        MultipartReplyAggregateCase caseBody = (MultipartReplyAggregateCase) mpReply.getMultipartReplyBody();
+    private static MultipartReplyFlowAggregateStats translateAggregate(final MultipartReply msg) {
+        MultipartReplyFlowAggregateStatsBuilder message = new MultipartReplyFlowAggregateStatsBuilder();
+        MultipartReplyAggregateCase caseBody = (MultipartReplyAggregateCase) msg.getMultipartReplyBody();
         MultipartReplyAggregate replyBody = caseBody.getMultipartReplyAggregate();
         message.setByteCount(new Counter64(replyBody.getByteCount()));
         message.setPacketCount(new Counter64(replyBody.getPacketCount()));
         message.setFlowCount(new Counter32(replyBody.getFlowCount()));
-
-        listDataObject.add(message.build());
+        return message.build();
     }
 
-    private void translatePortStats(final List<DataObject> listDataObject,
-                                    final MultipartReplyMessage mpReply,
-                                    final NodeId node,
-                                    final OpenflowVersion ofVersion,
-                                    final BigInteger datapathId) {
-        if (!MultipartType.OFPMPPORTSTATS.equals(mpReply.getType())) {
-            return;
-        }
-
-        NodeConnectorStatisticsUpdateBuilder message = new NodeConnectorStatisticsUpdateBuilder();
-        message.setId(node);
-        message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
-        message.setTransactionId(generateTransactionId(mpReply.getXid()));
-
-        MultipartReplyPortStatsCase caseBody = (MultipartReplyPortStatsCase) mpReply.getMultipartReplyBody();
+    private static org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.multipart.reply.multipart.reply.body
+        .MultipartReplyPortStats translatePortStats(final MultipartReply msg,
+                                                    final OpenflowVersion ofVersion,
+                                                    final BigInteger datapathId) {
+        MultipartReplyPortStatsBuilder message = new MultipartReplyPortStatsBuilder();
+        MultipartReplyPortStatsCase caseBody = (MultipartReplyPortStatsCase) msg.getMultipartReplyBody();
         MultipartReplyPortStats replyBody = caseBody.getMultipartReplyPortStats();
 
         List<NodeConnectorStatisticsAndPortNumberMap> statsMap =
-                new ArrayList<>();
+            new ArrayList<>();
         for (PortStats portStats : replyBody.getPortStats()) {
 
             NodeConnectorStatisticsAndPortNumberMapBuilder statsBuilder =
-                    new NodeConnectorStatisticsAndPortNumberMapBuilder();
+                new NodeConnectorStatisticsAndPortNumberMapBuilder();
             statsBuilder.setNodeConnectorId(
-                    InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(datapathId,
-                            portStats.getPortNo(), ofVersion));
+                InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(datapathId,
+                    portStats.getPortNo(), ofVersion));
 
             BytesBuilder bytesBuilder = new BytesBuilder();
             bytesBuilder.setReceived(portStats.getRxBytes());
@@ -250,69 +311,46 @@ public class SinglePurposeMultipartReplyTranslator {
         message.setNodeConnectorStatisticsAndPortNumberMap(statsMap);
 
 
-        listDataObject.add(message.build());
+        return message.build();
     }
 
-    private void translateGroup(final List<DataObject> listDataObject,
-                                final MultipartReplyMessage mpReply,
-                                final NodeId node,
-                                final VersionDatapathIdConvertorData data) {
-        if (!MultipartType.OFPMPGROUP.equals(mpReply.getType())) {
-            return;
-        }
-
-        GroupStatisticsUpdatedBuilder message = new GroupStatisticsUpdatedBuilder();
-        message.setId(node);
-        message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
-        message.setTransactionId(generateTransactionId(mpReply.getXid()));
-        MultipartReplyGroupCase caseBody = (MultipartReplyGroupCase) mpReply.getMultipartReplyBody();
+    private static MultipartReplyGroupStats translateGroup(final MultipartReply msg,
+                                                           final VersionDatapathIdConvertorData data,
+                                                           final ConvertorExecutor convertorExecutor) {
+        MultipartReplyGroupStatsBuilder message = new MultipartReplyGroupStatsBuilder();
+        MultipartReplyGroupCase caseBody = (MultipartReplyGroupCase) msg.getMultipartReplyBody();
         MultipartReplyGroup replyBody = caseBody.getMultipartReplyGroup();
         final Optional<List<GroupStats>> groupStatsList = convertorExecutor.convert(
-                replyBody.getGroupStats(), data);
+            replyBody.getGroupStats(), data);
 
         message.setGroupStats(groupStatsList.orElse(Collections.emptyList()));
 
-        listDataObject.add(message.build());
+        return message.build();
     }
 
-    private void translateGroupDesc(final List<DataObject> listDataObject,
-                                    final MultipartReplyMessage mpReply,
-                                    final NodeId node,
-                                    final VersionDatapathIdConvertorData data) {
-        if (!MultipartType.OFPMPGROUPDESC.equals(mpReply.getType())) {
-            return;
-        }
-
-        GroupDescStatsUpdatedBuilder message = new GroupDescStatsUpdatedBuilder();
-        message.setId(node);
-        message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
-        message.setTransactionId(generateTransactionId(mpReply.getXid()));
-        MultipartReplyGroupDescCase caseBody = (MultipartReplyGroupDescCase) mpReply.getMultipartReplyBody();
+    private static org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply.multipart.reply.body
+        .MultipartReplyGroupDesc translateGroupDesc(final MultipartReply msg,
+                                                    final VersionDatapathIdConvertorData data,
+                                                    final ConvertorExecutor convertorExecutor) {
+        MultipartReplyGroupDescBuilder message = new MultipartReplyGroupDescBuilder();
+        MultipartReplyGroupDescCase caseBody = (MultipartReplyGroupDescCase) msg.getMultipartReplyBody();
         MultipartReplyGroupDesc replyBody = caseBody.getMultipartReplyGroupDesc();
 
         final Optional<List<GroupDescStats>> groupDescStatsList = convertorExecutor.convert(
-                replyBody.getGroupDesc(), data);
+            replyBody.getGroupDesc(), data);
 
         message.setGroupDescStats(groupDescStatsList.orElse(Collections.emptyList()));
 
-        listDataObject.add(message.build());
+        return message.build();
     }
 
-    private void translateGroupFeatures(final List<DataObject> listDataObject,
-                                        final MultipartReplyMessage mpReply,
-                                        final NodeId node) {
-        if (!MultipartType.OFPMPGROUPFEATURES.equals(mpReply.getType())) {
-            return;
-        }
-
-        GroupFeaturesUpdatedBuilder message = new GroupFeaturesUpdatedBuilder();
-        message.setId(node);
-        message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
-        message.setTransactionId(generateTransactionId(mpReply.getXid()));
-        MultipartReplyGroupFeaturesCase caseBody = (MultipartReplyGroupFeaturesCase) mpReply.getMultipartReplyBody();
+    private static org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply.multipart.reply.body
+        .MultipartReplyGroupFeatures translateGroupFeatures(final MultipartReply msg) {
+        MultipartReplyGroupFeaturesBuilder message = new MultipartReplyGroupFeaturesBuilder();
+        MultipartReplyGroupFeaturesCase caseBody = (MultipartReplyGroupFeaturesCase) msg.getMultipartReplyBody();
         MultipartReplyGroupFeatures replyBody = caseBody.getMultipartReplyGroupFeatures();
         List<Class<? extends GroupType>> supportedGroups =
-                new ArrayList<>();
+            new ArrayList<>();
 
         if (replyBody.getTypes().isOFPGTALL()) {
             supportedGroups.add(GroupAll.class);
@@ -330,7 +368,7 @@ public class SinglePurposeMultipartReplyTranslator {
         message.setMaxGroups(replyBody.getMaxGroups());
 
         List<Class<? extends GroupCapability>> supportedCapabilities =
-                new ArrayList<>();
+            new ArrayList<>();
 
         if (replyBody.getCapabilities().isOFPGFCCHAINING()) {
             supportedCapabilities.add(Chaining.class);
@@ -348,75 +386,48 @@ public class SinglePurposeMultipartReplyTranslator {
         message.setGroupCapabilitiesSupported(supportedCapabilities);
 
         message.setActions(GroupUtil.extractGroupActionsSupportBitmap(replyBody.getActionsBitmap()));
-        listDataObject.add(message.build());
+        return message.build();
     }
 
-    private void translateMeter(final List<DataObject> listDataObject,
-                                final MultipartReplyMessage mpReply,
-                                final NodeId node,
-                                final VersionDatapathIdConvertorData data) {
-        if (!MultipartType.OFPMPMETER.equals(mpReply.getType())) {
-            return;
-        }
-
-        MeterStatisticsUpdatedBuilder message = new MeterStatisticsUpdatedBuilder();
-        message.setId(node);
-        message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
-        message.setTransactionId(generateTransactionId(mpReply.getXid()));
-
-        MultipartReplyMeterCase caseBody = (MultipartReplyMeterCase) mpReply.getMultipartReplyBody();
+    private static MultipartReplyMeterStats translateMeter(final MultipartReply msg,
+                                                           final VersionDatapathIdConvertorData data,
+                                                           final ConvertorExecutor convertorExecutor) {
+        MultipartReplyMeterStatsBuilder message = new MultipartReplyMeterStatsBuilder();
+        MultipartReplyMeterCase caseBody = (MultipartReplyMeterCase) msg.getMultipartReplyBody();
         MultipartReplyMeter replyBody = caseBody.getMultipartReplyMeter();
         final Optional<List<org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats>> meterStatsList =
-                convertorExecutor.convert(replyBody.getMeterStats(), data);
+            convertorExecutor.convert(replyBody.getMeterStats(), data);
 
         message.setMeterStats(meterStatsList.orElse(Collections.emptyList()));
 
-        listDataObject.add(message.build());
+        return message.build();
     }
 
-    private void translateMeterConfig(final List<DataObject> listDataObject,
-                                      final MultipartReplyMessage mpReply,
-                                      final NodeId node,
-                                      final VersionDatapathIdConvertorData data) {
-        if (!MultipartType.OFPMPMETERCONFIG.equals(mpReply.getType())) {
-            return;
-        }
-
-        MeterConfigStatsUpdatedBuilder message = new MeterConfigStatsUpdatedBuilder();
-        message.setId(node);
-        message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
-        message.setTransactionId(generateTransactionId(mpReply.getXid()));
-
-        MultipartReplyMeterConfigCase caseBody = (MultipartReplyMeterConfigCase) mpReply.getMultipartReplyBody();
+    private static org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart.reply.body
+        .MultipartReplyMeterConfig translateMeterConfig(final MultipartReply msg,
+                                                        final VersionDatapathIdConvertorData data,
+                                                        final ConvertorExecutor convertorExecutor) {
+        MultipartReplyMeterConfigBuilder message = new MultipartReplyMeterConfigBuilder();
+        MultipartReplyMeterConfigCase caseBody = (MultipartReplyMeterConfigCase) msg.getMultipartReplyBody();
         MultipartReplyMeterConfig replyBody = caseBody.getMultipartReplyMeterConfig();
         final Optional<List<MeterConfigStats>> meterConfigStatsList = convertorExecutor.convert(replyBody.getMeterConfig(), data);
 
         message.setMeterConfigStats(meterConfigStatsList.orElse(Collections.emptyList()));
 
-        listDataObject.add(message.build());
+        return message.build();
     }
 
-    private void translateMeterFeatures(final List<DataObject> listDataObject,
-                                               final MultipartReplyMessage mpReply,
-                                               final NodeId node) {
-        if (!MultipartType.OFPMPMETERFEATURES.equals(mpReply.getType())) {
-            return;
-        }
-
-        //Convert OF message and send it to SAL listener
-        MeterFeaturesUpdatedBuilder message = new MeterFeaturesUpdatedBuilder();
-        message.setId(node);
-        message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
-        message.setTransactionId(generateTransactionId(mpReply.getXid()));
-
-        MultipartReplyMeterFeaturesCase caseBody = (MultipartReplyMeterFeaturesCase) mpReply.getMultipartReplyBody();
+    private static org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart.reply.body
+        .MultipartReplyMeterFeatures translateMeterFeatures(final MultipartReply msg) {
+        MultipartReplyMeterFeaturesBuilder message = new MultipartReplyMeterFeaturesBuilder();
+        MultipartReplyMeterFeaturesCase caseBody = (MultipartReplyMeterFeaturesCase) msg.getMultipartReplyBody();
         MultipartReplyMeterFeatures replyBody = caseBody.getMultipartReplyMeterFeatures();
         message.setMaxBands(replyBody.getMaxBands());
         message.setMaxColor(replyBody.getMaxColor());
         message.setMaxMeter(new Counter32(replyBody.getMaxMeter()));
 
         List<Class<? extends MeterCapability>> supportedCapabilities =
-                new ArrayList<>();
+            new ArrayList<>();
         if (replyBody.getCapabilities().isOFPMFBURST()) {
             supportedCapabilities.add(MeterBurst.class);
         }
@@ -435,7 +446,7 @@ public class SinglePurposeMultipartReplyTranslator {
         message.setMeterCapabilitiesSupported(supportedCapabilities);
 
         List<Class<? extends MeterBand>> supportedMeterBand =
-                new ArrayList<>();
+            new ArrayList<>();
         if (replyBody.getBandTypes().isOFPMBTDROP()) {
             supportedMeterBand.add(MeterBandDrop.class);
         }
@@ -443,22 +454,12 @@ public class SinglePurposeMultipartReplyTranslator {
             supportedMeterBand.add(MeterBandDscpRemark.class);
         }
         message.setMeterBandSupported(supportedMeterBand);
-        listDataObject.add(message.build());
+        return message.build();
     }
 
-    private void translateTable(final List<DataObject> listDataObject,
-                                       final MultipartReplyMessage mpReply,
-                                       final NodeId node) {
-        if (!MultipartType.OFPMPTABLE.equals(mpReply.getType())) {
-            return;
-        }
-
-        FlowTableStatisticsUpdateBuilder message = new FlowTableStatisticsUpdateBuilder();
-        message.setId(node);
-        message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
-        message.setTransactionId(generateTransactionId(mpReply.getXid()));
-
-        MultipartReplyTableCase caseBody = (MultipartReplyTableCase) mpReply.getMultipartReplyBody();
+    private static MultipartReplyFlowTableStats translateTable(final MultipartReply msg) {
+        MultipartReplyFlowTableStatsBuilder message = new MultipartReplyFlowTableStatsBuilder();
+        MultipartReplyTableCase caseBody = (MultipartReplyTableCase) msg.getMultipartReplyBody();
         MultipartReplyTable replyBody = caseBody.getMultipartReplyTable();
         List<TableStats> swTablesStats = replyBody.getTableStats();
 
@@ -474,36 +475,26 @@ public class SinglePurposeMultipartReplyTranslator {
         }
 
         message.setFlowTableAndStatisticsMap(salFlowStats);
-        listDataObject.add(message.build());
+        return message.build();
     }
 
-    private void translateQueue(final List<DataObject> listDataObject,
-                                       final MultipartReplyMessage mpReply,
-                                       final NodeId node,
-                                       final OpenflowVersion ofVersion,
-                                       final BigInteger datapathId) {
-        if (!MultipartType.OFPMPQUEUE.equals(mpReply.getType())) {
-            return;
-        }
-
-        QueueStatisticsUpdateBuilder message = new QueueStatisticsUpdateBuilder();
-        message.setId(node);
-        message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
-        message.setTransactionId(generateTransactionId(mpReply.getXid()));
-
-        MultipartReplyQueueCase caseBody = (MultipartReplyQueueCase) mpReply.getMultipartReplyBody();
+    private static MultipartReplyQueueStats translateQueue(final MultipartReply msg,
+                                                           final OpenflowVersion ofVersion,
+                                                           final BigInteger datapathId) {
+        MultipartReplyQueueStatsBuilder message = new MultipartReplyQueueStatsBuilder();
+        MultipartReplyQueueCase caseBody = (MultipartReplyQueueCase) msg.getMultipartReplyBody();
         MultipartReplyQueue replyBody = caseBody.getMultipartReplyQueue();
 
         List<QueueIdAndStatisticsMap> statsMap =
-                new ArrayList<QueueIdAndStatisticsMap>();
+            new ArrayList<>();
 
         for (QueueStats queueStats : replyBody.getQueueStats()) {
 
             QueueIdAndStatisticsMapBuilder statsBuilder =
-                    new QueueIdAndStatisticsMapBuilder();
+                new QueueIdAndStatisticsMapBuilder();
             statsBuilder.setNodeConnectorId(
-                    InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(datapathId,
-                            queueStats.getPortNo(), ofVersion));
+                InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(datapathId,
+                    queueStats.getPortNo(), ofVersion));
             statsBuilder.setTransmissionErrors(new Counter64(queueStats.getTxErrors()));
             statsBuilder.setTransmittedBytes(new Counter64(queueStats.getTxBytes()));
             statsBuilder.setTransmittedPackets(new Counter64(queueStats.getTxPackets()));
@@ -515,22 +506,13 @@ public class SinglePurposeMultipartReplyTranslator {
 
             statsBuilder.setQueueId(new QueueId(queueStats.getQueueId()));
             statsBuilder.setNodeConnectorId(InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(datapathId,
-                    queueStats.getPortNo(), ofVersion));
+                queueStats.getPortNo(), ofVersion));
 
             statsMap.add(statsBuilder.build());
         }
         message.setQueueIdAndStatisticsMap(statsMap);
 
-        listDataObject.add(message.build());
+        return message.build();
     }
 
-    private static NodeId nodeIdFromDatapathId(final BigInteger datapathId) {
-        String current = datapathId.toString();
-        return new NodeId("openflow:" + current);
-    }
-
-    private static TransactionId generateTransactionId(final Long xid) {
-        BigInteger bigIntXid = BigInteger.valueOf(xid);
-        return new TransactionId(bigIntXid);
-    }
 }
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/common/NodeConnectorTranslatorUtil.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/common/NodeConnectorTranslatorUtil.java
deleted file mode 100644 (file)
index 9afc37e..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/**
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.openflowplugin.impl.common;
-
-import com.google.common.base.Preconditions;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder;
-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.PortNumberUni;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.State;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.StateBuilder;
-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.NodeConnectorBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortConfigV10;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeaturesV10;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortState;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortStateV10;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.features.reply.PhyPort;
-
-/**
- * openflowplugin-impl
- * org.opendaylight.openflowplugin.impl.common
- *
- * Translator helper for Translating OF java models to MD-SAL inventory models.
- * Translator focus for {@link NodeConnector} object and relevant OF augmentation
- * {@link FlowCapableNodeConnector}.
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- * Created: Mar 31, 2015
- */
-public final class NodeConnectorTranslatorUtil {
-
-    private NodeConnectorTranslatorUtil () {
-        throw new UnsupportedOperationException("Utility class");
-    }
-
-    /**
-     * Method translates {@link PhyPort} object directly to {@link NodeConnector} which is augmented
-     * by {@link FlowCapableNodeConnector} and contains all relevant content translated by actual OF version.
-     *
-     * @param featuresReply
-     * @return
-     */
-    public static List<NodeConnector> translateNodeConnectorFromFeaturesReply(@CheckForNull final FeaturesReply featuresReply) {
-        Preconditions.checkArgument(featuresReply != null);
-        Preconditions.checkArgument(featuresReply.getPhyPort() != null);
-        final Short version = featuresReply.getVersion();
-        final BigInteger dataPathId = featuresReply.getDatapathId();
-        final List<NodeConnector> resultList = new ArrayList<>(featuresReply.getPhyPort().size());
-        for (final PhyPort port : featuresReply.getPhyPort()) {
-            final NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder();
-            ncBuilder.setId(makeNodeConnectorId(dataPathId, port.getName(), port.getPortNo()));
-            ncBuilder.addAugmentation(FlowCapableNodeConnector.class, translateFlowCapableNodeFromPhyPort(port, version));
-            resultList.add(ncBuilder.build());
-        }
-        return resultList;
-    }
-
-    /**
-     * Method translates {@link PhyPort} object directly to {@link FlowCapableNodeConnector} which is augmented
-     * by {@link NodeConnector} and contains all relevant content translated by actual OF version.
-     *
-     * @param port
-     * @param version
-     * @return
-     */
-    public static FlowCapableNodeConnector translateFlowCapableNodeFromPhyPort(@CheckForNull final PhyPort port, final short version) {
-        Preconditions.checkArgument(port != null);
-        final FlowCapableNodeConnectorBuilder fcncBuilder = new FlowCapableNodeConnectorBuilder();
-        fcncBuilder.setHardwareAddress(port.getHwAddr());
-        fcncBuilder.setCurrentSpeed(port.getCurrSpeed());
-        fcncBuilder.setMaximumSpeed(port.getMaxSpeed());
-        fcncBuilder.setName(port.getName());
-        fcncBuilder.setPortNumber(new PortNumberUni(port.getPortNo()));
-        if (OFConstants.OFP_VERSION_1_3 == version) {
-            fcncBuilder.setAdvertisedFeatures(translatePortFeatures(port.getAdvertisedFeatures()));
-            fcncBuilder.setConfiguration(translatePortConfig(port.getConfig()));
-            fcncBuilder.setCurrentFeature(translatePortFeatures(port.getCurrentFeatures()));
-            fcncBuilder.setPeerFeatures(translatePortFeatures(port.getPeerFeatures()));
-            fcncBuilder.setSupported(translatePortFeatures(port.getSupportedFeatures()));
-            fcncBuilder.setState(translatePortState(port.getState()));
-        } else if (OFConstants.OFP_VERSION_1_0 == version) {
-            fcncBuilder.setAdvertisedFeatures(translatePortFeatures(port.getAdvertisedFeaturesV10()));
-            fcncBuilder.setConfiguration(translatePortConfig(port.getConfigV10()));
-            fcncBuilder.setCurrentFeature(translatePortFeatures(port.getCurrentFeaturesV10()));
-            fcncBuilder.setPeerFeatures(translatePortFeatures(port.getPeerFeaturesV10()));
-            fcncBuilder.setSupported(translatePortFeatures(port.getSupportedFeaturesV10()));
-            fcncBuilder.setState(translatePortState(port.getStateV10()));
-        } else {
-            throw new IllegalArgumentException("Unknown OF version " + version);
-        }
-        return fcncBuilder.build();
-    }
-
-    private static PortConfig translatePortConfig(@CheckForNull final org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortConfig pc) {
-        Preconditions.checkArgument(pc != null);
-        return new PortConfig(pc.isNoFwd(), pc.isNoPacketIn(), pc.isNoRecv(), pc.isPortDown());
-    }
-
-    private static PortConfig translatePortConfig(@CheckForNull final PortConfigV10 pc) {
-        Preconditions.checkArgument(pc != null);
-        return new PortConfig(pc.isNoFwd(), pc.isNoPacketIn(), pc.isNoRecv(), pc.isPortDown());
-    }
-
-    private static PortFeatures translatePortFeatures(@CheckForNull final org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeatures pf) {
-        Preconditions.checkArgument(pf != null);
-        return new PortFeatures(pf.isAutoneg(), pf.isCopper(), pf.isFiber(), pf.is_40gbFd(), pf.is_100gbFd(), pf.is_100mbFd(), pf.is_100mbHd(),
-                pf.is_1gbFd(), pf.is_1gbHd(), pf.is_1tbFd(), pf.isOther(), pf.isPause(), pf.isPauseAsym(), pf.is_10gbFd(), pf.is_10mbFd(), pf.is_10mbHd());
-    }
-
-    private static PortFeatures translatePortFeatures(@CheckForNull final PortFeaturesV10 pf) {
-        Preconditions.checkArgument(pf != null);
-        return new PortFeatures(pf.isAutoneg(), pf.isCopper(), pf.isFiber(), Boolean.FALSE, Boolean.FALSE, pf.is_100mbFd(), pf.is_100mbHd(),
-                pf.is_1gbFd(), pf.is_1gbHd(), Boolean.FALSE, Boolean.FALSE, pf.isPause(), pf.isPauseAsym(), pf.is_10gbFd(), pf.is_10mbFd(), pf.is_10mbHd());
-    }
-
-    private static State translatePortState(@CheckForNull final PortState state) {
-        Preconditions.checkArgument(state != null);
-        return new StateBuilder().setBlocked(state.isBlocked()).setLinkDown(state.isLinkDown()).setLive(state.isLive()).build();
-    }
-
-    private static State translatePortState(@CheckForNull final PortStateV10 state) {
-        Preconditions.checkArgument(state != null);
-        return new StateBuilder().setBlocked(state.isBlocked()).setLinkDown(state.isLinkDown()).setLive(state.isLive()).build();
-    }
-
-    /**
-     * Method makes NodeConnectorId with prefix  "openflow:" from dataPathId and logical name or port number
-     *
-     * @param dataPathId
-     * @param logicalName
-     * @param portNo
-     * @return
-     */
-    public static NodeConnectorId makeNodeConnectorId(@CheckForNull final BigInteger dataPathId,
-            @Nullable final String logicalName, final long portNo) {
-        Preconditions.checkArgument(dataPathId != null);
-        return new NodeConnectorId(OFConstants.OF_URI_PREFIX + dataPathId + ":" + (logicalName == null ? portNo : logicalName));
-    }
-}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/common/NodeStaticReplyTranslatorUtil.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/common/NodeStaticReplyTranslatorUtil.java
deleted file mode 100644 (file)
index 78018d8..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/**
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.openflowplugin.impl.common;
-
-import com.google.common.base.Preconditions;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-import javax.annotation.CheckForNull;
-import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.impl.util.GroupUtil;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData;
-import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.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.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.group.features.GroupFeaturesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Chaining;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.ChainingChecks;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupAll;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupCapability;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupFf;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupIndirect;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupSelect;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.SelectLiveness;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.SelectWeight;
-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.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.nodes.node.MeterFeaturesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBand;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBandDrop;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBandDscpRemark;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBurst;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterCapability;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterKbps;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterPktps;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDesc;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.features._case.MultipartReplyGroupFeatures;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter.features._case.MultipartReplyMeterFeatures;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table.features._case.MultipartReplyTableFeatures;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
-
-/**
- * <p>
- * openflowplugin-impl
- * org.opendaylight.openflowplugin.impl.common
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *         </p>
- *         Created: Mar 31, 2015
- */
-public class NodeStaticReplyTranslatorUtil {
-
-    private NodeStaticReplyTranslatorUtil() {
-        throw new UnsupportedOperationException("Utility class");
-    }
-
-    /**
-     * Method transforms OFjava multipart reply model {@link MultipartReplyDesc} object
-     * to inventory data model {@link FlowCapableNode} object.
-     *
-     * @param reply
-     * @return
-     */
-    public static FlowCapableNodeBuilder nodeDescTranslator(@CheckForNull final MultipartReplyDesc reply, final IpAddress ipAddress) {
-        Preconditions.checkArgument(reply != null);
-        final FlowCapableNodeBuilder flowCapAugBuilder = new FlowCapableNodeBuilder();
-        flowCapAugBuilder.setDescription(reply.getDpDesc());
-        flowCapAugBuilder.setHardware(reply.getHwDesc());
-        flowCapAugBuilder.setManufacturer(reply.getMfrDesc());
-        flowCapAugBuilder.setSoftware(reply.getSwDesc());
-        flowCapAugBuilder.setSerialNumber(reply.getSerialNum());
-        flowCapAugBuilder.setTable(Collections.<Table>emptyList());
-        flowCapAugBuilder.setMeter(Collections.<Meter>emptyList());
-        flowCapAugBuilder.setGroup(Collections.<Group>emptyList());
-        if (ipAddress != null) {
-            flowCapAugBuilder.setIpAddress(ipAddress);
-        }
-        return flowCapAugBuilder;
-    }
-
-    /**
-     * Method transforms OFjava multipart reply model {@link MultipartReplyMeterFeatures} object
-     * to inventory data model {@link NodeMeterFeatures} object.
-     *
-     * @param reply
-     * @return
-     */
-    public static NodeMeterFeatures nodeMeterFeatureTranslator(@CheckForNull final MultipartReplyMeterFeatures reply) {
-        Preconditions.checkArgument(reply != null);
-        final MeterFeaturesBuilder meterFeature = new MeterFeaturesBuilder();
-        meterFeature.setMaxBands(reply.getMaxBands());
-        meterFeature.setMaxColor(reply.getMaxColor());
-        meterFeature.setMaxMeter(new Counter32(reply.getMaxMeter()));
-        final List<Class<? extends MeterBand>> meterBandTypes = new ArrayList<>();
-        if (reply.getBandTypes().isOFPMBTDROP()) {
-            meterBandTypes.add(MeterBandDrop.class);
-        }
-        if (reply.getBandTypes().isOFPMBTDSCPREMARK()) {
-            meterBandTypes.add(MeterBandDscpRemark.class);
-        }
-        meterFeature.setMeterBandSupported(Collections.unmodifiableList(meterBandTypes));
-
-        final List<java.lang.Class<? extends MeterCapability>> mCapability = new ArrayList<>();
-        if (reply.getCapabilities().isOFPMFBURST()) {
-            mCapability.add(MeterBurst.class);
-        }
-        if (reply.getCapabilities().isOFPMFKBPS()) {
-            mCapability.add(MeterKbps.class);
-
-        }
-        if (reply.getCapabilities().isOFPMFPKTPS()) {
-            mCapability.add(MeterPktps.class);
-
-        }
-        if (reply.getCapabilities().isOFPMFSTATS()) {
-            mCapability.add(MeterStats.class);
-
-        }
-        meterFeature.setMeterCapabilitiesSupported(Collections.unmodifiableList(mCapability));
-        return new NodeMeterFeaturesBuilder().setMeterFeatures(meterFeature.build()).build();
-    }
-
-    /**
-     * Method transforms OFjava reply model {@link MultipartReplyGroupFeatures} object
-     * to inventory data model {@link NodeGroupFeatures} object.
-     *
-     * @param reply
-     * @return
-     */
-    public static NodeGroupFeatures nodeGroupFeatureTranslator(@CheckForNull final MultipartReplyGroupFeatures reply) {
-        Preconditions.checkArgument(reply != null);
-        final GroupFeaturesBuilder groupFeature = new GroupFeaturesBuilder();
-        groupFeature.setMaxGroups(reply.getMaxGroups());
-
-        final List<Class<? extends GroupType>> supportedGroups = new ArrayList<>();
-        addSupportedGroups(reply, supportedGroups);
-        groupFeature.setGroupTypesSupported(supportedGroups);
-
-        final List<Class<? extends GroupCapability>> gCapability = new ArrayList<>();
-        addGroupCapabilities(reply, gCapability);
-        groupFeature.setGroupCapabilitiesSupported(gCapability);
-
-        groupFeature.setActions(GroupUtil.extractGroupActionsSupportBitmap(reply.getActionsBitmap()));
-        return new NodeGroupFeaturesBuilder().setGroupFeatures(groupFeature.build()).build();
-    }
-
-    private static void addGroupCapabilities(final MultipartReplyGroupFeatures reply, final List<Class<? extends GroupCapability>> gCapability) {
-        if (reply.getCapabilities().isOFPGFCCHAINING()) {
-            gCapability.add(Chaining.class);
-        }
-        if (reply.getCapabilities().isOFPGFCCHAININGCHECKS()) {
-            gCapability.add(ChainingChecks.class);
-        }
-        if (reply.getCapabilities().isOFPGFCSELECTLIVENESS()) {
-            gCapability.add(SelectLiveness.class);
-        }
-        if (reply.getCapabilities().isOFPGFCSELECTWEIGHT()) {
-            gCapability.add(SelectWeight.class);
-        }
-    }
-
-    private static void addSupportedGroups(final MultipartReplyGroupFeatures reply, final List<Class<? extends GroupType>> supportedGroups) {
-        if (reply.getTypes().isOFPGTALL()) {
-            supportedGroups.add(GroupAll.class);
-        }
-        if (reply.getTypes().isOFPGTSELECT()) {
-            supportedGroups.add(GroupSelect.class);
-        }
-        if (reply.getTypes().isOFPGTINDIRECT()) {
-            supportedGroups.add(GroupIndirect.class);
-        }
-        if (reply.getTypes().isOFPGTFF()) {
-            supportedGroups.add(GroupFf.class);
-        }
-    }
-
-    /**
-     * Method transform {@link MultipartReplyTableFeatures} to list of {@link TableFeatures}. Every
-     * table can have List of TableFeatures so add it directly to
-     * {@link org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder}
-     *
-     * @param reply reply
-     * @param version Openflow version
-     * @param convertorExecutor convertor executor
-     * @return list of table features
-     */
-    public static List<TableFeatures> nodeTableFeatureTranslator(@CheckForNull final MultipartReplyTableFeatures reply, final short version, @CheckForNull final ConvertorExecutor convertorExecutor) {
-        Preconditions.checkArgument(reply != null);
-        Preconditions.checkArgument(convertorExecutor != null);
-        final Optional<List<TableFeatures>> tableFeaturesList = convertorExecutor.convert(reply, new VersionConvertorData(version));
-        return tableFeaturesList.orElse(Collections.emptyList());
-    }
-
-    /**
-     * Method build a ID Node Connector from version and port number.
-     *
-     * @param datapathId
-     * @param portNo
-     * @param version
-     * @return
-     */
-    public static NodeConnectorId nodeConnectorId(@CheckForNull final String datapathId, final long portNo, final short version) {
-        Preconditions.checkArgument(datapathId != null);
-        final String logicalName = OpenflowPortsUtil.getPortLogicalName(version, portNo);
-        return new NodeConnectorId(OFConstants.OF_URI_PREFIX + datapathId + ":" + (logicalName == null ? portNo : logicalName));
-    }
-}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/MultipartWriterProvider.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/MultipartWriterProvider.java
new file mode 100644 (file)
index 0000000..0f50c24
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.datastore;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import org.opendaylight.openflowplugin.impl.datastore.multipart.AbstractMultipartWriter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+
+public class MultipartWriterProvider {
+
+    private final Map<MultipartType, AbstractMultipartWriter> writers = new HashMap<>();
+
+    /**
+     * Register statistics writer.
+     *
+     * @param type    the writer type
+     * @param writer the writer instance
+     */
+    public void register(final MultipartType type, final AbstractMultipartWriter writer) {
+        writers.put(type, writer);
+    }
+
+    /**
+     * Lookup  statistics writer.
+     *
+     * @param type the writer type
+     * @return the writer instance
+     */
+    public Optional<AbstractMultipartWriter> lookup(final MultipartType type) {
+        return Optional.ofNullable(writers.get(type));
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/MultipartWriterProviderFactory.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/MultipartWriterProviderFactory.java
new file mode 100644 (file)
index 0000000..bc0d817
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.datastore;
+
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.impl.datastore.multipart.DescMultipartWriter;
+import org.opendaylight.openflowplugin.impl.datastore.multipart.FlowStatsMultipartWriter;
+import org.opendaylight.openflowplugin.impl.datastore.multipart.GroupDescMultipartWriter;
+import org.opendaylight.openflowplugin.impl.datastore.multipart.GroupFeaturesMultipartWriter;
+import org.opendaylight.openflowplugin.impl.datastore.multipart.GroupStatsMultipartWriter;
+import org.opendaylight.openflowplugin.impl.datastore.multipart.MeterConfigMultipartWriter;
+import org.opendaylight.openflowplugin.impl.datastore.multipart.MeterFeaturesMultipartWriter;
+import org.opendaylight.openflowplugin.impl.datastore.multipart.MeterStatsMultipartWriter;
+import org.opendaylight.openflowplugin.impl.datastore.multipart.PortDescMultipartWriter;
+import org.opendaylight.openflowplugin.impl.datastore.multipart.PortStatsMultipartWriter;
+import org.opendaylight.openflowplugin.impl.datastore.multipart.QueueStatsMultipartWriter;
+import org.opendaylight.openflowplugin.impl.datastore.multipart.TableFeaturesMultipartWriter;
+import org.opendaylight.openflowplugin.impl.datastore.multipart.TableStatsMultipartWriter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Multipart writer provider factory
+ */
+public class MultipartWriterProviderFactory {
+
+    /**
+     * Create default #{@link MultipartWriterProvider}
+     * @param deviceContext device context
+     * @return the statistics writer provider
+     */
+    public static MultipartWriterProvider createDefaultProvider(final DeviceContext deviceContext) {
+        final InstanceIdentifier<Node> instanceIdentifier = deviceContext.getDeviceInfo().getNodeInstanceIdentifier();
+        final MultipartWriterProvider provider = new MultipartWriterProvider();
+
+        //  Periodic/direct statistics writers
+        provider.register(MultipartType.OFPMPTABLE, new TableStatsMultipartWriter(deviceContext, instanceIdentifier));
+        provider.register(MultipartType.OFPMPGROUP, new GroupStatsMultipartWriter(deviceContext, instanceIdentifier));
+        provider.register(MultipartType.OFPMPMETER, new MeterStatsMultipartWriter(deviceContext, instanceIdentifier));
+        provider.register(MultipartType.OFPMPPORTSTATS, new PortStatsMultipartWriter(deviceContext, instanceIdentifier, deviceContext.getPrimaryConnectionContext().getFeatures()));
+        provider.register(MultipartType.OFPMPQUEUE, new QueueStatsMultipartWriter(deviceContext, instanceIdentifier));
+        provider.register(MultipartType.OFPMPFLOW, new FlowStatsMultipartWriter(deviceContext, instanceIdentifier, deviceContext, deviceContext.getDeviceInfo().getVersion()));
+        provider.register(MultipartType.OFPMPGROUPDESC, new GroupDescMultipartWriter(deviceContext, instanceIdentifier, deviceContext));
+        provider.register(MultipartType.OFPMPMETERCONFIG, new MeterConfigMultipartWriter(deviceContext, instanceIdentifier, deviceContext));
+
+        // Device initialization writers
+        provider.register(MultipartType.OFPMPDESC, new DescMultipartWriter(deviceContext, instanceIdentifier, deviceContext.getPrimaryConnectionContext()));
+        provider.register(MultipartType.OFPMPGROUPFEATURES, new GroupFeaturesMultipartWriter(deviceContext, instanceIdentifier));
+        provider.register(MultipartType.OFPMPMETERFEATURES, new MeterFeaturesMultipartWriter(deviceContext, instanceIdentifier));
+        provider.register(MultipartType.OFPMPTABLEFEATURES, new TableFeaturesMultipartWriter(deviceContext, instanceIdentifier));
+        provider.register(MultipartType.OFPMPPORTDESC, new PortDescMultipartWriter(deviceContext, instanceIdentifier, deviceContext.getPrimaryConnectionContext().getFeatures()));
+
+        return provider;
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/AbstractMultipartWriter.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/AbstractMultipartWriter.java
new file mode 100644 (file)
index 0000000..28a2d2c
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.datastore.multipart;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
+import org.opendaylight.openflowplugin.impl.services.AbstractMultipartService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractMultipartWriter<T extends DataContainer> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractMultipartService.class);
+
+    private final TxFacade txFacade;
+    private final InstanceIdentifier<Node> instanceIdentifier;
+
+    AbstractMultipartWriter(final TxFacade txFacade, final InstanceIdentifier<Node> instanceIdentifier) {
+        this.txFacade = txFacade;
+        this.instanceIdentifier = instanceIdentifier;
+    }
+
+    /**
+     * Creates put operation using provided data in underlying transaction chain.
+     * @param path path
+     * @param data data
+     * @param <O> data type
+     */
+    protected <O extends DataObject> void writeToTransaction(final InstanceIdentifier<O> path,
+                                                             final O data,
+                                                             final boolean withParents) {
+        if (withParents) {
+            txFacade.writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, path, data);
+        } else {
+            txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, path, data);
+        }
+    }
+
+    /**
+     * Get instance identifier
+     * @return instance identifier
+     */
+    protected InstanceIdentifier<Node> getInstanceIdentifier() {
+        return instanceIdentifier;
+    }
+
+    /**
+     * Write dataContainer
+     * @param dataContainer dataContainer
+     * @param withParents write missing parents if needed (slower)
+     * @return true if we have correct dataContainer type
+     */
+    public boolean write(final DataContainer dataContainer, final boolean withParents) {
+        if (getType().isInstance(dataContainer)) {
+            LOG.debug("Writing multipart data of type {} for node {}", getType(), getInstanceIdentifier());
+            storeStatistics(getType().cast(dataContainer), withParents);
+            return true;
+        }
+
+        LOG.debug("Failed to write multipart data of type {} for node {}", getType(), getInstanceIdentifier());
+        return false;
+    }
+
+    /**
+     * Get type of writer
+     * @return type of writer
+     */
+    protected abstract Class<T> getType();
+
+    /**
+     * Write statistics
+     * @param statistics statistics
+     * @param withParents write missing parents if needed (slower)
+     */
+    protected abstract void storeStatistics(final T statistics,
+                                            final boolean withParents);
+
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/DescMultipartWriter.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/DescMultipartWriter.java
new file mode 100644 (file)
index 0000000..b9f3177
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.datastore.multipart;
+
+import java.util.Collections;
+import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
+import org.opendaylight.openflowplugin.impl.util.DeviceInitializationUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.Desc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class DescMultipartWriter extends AbstractMultipartWriter<Desc> {
+
+    private final ConnectionContext connectionContext;
+
+    public DescMultipartWriter(final TxFacade txFacade,
+                               final InstanceIdentifier<Node> instanceIdentifier,
+                               final ConnectionContext connectionContext) {
+        super(txFacade, instanceIdentifier);
+        this.connectionContext = connectionContext;
+    }
+
+    @Override
+    protected Class<Desc> getType() {
+        return Desc.class;
+    }
+
+    @Override
+    public void storeStatistics(final Desc statistics, final boolean withParents) {
+        writeToTransaction(getInstanceIdentifier()
+                .augmentation(FlowCapableNode.class),
+            new FlowCapableNodeBuilder(statistics)
+                .setTable(Collections.emptyList())
+                .setMeter(Collections.emptyList())
+                .setGroup(Collections.emptyList())
+                .setIpAddress(DeviceInitializationUtil.getIpAddress(connectionContext, getInstanceIdentifier()))
+                .setSwitchFeatures(DeviceInitializationUtil.getSwitchFeatures(connectionContext))
+                .build(),
+            withParents);
+    }
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/FlowStatsMultipartWriter.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/FlowStatsMultipartWriter.java
new file mode 100644 (file)
index 0000000..6974386
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.datastore.multipart;
+
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceRegistry;
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
+import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.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.FlowAndStatisticsMapList;
+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.flow.statistics.FlowStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class FlowStatsMultipartWriter extends AbstractMultipartWriter<FlowAndStatisticsMapList> {
+
+    private final DeviceRegistry registry;
+    private final short version;
+
+    public FlowStatsMultipartWriter(final TxFacade txFacade,
+                                    final InstanceIdentifier<Node> instanceIdentifier,
+                                    final DeviceRegistry registry,
+                                    final short version) {
+        super(txFacade, instanceIdentifier);
+        this.registry = registry;
+        this.version = version;
+    }
+
+    @Override
+    protected Class<FlowAndStatisticsMapList> getType() {
+        return FlowAndStatisticsMapList.class;
+    }
+
+    @Override
+    public void storeStatistics(final FlowAndStatisticsMapList statistics, final boolean withParents) {
+        statistics.getFlowAndStatisticsMapList()
+            .forEach(stat -> {
+                final FlowBuilder flow = new FlowBuilder(stat)
+                    .addAugmentation(
+                        FlowStatisticsData.class,
+                        new FlowStatisticsDataBuilder()
+                            .setFlowStatistics(new FlowStatisticsBuilder(stat).build())
+                            .build());
+
+                final FlowKey key = new FlowKey(registry
+                    .getDeviceFlowRegistry()
+                    .storeIfNecessary(FlowRegistryKeyFactory
+                        .create(version, flow.build())));
+
+                writeToTransaction(
+                    getInstanceIdentifier()
+                        .augmentation(FlowCapableNode.class)
+                        .child(Table.class, new TableKey(stat.getTableId()))
+                        .child(Flow.class, key),
+                    flow
+                        .setId(key.getId())
+                        .setKey(key)
+                        .build(),
+                    withParents);
+            });
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/GroupDescMultipartWriter.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/GroupDescMultipartWriter.java
new file mode 100644 (file)
index 0000000..b02e246
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.datastore.multipart;
+
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceRegistry;
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+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.types.rev131018.GroupDescStatsReply;
+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.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class GroupDescMultipartWriter extends AbstractMultipartWriter<GroupDescStatsReply> {
+
+    private final DeviceRegistry registry;
+
+    public GroupDescMultipartWriter(final TxFacade txFacade,
+                                    final InstanceIdentifier<Node> instanceIdentifier,
+                                    final DeviceRegistry registry) {
+        super(txFacade, instanceIdentifier);
+        this.registry = registry;
+    }
+
+    @Override
+    protected Class<GroupDescStatsReply> getType() {
+        return GroupDescStatsReply.class;
+    }
+
+    @Override
+    public void storeStatistics(final GroupDescStatsReply statistics, final boolean withParents) {
+        statistics.getGroupDescStats()
+            .forEach(stat -> {
+                writeToTransaction(
+                    getInstanceIdentifier()
+                        .augmentation(FlowCapableNode.class)
+                        .child(Group.class, new GroupKey(stat.getGroupId())),
+                    new GroupBuilder(stat)
+                        .setKey(new GroupKey(stat.getGroupId()))
+                        .addAugmentation(NodeGroupStatistics.class, new NodeGroupStatisticsBuilder().build())
+                        .build(),
+                    withParents);
+
+                registry.getDeviceGroupRegistry().store(stat.getGroupId());
+            });
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/GroupFeaturesMultipartWriter.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/GroupFeaturesMultipartWriter.java
new file mode 100644 (file)
index 0000000..f83afee
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.datastore.multipart;
+
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
+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.group.features.GroupFeaturesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class GroupFeaturesMultipartWriter extends AbstractMultipartWriter<GroupFeatures> {
+
+    public GroupFeaturesMultipartWriter(final TxFacade txFacade, final InstanceIdentifier<Node> instanceIdentifier) {
+        super(txFacade, instanceIdentifier);
+    }
+
+    @Override
+    protected Class<GroupFeatures> getType() {
+        return GroupFeatures.class;
+    }
+
+    @Override
+    public void storeStatistics(final GroupFeatures statistics, final boolean withParents) {
+        writeToTransaction(getInstanceIdentifier()
+                .augmentation(NodeGroupFeatures.class),
+            new NodeGroupFeaturesBuilder()
+                .setGroupFeatures(new GroupFeaturesBuilder(statistics)
+                    .build())
+                .build(),
+            withParents);
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/GroupStatsMultipartWriter.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/GroupStatsMultipartWriter.java
new file mode 100644 (file)
index 0000000..702ad56
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.datastore.multipart;
+
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatistics;
+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.GroupStatisticsReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class GroupStatsMultipartWriter extends AbstractMultipartWriter<GroupStatisticsReply> {
+
+    public GroupStatsMultipartWriter(final TxFacade txFacade, final InstanceIdentifier<Node> instanceIdentifier) {
+        super(txFacade, instanceIdentifier);
+    }
+
+    @Override
+    protected Class<GroupStatisticsReply> getType() {
+        return GroupStatisticsReply.class;
+    }
+
+    @Override
+    public void storeStatistics(final GroupStatisticsReply statistics, final boolean withParents) {
+        statistics.getGroupStats()
+            .forEach(stat -> writeToTransaction(
+                getInstanceIdentifier()
+                    .augmentation(FlowCapableNode.class)
+                    .child(Group.class, new GroupKey(stat.getGroupId()))
+                    .augmentation(NodeGroupStatistics.class)
+                    .child(GroupStatistics.class),
+                new GroupStatisticsBuilder(stat).build(),
+                withParents));
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/MeterConfigMultipartWriter.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/MeterConfigMultipartWriter.java
new file mode 100644 (file)
index 0000000..42a8c2e
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.datastore.multipart;
+
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceRegistry;
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+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.types.rev130918.MeterConfigStatsReply;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class MeterConfigMultipartWriter extends AbstractMultipartWriter<MeterConfigStatsReply> {
+
+    private final DeviceRegistry registry;
+
+    public MeterConfigMultipartWriter(final TxFacade txFacade,
+                                      final InstanceIdentifier<Node> instanceIdentifier,
+                                      final DeviceRegistry registry) {
+        super(txFacade, instanceIdentifier);
+        this.registry = registry;
+    }
+
+    @Override
+    protected Class<MeterConfigStatsReply> getType() {
+        return MeterConfigStatsReply.class;
+    }
+
+    @Override
+    public void storeStatistics(final MeterConfigStatsReply statistics, final boolean withParents) {
+        statistics.getMeterConfigStats()
+            .forEach(stat -> {
+                writeToTransaction(
+                    getInstanceIdentifier()
+                        .augmentation(FlowCapableNode.class)
+                        .child(Meter.class, new MeterKey(stat.getMeterId())),
+                    new MeterBuilder(stat)
+                        .setKey(new MeterKey(stat.getMeterId()))
+                        .addAugmentation(NodeMeterStatistics.class, new NodeMeterStatisticsBuilder().build())
+                        .build(),
+                    withParents);
+
+                registry.getDeviceMeterRegistry().store(stat.getMeterId());
+            });
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/MeterFeaturesMultipartWriter.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/MeterFeaturesMultipartWriter.java
new file mode 100644 (file)
index 0000000..ffaedc8
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.datastore.multipart;
+
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+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.nodes.node.MeterFeatures;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class MeterFeaturesMultipartWriter extends AbstractMultipartWriter<MeterFeatures> {
+
+    public MeterFeaturesMultipartWriter(final TxFacade txFacade, final InstanceIdentifier<Node> instanceIdentifier) {
+        super(txFacade, instanceIdentifier);
+    }
+
+    @Override
+    protected Class<MeterFeatures> getType() {
+        return MeterFeatures.class;
+    }
+
+    @Override
+    public void storeStatistics(final MeterFeatures statistics, final boolean withParents) {
+        writeToTransaction(getInstanceIdentifier()
+                .augmentation(NodeMeterFeatures.class),
+            new NodeMeterFeaturesBuilder()
+                .setMeterFeatures(statistics)
+                .build(),
+            withParents);
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/MeterStatsMultipartWriter.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/MeterStatsMultipartWriter.java
new file mode 100644 (file)
index 0000000..5abd785
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.datastore.multipart;
+
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatistics;
+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.MeterStatisticsReply;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class MeterStatsMultipartWriter extends AbstractMultipartWriter<MeterStatisticsReply> {
+
+    public MeterStatsMultipartWriter(final TxFacade txFacade, final InstanceIdentifier<Node> instanceIdentifier) {
+        super(txFacade, instanceIdentifier);
+    }
+
+    @Override
+    protected Class<MeterStatisticsReply> getType() {
+        return MeterStatisticsReply.class;
+    }
+
+    @Override
+    public void storeStatistics(final MeterStatisticsReply statistics, final boolean withParents) {
+        statistics.getMeterStats()
+            .forEach(stat -> writeToTransaction(
+                getInstanceIdentifier()
+                    .augmentation(FlowCapableNode.class)
+                    .child(Meter.class, new MeterKey(stat.getMeterId()))
+                    .augmentation(NodeMeterStatistics.class)
+                    .child(MeterStatistics.class),
+                new MeterStatisticsBuilder(stat).build(),
+                withParents));
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/PortDescMultipartWriter.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/PortDescMultipartWriter.java
new file mode 100644 (file)
index 0000000..36dac14
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.datastore.multipart;
+
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
+import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
+import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.multipart.reply.multipart.reply.body.MultipartReplyPortDesc;
+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.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.openflow.protocol.rev130731.FeaturesReply;
+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.yangtools.yang.binding.InstanceIdentifier;
+
+public class PortDescMultipartWriter extends AbstractMultipartWriter<MultipartReplyPortDesc> {
+
+    private final FeaturesReply features;
+
+    public PortDescMultipartWriter(final TxFacade txFacade,
+                                   final InstanceIdentifier<Node> instanceIdentifier,
+                                   final FeaturesReply features) {
+        super(txFacade, instanceIdentifier);
+        this.features = features;
+    }
+
+    @Override
+    protected Class<MultipartReplyPortDesc> getType() {
+        return MultipartReplyPortDesc.class;
+    }
+
+    @Override
+    public void storeStatistics(final MultipartReplyPortDesc statistics, final boolean withParents) {
+        statistics.getPorts()
+            .forEach(stat -> {
+                final NodeConnectorId id = InventoryDataServiceUtil
+                    .nodeConnectorIdfromDatapathPortNo(
+                        features.getDatapathId(),
+                        OpenflowPortsUtil.getProtocolPortNumber(
+                            OpenflowVersion.get(features.getVersion()),
+                            stat.getPortNumber()),
+                        OpenflowVersion.get(features.getVersion()));
+
+                writeToTransaction(
+                    getInstanceIdentifier()
+                        .child(NodeConnector.class, new NodeConnectorKey(id)),
+                    new NodeConnectorBuilder()
+                        .setId(id)
+                        .addAugmentation(
+                            FlowCapableNodeConnector.class,
+                            new FlowCapableNodeConnectorBuilder(stat).build())
+                        .addAugmentation(
+                            FlowCapableNodeConnectorStatisticsData.class,
+                            new FlowCapableNodeConnectorStatisticsDataBuilder().build())
+                        .build(),
+                    withParents);
+            });
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/PortStatsMultipartWriter.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/PortStatsMultipartWriter.java
new file mode 100644 (file)
index 0000000..8faf97f
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.datastore.multipart;
+
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
+import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
+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.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsAndPortNumberMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatisticsBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PortStatsMultipartWriter extends AbstractMultipartWriter<NodeConnectorStatisticsAndPortNumberMap> {
+
+    private final FeaturesReply features;
+
+    public PortStatsMultipartWriter(final TxFacade txFacade,
+                                    final InstanceIdentifier<Node> instanceIdentifier,
+                                    final FeaturesReply features) {
+        super(txFacade, instanceIdentifier);
+        this.features = features;
+    }
+
+    @Override
+    protected Class<NodeConnectorStatisticsAndPortNumberMap> getType() {
+        return NodeConnectorStatisticsAndPortNumberMap.class;
+    }
+
+    @Override
+    public void storeStatistics(final NodeConnectorStatisticsAndPortNumberMap statistics, final boolean withParents) {
+        statistics.getNodeConnectorStatisticsAndPortNumberMap()
+            .forEach(stat -> {
+                final OpenflowVersion openflowVersion = OpenflowVersion.get(features.getVersion());
+                final Long port = InventoryDataServiceUtil
+                    .portNumberfromNodeConnectorId(openflowVersion, stat.getNodeConnectorId());
+
+                final NodeConnectorId id = InventoryDataServiceUtil
+                    .nodeConnectorIdfromDatapathPortNo(
+                        features.getDatapathId(),
+                        port,
+                        OpenflowVersion.get(features.getVersion()));
+
+                writeToTransaction(
+                    getInstanceIdentifier()
+                        .child(NodeConnector.class, new NodeConnectorKey(id))
+                        .augmentation(FlowCapableNodeConnectorStatisticsData.class)
+                        .child(FlowCapableNodeConnectorStatistics.class),
+                    new FlowCapableNodeConnectorStatisticsBuilder(stat)
+                        .build(),
+                    withParents);
+            });
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/QueueStatsMultipartWriter.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/QueueStatsMultipartWriter.java
new file mode 100644 (file)
index 0000000..6fe50d0
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.datastore.multipart;
+
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
+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.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.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.QueueIdAndStatisticsMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.flow.capable.node.connector.queue.statistics.FlowCapableNodeConnectorQueueStatisticsBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class QueueStatsMultipartWriter extends AbstractMultipartWriter<QueueIdAndStatisticsMap> {
+
+    public QueueStatsMultipartWriter(final TxFacade txFacade, final InstanceIdentifier<Node> instanceIdentifier) {
+        super(txFacade, instanceIdentifier);
+    }
+
+    @Override
+    protected Class<QueueIdAndStatisticsMap> getType() {
+        return QueueIdAndStatisticsMap.class;
+    }
+
+    @Override
+    public void storeStatistics(final QueueIdAndStatisticsMap statistics, final boolean withParents) {
+        statistics.getQueueIdAndStatisticsMap()
+            .forEach(stat -> writeToTransaction(
+                getInstanceIdentifier()
+                    .child(NodeConnector.class, new NodeConnectorKey(stat.getNodeConnectorId()))
+                    .augmentation(FlowCapableNodeConnector.class)
+                    .child(Queue.class, new QueueKey(stat.getQueueId())),
+                new QueueBuilder()
+                    .setKey(new QueueKey(stat.getQueueId()))
+                    .setQueueId(stat.getQueueId())
+                    .addAugmentation(
+                        FlowCapableNodeConnectorQueueStatisticsData.class,
+                        new FlowCapableNodeConnectorQueueStatisticsDataBuilder()
+                            .setFlowCapableNodeConnectorQueueStatistics(
+                                new FlowCapableNodeConnectorQueueStatisticsBuilder(stat).build())
+                            .build())
+                    .build(),
+                withParents));
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/TableFeaturesMultipartWriter.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/TableFeaturesMultipartWriter.java
new file mode 100644 (file)
index 0000000..f839ac3
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.datastore.multipart;
+
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
+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.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeaturesKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class TableFeaturesMultipartWriter extends AbstractMultipartWriter<TableFeatures> {
+
+    public TableFeaturesMultipartWriter(final TxFacade txFacade,
+                                        final InstanceIdentifier<Node> instanceIdentifier) {
+        super(txFacade, instanceIdentifier);
+    }
+
+    @Override
+    protected Class<TableFeatures> getType() {
+        return TableFeatures.class;
+    }
+
+    @Override
+    public void storeStatistics(final TableFeatures statistics, final boolean withParents) {
+        statistics.getTableFeatures()
+            .forEach(stat -> {
+                writeToTransaction(getInstanceIdentifier()
+                        .augmentation(FlowCapableNode.class)
+                        .child(org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features
+                                .TableFeatures.class,
+                            new TableFeaturesKey(stat.getTableId())),
+                    stat,
+                    withParents);
+
+                // Write parent for table statistics
+                writeToTransaction(getInstanceIdentifier()
+                        .augmentation(FlowCapableNode.class)
+                        .child(Table.class, new TableKey(stat.getTableId())),
+                    new TableBuilder()
+                        .setId(stat.getTableId())
+                        .addAugmentation(FlowTableStatisticsData.class, new FlowTableStatisticsDataBuilder()
+                            .build())
+                        .build(),
+                    withParents);
+            });
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/TableStatsMultipartWriter.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/TableStatsMultipartWriter.java
new file mode 100644 (file)
index 0000000..95758ab
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.datastore.multipart;
+
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableAndStatisticsMap;
+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.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.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class TableStatsMultipartWriter extends AbstractMultipartWriter<FlowTableAndStatisticsMap> {
+
+    public TableStatsMultipartWriter(final TxFacade txFacade, final InstanceIdentifier<Node> instanceIdentifier) {
+        super(txFacade, instanceIdentifier);
+    }
+
+    @Override
+    protected Class<FlowTableAndStatisticsMap> getType() {
+        return FlowTableAndStatisticsMap.class;
+    }
+
+    @Override
+    public void storeStatistics(final FlowTableAndStatisticsMap statistics,
+                                final boolean withParents) {
+        statistics.getFlowTableAndStatisticsMap()
+            .forEach(stat -> writeToTransaction(
+                getInstanceIdentifier()
+                    .augmentation(FlowCapableNode.class)
+                    .child(Table.class, new TableKey(stat.getTableId().getValue()))
+                    .augmentation(FlowTableStatisticsData.class)
+                    .child(FlowTableStatistics.class),
+                new FlowTableStatisticsBuilder(stat).build(),
+                withParents));
+    }
+
+}
index cb01c5cabe2e0dd7ed805ba548e6791c0d68a9c4..43db4f34ebbd0f86013051c59257626f9ef35894 100644 (file)
@@ -23,6 +23,7 @@ import java.math.BigInteger;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
@@ -35,6 +36,7 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
 import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
+import org.opendaylight.openflowplugin.api.ConnectionException;
 import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
@@ -50,6 +52,7 @@ import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgColl
 import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
 import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
 import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
+import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
 import org.opendaylight.openflowplugin.api.openflow.registry.ItemLifeCycleRegistry;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
@@ -65,16 +68,19 @@ import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionCon
 import org.opendaylight.openflowplugin.extension.api.exception.ConversionException;
 import org.opendaylight.openflowplugin.extension.api.path.MessagePath;
 import org.opendaylight.openflowplugin.impl.common.ItemLifeCycleSourceImpl;
-import org.opendaylight.openflowplugin.impl.common.NodeStaticReplyTranslatorUtil;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProviderFactory;
+import org.opendaylight.openflowplugin.impl.device.initialization.AbstractDeviceInitializer;
+import org.opendaylight.openflowplugin.impl.device.initialization.DeviceInitializerProvider;
 import org.opendaylight.openflowplugin.impl.device.listener.MultiMsgCollectorImpl;
 import org.opendaylight.openflowplugin.impl.registry.flow.DeviceFlowRegistryImpl;
 import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
 import org.opendaylight.openflowplugin.impl.registry.group.DeviceGroupRegistryImpl;
 import org.opendaylight.openflowplugin.impl.registry.meter.DeviceMeterRegistryImpl;
 import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext;
-import org.opendaylight.openflowplugin.impl.util.DeviceInitializationUtils;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.openflowplugin.openflow.md.core.session.SwitchConnectionCookieOFImpl;
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.message.service.rev151020.ExperimenterMessageFromDevBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
@@ -91,7 +97,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev13
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.Error;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemoved;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketIn;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
@@ -159,23 +164,27 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     private volatile CONTEXT_STATE state;
     private ClusterInitializationPhaseHandler clusterInitializationPhaseHandler;
     private final DeviceManager myManager;
+    private final DeviceInitializerProvider deviceInitializerProvider;
     private final boolean useSingleLayerSerialization;
 
     DeviceContextImpl(
-            @Nonnull final ConnectionContext primaryConnectionContext,
-            @Nonnull final DataBroker dataBroker,
-            @Nonnull final MessageSpy messageSpy,
-            @Nonnull final TranslatorLibrary translatorLibrary,
-            @Nonnull final DeviceManager manager,
-            final ConvertorExecutor convertorExecutor,
-            final boolean skipTableFeatures,
-            final HashedWheelTimer hashedWheelTimer,
-            final DeviceManager myManager,
-            final boolean useSingleLayerSerialization) {
+        @Nonnull final ConnectionContext primaryConnectionContext,
+        @Nonnull final DataBroker dataBroker,
+        @Nonnull final MessageSpy messageSpy,
+        @Nonnull final TranslatorLibrary translatorLibrary,
+        @Nonnull final DeviceManager manager,
+        final ConvertorExecutor convertorExecutor,
+        final boolean skipTableFeatures,
+        final HashedWheelTimer hashedWheelTimer,
+        final DeviceManager myManager,
+        final boolean useSingleLayerSerialization,
+        final DeviceInitializerProvider deviceInitializerProvider) {
+
         this.primaryConnectionContext = primaryConnectionContext;
         this.deviceInfo = primaryConnectionContext.getDeviceInfo();
         this.hashedWheelTimer = hashedWheelTimer;
         this.myManager = myManager;
+        this.deviceInitializerProvider = deviceInitializerProvider;
         this.deviceState = new DeviceStateImpl();
         this.dataBroker = dataBroker;
         this.auxiliaryConnectionContexts = new HashMap<>();
@@ -295,18 +304,20 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
 
     @Override
     public void processReply(final OfHeader ofHeader) {
-        if (ofHeader instanceof Error) {
-            messageSpy.spyMessage(ofHeader.getImplementedInterface(), MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_FAILURE);
-        } else {
-            messageSpy.spyMessage(ofHeader.getImplementedInterface(), MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_SUCCESS);
-        }
+        messageSpy.spyMessage(
+            ofHeader.getImplementedInterface(),
+            (ofHeader instanceof Error)
+                ? MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_FAILURE
+                : MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_SUCCESS);
     }
 
     @Override
-    public void processReply(final Xid xid, final List<MultipartReply> ofHeaderList) {
-        for (final MultipartReply multipartReply : ofHeaderList) {
-            messageSpy.spyMessage(multipartReply.getImplementedInterface(), MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_FAILURE);
-        }
+    public void processReply(final Xid xid, final List<? extends OfHeader> ofHeaderList) {
+        ofHeaderList.forEach(header -> messageSpy.spyMessage(
+            header.getImplementedInterface(),
+            (header instanceof Error)
+                ? MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_FAILURE
+                : MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_SUCCESS));
     }
 
     @Override
@@ -370,7 +381,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     private KeyedInstanceIdentifier<NodeConnector, NodeConnectorKey> provideIIToNodeConnector(final long portNo, final short version) {
         final InstanceIdentifier<Node> iiToNodes = getDeviceInfo().getNodeInstanceIdentifier();
         final BigInteger dataPathId = getDeviceInfo().getDatapathId();
-        final NodeConnectorId nodeConnectorId = NodeStaticReplyTranslatorUtil.nodeConnectorId(dataPathId.toString(), portNo, version);
+        final NodeConnectorId nodeConnectorId = InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(dataPathId, portNo, OpenflowVersion.get(version));
         return iiToNodes.child(NodeConnector.class, new NodeConnectorKey(nodeConnectorId));
     }
 
@@ -485,8 +496,8 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     }
 
     @Override
-    public MultiMsgCollector getMultiMsgCollector(final RequestContext<List<MultipartReply>> requestContext) {
-        return new MultiMsgCollectorImpl(this, requestContext);
+    public <T extends OfHeader> MultiMsgCollector<T> getMultiMsgCollector(final RequestContext<List<T>> requestContext) {
+        return new MultiMsgCollectorImpl<>(this, requestContext);
     }
 
     @Override
@@ -648,8 +659,8 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     }
 
     @Override
-    public boolean isUseSingleLayerSerialization() {
-        return useSingleLayerSerialization;
+    public boolean canUseSingleLayerSerialization() {
+        return useSingleLayerSerialization && getDeviceInfo().getVersion() >= OFConstants.OFP_VERSION_1_3;
     }
 
     @Override
@@ -682,14 +693,21 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
         this.transactionChainManager.activateTransactionManager();
 
         try {
-            DeviceInitializationUtils.initializeNodeInformation(this, switchFeaturesMandatory, this.convertorExecutor);
+            final Optional<AbstractDeviceInitializer> initializer = deviceInitializerProvider
+                .lookup(deviceInfo.getVersion());
+
+            if (initializer.isPresent()) {
+                final MultipartWriterProvider writerProvider = MultipartWriterProviderFactory.createDefaultProvider(this);
+                initializer.get().initialize(this, switchFeaturesMandatory, writerProvider, convertorExecutor);
+            } else {
+                throw new ExecutionException(new ConnectionException("Unsupported version " + deviceInfo.getVersion()));
+            }
         } catch (ExecutionException | InterruptedException e) {
             LOG.warn("Device {} cannot be initialized: ", deviceInfo.getLOGValue(), e);
             return false;
         }
 
         Futures.addCallback(sendRoleChangeToDevice(OfpRole.BECOMEMASTER), new RpcResultFutureCallback());
-
         return this.clusterInitializationPhaseHandler.onContextInstantiateService(getPrimaryConnectionContext());
     }
 
index 9144f61d5e009c20c62c868e91082d213dcd5207..df49b1443769a6145fa754673ab673114b22c2b1 100644 (file)
@@ -51,9 +51,10 @@ import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.Messa
 import org.opendaylight.openflowplugin.extension.api.ExtensionConverterProviderKeeper;
 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
 import org.opendaylight.openflowplugin.impl.connection.OutboundQueueProviderImpl;
+import org.opendaylight.openflowplugin.impl.device.initialization.DeviceInitializerProvider;
 import org.opendaylight.openflowplugin.impl.device.listener.OpenflowProtocolListenerFullImpl;
 import org.opendaylight.openflowplugin.impl.lifecycle.LifecycleServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.SalRoleServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.SalRoleServiceImpl;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
@@ -78,6 +79,7 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
     private static final int SPY_RATE = 10;
 
     private final DataBroker dataBroker;
+    private final DeviceInitializerProvider deviceInitializerProvider;
     private final ConvertorExecutor convertorExecutor;
     private TranslatorLibrary translatorLibrary;
     private DeviceInitializationPhaseHandler deviceInitPhaseHandler;
@@ -109,9 +111,11 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
                              final HashedWheelTimer hashedWheelTimer,
                              final ConvertorExecutor convertorExecutor,
                              final boolean skipTableFeatures,
-                             final boolean useSingleLayerSerialization) {
+                             final boolean useSingleLayerSerialization,
+                             final DeviceInitializerProvider deviceInitializerProvider) {
 
         this.dataBroker = dataBroker;
+        this.deviceInitializerProvider = deviceInitializerProvider;
 
         /* merge empty nodes to oper DS to predict any problems with missing parent for Node */
         final WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
@@ -198,7 +202,6 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
         connectionContext.setOutboundQueueHandleRegistration(outboundQueueHandlerRegistration);
 
         final LifecycleService lifecycleService = new LifecycleServiceImpl();
-
         final DeviceContext deviceContext = new DeviceContextImpl(
                 connectionContext,
                 dataBroker,
@@ -209,7 +212,8 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
                 skipTableFeatures,
                 hashedWheelTimer,
                 this,
-                useSingleLayerSerialization);
+                useSingleLayerSerialization,
+                deviceInitializerProvider);
 
         deviceContext.setSalRoleService(new SalRoleServiceImpl(deviceContext, deviceContext));
         deviceContexts.put(deviceInfo, deviceContext);
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/AbstractDeviceInitializer.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/AbstractDeviceInitializer.java
new file mode 100644 (file)
index 0000000..25a84ef
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.device.initialization;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.api.ConnectionException;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractDeviceInitializer {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractDeviceInitializer.class);
+
+    /**
+     * Perform initial information gathering and store them to operational datastore
+     * @param deviceContext device context
+     * @param multipartWriterProvider multipart writer provider
+     */
+    public void initialize(@Nonnull final DeviceContext deviceContext,
+                           final boolean switchFeaturesMandatory,
+                           @Nullable final MultipartWriterProvider multipartWriterProvider,
+                           @Nullable final ConvertorExecutor convertorExecutor) throws ExecutionException,InterruptedException {
+        Preconditions.checkNotNull(deviceContext);
+
+        // Write node to datastore
+        LOG.debug("Initializing node information for node {}", deviceContext.getDeviceInfo().getLOGValue());
+        try {
+            deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, deviceContext
+                    .getDeviceInfo()
+                    .getNodeInstanceIdentifier(),
+                new NodeBuilder()
+                    .setId(deviceContext.getDeviceInfo().getNodeId())
+                    .setNodeConnector(Collections.emptyList())
+                    .build());
+        } catch (final Exception e) {
+            LOG.warn("Failed to write node {} to DS ", deviceContext.getDeviceInfo().getNodeId(), e);
+            throw new ExecutionException(new ConnectionException("Failed to write node " + deviceContext.getDeviceInfo().getNodeId() + " to DS ", e));
+        }
+
+        // Synchronously get information about device
+        initializeNodeInformation(deviceContext, switchFeaturesMandatory, multipartWriterProvider, convertorExecutor)
+            .get();
+    }
+
+    protected abstract Future<Void> initializeNodeInformation(@Nonnull final DeviceContext deviceContext,
+                                                              final boolean switchFeaturesMandatory,
+                                                              @Nullable final MultipartWriterProvider multipartWriterProvider,
+                                                              @Nullable final ConvertorExecutor convertorExecutor);
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/DeviceInitializerProvider.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/DeviceInitializerProvider.java
new file mode 100644 (file)
index 0000000..9ed66e9
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.device.initialization;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+public class DeviceInitializerProvider {
+
+    private final Map<Short, AbstractDeviceInitializer> initializers = new HashMap<>();
+
+    /**
+     * Register device initializer.
+     *
+     * @param version     the initializer version
+     * @param initializer the initializer instance
+     */
+    public void register(final Short version, final AbstractDeviceInitializer initializer) {
+        initializers.put(version, initializer);
+    }
+
+    /**
+     * Lookup  device initializer.
+     *
+     * @param version the initializer version
+     * @return the initializer instance
+     */
+    public Optional<AbstractDeviceInitializer> lookup(final Short version) {
+        return Optional.ofNullable(initializers.get(version));
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/DeviceInitializerProviderFactory.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/DeviceInitializerProviderFactory.java
new file mode 100644 (file)
index 0000000..a49515f
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.device.initialization;
+
+import org.opendaylight.openflowplugin.api.OFConstants;
+
+/**
+ * Multipart writer provider factory
+ */
+public class DeviceInitializerProviderFactory {
+
+    /**
+     * Create default #{@link org.opendaylight.openflowplugin.impl.device.initialization.DeviceInitializerProvider}
+     * @return the device initialization provider
+     */
+    public static DeviceInitializerProvider createDefaultProvider() {
+        final DeviceInitializerProvider provider = new DeviceInitializerProvider();
+        provider.register(OFConstants.OFP_VERSION_1_0, new OF10DeviceInitializer());
+        provider.register(OFConstants.OFP_VERSION_1_3, new OF13DeviceInitializer());
+        return provider;
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/OF10DeviceInitializer.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/OF10DeviceInitializer.java
new file mode 100644 (file)
index 0000000..a9f7386
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.device.initialization;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.List;
+import java.util.concurrent.Future;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
+import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
+import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.services.multilayer.MultiLayerMultipartCollectorService;
+import org.opendaylight.openflowplugin.impl.services.singlelayer.SingleLayerMultipartCollectorService;
+import org.opendaylight.openflowplugin.impl.util.DeviceInitializationUtil;
+import org.opendaylight.openflowplugin.impl.util.DeviceStateUtil;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.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.multipart.types.rev170112.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.CapabilitiesV10;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortGrouping;
+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.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OF10DeviceInitializer extends AbstractDeviceInitializer {
+
+    private static final Logger LOG = LoggerFactory.getLogger(OF10DeviceInitializer.class);
+
+    @Override
+    protected Future<Void> initializeNodeInformation(@Nonnull final DeviceContext deviceContext,
+                                                     final boolean switchFeaturesMandatory,
+                                                     @Nullable final MultipartWriterProvider multipartWriterProvider,
+                                                     @Nullable final ConvertorExecutor convertorExecutor) {
+        final ConnectionContext connectionContext = Preconditions.checkNotNull(deviceContext.getPrimaryConnectionContext());
+        final DeviceState deviceState = Preconditions.checkNotNull(deviceContext.getDeviceState());
+        final DeviceInfo deviceInfo = Preconditions.checkNotNull(deviceContext.getDeviceInfo());
+        final CapabilitiesV10 capabilitiesV10 = connectionContext.getFeatures().getCapabilitiesV10();
+
+        // Set capabilities for this device based on capabilities of connection context
+        LOG.debug("Setting capabilities for device {}", deviceInfo.getLOGValue());
+        DeviceStateUtil.setDeviceStateBasedOnV10Capabilities(deviceState, capabilitiesV10);
+        final ListenableFuture<Boolean> future = requestMultipart(MultipartType.OFPMPDESC, deviceContext);
+
+        Futures.addCallback(future, new FutureCallback<Boolean>() {
+            @Override
+            public void onSuccess(@Nullable final Boolean result) {
+                if (Boolean.TRUE.equals(result)) {
+                    LOG.debug("Creating empty flow capable node: {}", deviceInfo.getLOGValue());
+                    makeEmptyFlowCapableNode(deviceContext, deviceInfo);
+
+                    LOG.debug("Creating empty tables for {}", deviceInfo.getLOGValue());
+                    DeviceInitializationUtil.makeEmptyTables(
+                        deviceContext,
+                        deviceInfo,
+                        deviceContext.getPrimaryConnectionContext().getFeatures().getTables());
+                }
+            }
+
+            @Override
+            public void onFailure(@Nonnull final Throwable t) {
+                LOG.warn("Error occurred in preparation node {} for protocol 1.0", deviceInfo.getLOGValue());
+                LOG.trace("Error for node {} : ", deviceInfo.getLOGValue(), t);
+            }
+        });
+
+        return Futures.transform(future, new Function<Boolean, Void>() {
+            @Nullable
+            @Override
+            public Void apply(@Nullable final Boolean input) {
+                writePhyPortInformation(deviceContext);
+                return null;
+            }
+        });
+    }
+
+    private static void writePhyPortInformation(final DeviceContext deviceContext) {
+        final DeviceInfo deviceInfo = deviceContext.getDeviceInfo();
+        final ConnectionContext connectionContext = deviceContext.getPrimaryConnectionContext();
+        final MessageTranslator<PortGrouping, FlowCapableNodeConnector> translator = deviceContext
+            .oook()
+            .lookupTranslator(new TranslatorKey(deviceInfo.getVersion(), PortGrouping.class.getName()));
+
+        connectionContext.getFeatures().getPhyPort().forEach(port -> {
+            final NodeConnectorId nodeConnectorId = InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(
+                deviceInfo.getDatapathId(),
+                port.getPortNo(),
+                OpenflowVersion.get(deviceInfo.getVersion()));
+
+            try {
+                deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL,
+                    deviceInfo
+                        .getNodeInstanceIdentifier()
+                        .child(NodeConnector.class, new NodeConnectorKey(nodeConnectorId)),
+                    new NodeConnectorBuilder()
+                        .setId(nodeConnectorId)
+                        .addAugmentation(
+                            FlowCapableNodeConnector.class,
+                            translator.translate(port, deviceInfo, null))
+                        .addAugmentation(
+                            FlowCapableNodeConnectorStatisticsData.class,
+                            new FlowCapableNodeConnectorStatisticsDataBuilder().build())
+                        .build());
+            } catch (final Exception e) {
+                LOG.debug("Failed to write node {} to DS ", deviceInfo.getLOGValue(), e);
+            }
+        });
+    }
+
+    private static void makeEmptyFlowCapableNode(final TxFacade txFacade, final DeviceInfo deviceInfo) {
+        try {
+            txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL,
+                deviceInfo
+                    .getNodeInstanceIdentifier()
+                    .augmentation(FlowCapableNode.class),
+                new FlowCapableNodeBuilder().build());
+        } catch (final Exception e) {
+            LOG.debug("Failed to write empty node {} to DS ", deviceInfo.getLOGValue(), e);
+        }
+    }
+
+    private static ListenableFuture<Boolean> requestMultipart(final MultipartType multipartType,
+                                                              final DeviceContext deviceContext) {
+        if (deviceContext.canUseSingleLayerSerialization()) {
+            final SingleLayerMultipartCollectorService service =
+                new SingleLayerMultipartCollectorService(deviceContext, deviceContext);
+
+            return Futures.transform(service.handleServiceCall(multipartType), new Function<RpcResult<List<MultipartReply>>, Boolean>() {
+                @Nullable
+                @Override
+                public Boolean apply(final RpcResult<List<MultipartReply>> input) {
+                    return input.isSuccessful();
+                }
+            });
+        }
+
+        final MultiLayerMultipartCollectorService service =
+            new MultiLayerMultipartCollectorService(deviceContext, deviceContext);
+
+        return Futures.transform(service.handleServiceCall(multipartType), new Function<RpcResult<List<org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply>>, Boolean>() {
+            @Nullable
+            @Override
+            public Boolean apply(final RpcResult<List<org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply>> input) {
+                return input.isSuccessful();
+            }
+        });
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/OF13DeviceInitializer.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/OF13DeviceInitializer.java
new file mode 100644 (file)
index 0000000..abb1b70
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.device.initialization;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.Future;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.impl.common.MultipartReplyTranslatorUtil;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.services.multilayer.MultiLayerMultipartCollectorService;
+import org.opendaylight.openflowplugin.impl.services.singlelayer.SingleLayerMultipartCollectorService;
+import org.opendaylight.openflowplugin.impl.util.DeviceInitializationUtil;
+import org.opendaylight.openflowplugin.impl.util.DeviceStateUtil;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.Capabilities;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OF13DeviceInitializer extends AbstractDeviceInitializer {
+
+    private static final Logger LOG = LoggerFactory.getLogger(OF13DeviceInitializer.class);
+
+    @Override
+    protected Future<Void> initializeNodeInformation(@Nonnull final DeviceContext deviceContext,
+                                                     final boolean switchFeaturesMandatory,
+                                                     @Nullable final MultipartWriterProvider multipartWriterProvider,
+                                                     @Nullable final ConvertorExecutor convertorExecutor) {
+        final ConnectionContext connectionContext = Preconditions.checkNotNull(deviceContext.getPrimaryConnectionContext());
+        final DeviceState deviceState = Preconditions.checkNotNull(deviceContext.getDeviceState());
+        final DeviceInfo deviceInfo = Preconditions.checkNotNull(deviceContext.getDeviceInfo());
+        final Capabilities capabilities = connectionContext.getFeatures().getCapabilities();
+        LOG.debug("Setting capabilities for device {}", deviceInfo.getLOGValue());
+        DeviceStateUtil.setDeviceStateBasedOnV13Capabilities(deviceState, capabilities);
+
+        // First process description reply, write data to DS and write consequent data if successful
+        return  Futures.transform(
+            requestMultipart(MultipartType.OFPMPDESC, deviceContext),
+            (AsyncFunction<RpcResult<List<OfHeader>>, Void>) input -> {
+                translateAndWriteResult(
+                    MultipartType.OFPMPDESC,
+                    input.getResult(),
+                    deviceContext,
+                    multipartWriterProvider,
+                    convertorExecutor);
+
+                final List<ListenableFuture<RpcResult<List<OfHeader>>>> futures = new ArrayList<>();
+                futures.add(requestAndProcessMultipart(MultipartType.OFPMPMETERFEATURES, deviceContext, multipartWriterProvider, convertorExecutor));
+                futures.add(requestAndProcessMultipart(MultipartType.OFPMPGROUPFEATURES, deviceContext, multipartWriterProvider, convertorExecutor));
+                futures.add(requestAndProcessMultipart(MultipartType.OFPMPTABLEFEATURES, deviceContext, multipartWriterProvider, convertorExecutor));
+                futures.add(requestAndProcessMultipart(MultipartType.OFPMPPORTDESC, deviceContext, multipartWriterProvider, convertorExecutor));
+
+                return Futures.transform(
+                    (switchFeaturesMandatory ? Futures.allAsList(futures) : Futures.successfulAsList(futures)),
+                    new Function<List<RpcResult<List<OfHeader>>>, Void>() {
+                        @Nullable
+                        @Override
+                        public Void apply(@Nullable final List<RpcResult<List<OfHeader>>> input) {
+                            LOG.info("Static node {} successfully finished collecting", deviceContext.getDeviceInfo().getLOGValue());
+                            return null;
+                        }
+                    });
+            });
+
+    }
+
+    /**
+     * Request multipart of specified type and then run some processing on it
+     * @param type multipart type
+     * @param deviceContext device context
+     * @param multipartWriterProvider multipart writer provider
+     * @param convertorExecutor convertor executor
+     * @return list of multipart messages unified to parent interface
+     */
+    private static ListenableFuture<RpcResult<List<OfHeader>>> requestAndProcessMultipart(final MultipartType type,
+                                                                                          final DeviceContext deviceContext,
+                                                                                          final MultipartWriterProvider multipartWriterProvider,
+                                                                                          @Nullable final ConvertorExecutor convertorExecutor) {
+        final ListenableFuture<RpcResult<List<OfHeader>>> rpcResultListenableFuture =
+            MultipartType.OFPMPTABLEFEATURES.equals(type) && deviceContext.isSkipTableFeatures()
+                ? RpcResultBuilder.<List<OfHeader>>success().buildFuture()
+                : requestMultipart(type, deviceContext);
+
+        createCallback(type, rpcResultListenableFuture, deviceContext, multipartWriterProvider, convertorExecutor);
+        return rpcResultListenableFuture;
+    }
+
+    /**
+     * Inject callback ti future for specified multipart type. This callback will translate and write
+     * result of multipart messages
+     * @param type multipart type
+     * @param future multipart collection future
+     * @param deviceContext device context
+     * @param multipartWriterProvider multipart writer provider
+     * @param convertorExecutor convertor executor
+     */
+    private static void createCallback(final MultipartType type,
+                                       final ListenableFuture<RpcResult<List<OfHeader>>> future,
+                                       final DeviceContext deviceContext,
+                                       @Nullable final MultipartWriterProvider multipartWriterProvider,
+                                       @Nullable final ConvertorExecutor convertorExecutor) {
+        Futures.addCallback(future, new FutureCallback<RpcResult<List<OfHeader>>>() {
+            @Override
+            public void onSuccess(final RpcResult<List<OfHeader>> result) {
+                if (Objects.nonNull(result.getResult())) {
+                    LOG.info("Static node {} info: {} collected", deviceContext.getDeviceInfo().getLOGValue(), type);
+                    translateAndWriteResult(
+                        type,
+                        result.getResult(),
+                        deviceContext,
+                        multipartWriterProvider,
+                        convertorExecutor);
+                } else {
+                    result.getErrors().forEach(rpcError -> {
+                        LOG.warn("Failed to retrieve static node {} info: {}", type, rpcError.getMessage());
+
+                        if (LOG.isTraceEnabled() && Objects.nonNull(rpcError.getCause())) {
+                            LOG.trace("Detailed error:", rpcError.getCause());
+                        }
+                    });
+
+                    // If table features are disabled or returned nothing, at least make empty tables
+                    if (MultipartType.OFPMPTABLEFEATURES.equals(type)) {
+                        DeviceInitializationUtil.makeEmptyTables(
+                            deviceContext,
+                            deviceContext.getDeviceInfo(),
+                            deviceContext.getPrimaryConnectionContext().getFeatures().getTables());
+                    }
+                }
+            }
+
+            @Override
+            public void onFailure(@Nonnull final Throwable t) {
+                LOG.warn("Request of type {} for static info of node {} failed.", type, deviceContext.getDeviceInfo().getLOGValue());
+            }
+        });
+    }
+
+    /**
+     * Translate and write multipart messages from OpenflowJava
+     * @param type multipart type
+     * @param result multipart messages
+     * @param deviceContext device context
+     * @param multipartWriterProvider multipart writer provider
+     * @param convertorExecutor convertor executor
+     */
+    private static void translateAndWriteResult(final MultipartType type,
+                                                final List<OfHeader> result,
+                                                final DeviceContext deviceContext,
+                                                @Nullable final MultipartWriterProvider multipartWriterProvider,
+                                                @Nullable final ConvertorExecutor convertorExecutor) {
+        if (Objects.nonNull(result)) {
+            try {
+                result.forEach(reply -> {
+                    // First, translate collected data to proper openflowplugin representation
+                    MultipartReplyTranslatorUtil
+                        .translate(
+                            reply,
+                            deviceContext.getDeviceInfo(),
+                            convertorExecutor,
+                            deviceContext.oook())
+                        .ifPresent(translatedReply -> {
+                            // If we collected meter features, check if we have support for meters
+                            // and pass this information to device context
+                            if (MultipartType.OFPMPMETERFEATURES.equals(type) &&
+                                translatedReply instanceof MeterFeatures) {
+                                final MeterFeatures meterFeatures = (MeterFeatures) translatedReply;
+
+                                if (meterFeatures.getMaxMeter().getValue() > 0) {
+                                    deviceContext.getDeviceState().setMeterAvailable(true);
+                                }
+                            }
+
+                            // Now. try to write translated collected features
+                            Optional.ofNullable(multipartWriterProvider)
+                                .flatMap(provider -> provider.lookup(type))
+                                .ifPresent(writer -> writer.write(translatedReply, false));
+                        });
+                });
+            } catch (final Exception e) {
+                LOG.warn("Failed to write node {} to DS ", deviceContext.getDeviceInfo().getLOGValue(), e);
+            }
+        } else {
+            LOG.warn("Failed to write node {} to DS because we failed to gather device info.",
+                deviceContext.getDeviceInfo().getLOGValue());
+        }
+    }
+
+    /**
+     * Send request to device and unify different possible reply types from OpenflowJava to common parent interface
+     * @param multipartType multipart type
+     * @param deviceContext device context
+     * @return unified replies
+     */
+    private static ListenableFuture<RpcResult<List<OfHeader>>> requestMultipart(final MultipartType multipartType,
+                                                                                final DeviceContext deviceContext) {
+        if (deviceContext.canUseSingleLayerSerialization()) {
+            final SingleLayerMultipartCollectorService service =
+                new SingleLayerMultipartCollectorService(deviceContext, deviceContext);
+
+            return Futures.transform(service.handleServiceCall(multipartType), new Function<RpcResult<List<MultipartReply>>, RpcResult<List<OfHeader>>>() {
+                @Nullable
+                @Override
+                public RpcResult<List<OfHeader>> apply(final RpcResult<List<MultipartReply>> input) {
+                    if (Objects.isNull(input.getResult()) && input.isSuccessful()) {
+                        final List<OfHeader> temp = null;
+                        return RpcResultBuilder.success(temp).build();
+                    }
+
+                    return input.isSuccessful()
+                        ? RpcResultBuilder.success(input
+                        .getResult()
+                        .stream()
+                        .map(reply -> (OfHeader) reply)
+                        .collect(Collectors.toList()))
+                        .build()
+                        : RpcResultBuilder.<List<OfHeader>>failed()
+                        .withRpcErrors(input.getErrors())
+                        .build();
+                }
+            });
+        }
+
+        final MultiLayerMultipartCollectorService service =
+            new MultiLayerMultipartCollectorService(deviceContext, deviceContext);
+
+        return Futures.transform(service.handleServiceCall(multipartType), new Function<RpcResult<List<org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply>>, RpcResult<List<OfHeader>>>() {
+            @Nullable
+            @Override
+            public RpcResult<List<OfHeader>> apply(final RpcResult<List<org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply>> input) {
+                if (Objects.isNull(input.getResult()) && input.isSuccessful()) {
+                    final List<OfHeader> temp = null;
+                    return RpcResultBuilder.success(temp).build();
+                }
+
+                return input.isSuccessful()
+                    ? RpcResultBuilder.success(input
+                    .getResult()
+                    .stream()
+                    .map(reply -> (OfHeader) reply)
+                    .collect(Collectors.toList()))
+                    .build()
+                    : RpcResultBuilder.<List<OfHeader>>failed()
+                    .withRpcErrors(input.getErrors())
+                    .build();
+            }
+        });
+    }
+
+}
index b373427f59812140844072567529421e78bcbd63..532a81fbf893f19924281b7dd7753d9274f4ef1f 100644 (file)
@@ -11,14 +11,15 @@ package org.opendaylight.openflowplugin.impl.device.listener;
 import com.google.common.base.Preconditions;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceReplyProcessor;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
 import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.EventsTimeCounter;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
@@ -34,54 +35,38 @@ import org.slf4j.LoggerFactory;
  *         </p>
  *         Created: Mar 23, 2015
  */
-public class MultiMsgCollectorImpl implements MultiMsgCollector {
-
+public class MultiMsgCollectorImpl<T extends OfHeader> implements MultiMsgCollector<T> {
     private static final Logger LOG = LoggerFactory.getLogger(MultiMsgCollectorImpl.class);
-
-    private final List<MultipartReply> replyCollection = new ArrayList<>();
-    private final RequestContext<List<MultipartReply>> requestContext;
+    private final List<T> replyCollection = new ArrayList<>();
+    private final RequestContext<List<T>> requestContext;
     private final DeviceReplyProcessor deviceReplyProcessor;
-    private MultipartType msgType;
 
-    public MultiMsgCollectorImpl(final DeviceReplyProcessor deviceReplyProcessor, final RequestContext<List<MultipartReply>> requestContext) {
+    public MultiMsgCollectorImpl(final DeviceReplyProcessor deviceReplyProcessor, final RequestContext<List<T>> requestContext) {
         this.deviceReplyProcessor = Preconditions.checkNotNull(deviceReplyProcessor);
         this.requestContext = Preconditions.checkNotNull(requestContext);
     }
 
     @Override
-    public void addMultipartMsg(final MultipartReply reply) {
-        addMultipartMsg(reply, null);
-    }
-
-    @Override
-    public void addMultipartMsg(@Nonnull final MultipartReply reply, @Nonnull final EventIdentifier eventIdentifier) {
+    public void addMultipartMsg(@Nonnull final T reply, final boolean reqMore, @Nullable final EventIdentifier eventIdentifier) {
         Preconditions.checkNotNull(reply);
+        Preconditions.checkNotNull(requestContext.getXid());
         Preconditions.checkArgument(requestContext.getXid().getValue().equals(reply.getXid()));
         LOG.trace("Try to add Multipart reply msg with XID {}", reply.getXid());
-
-        if (msgType == null) {
-            msgType = reply.getType();
-        }
-
-        if (!msgType.equals(reply.getType())) {
-            LOG.warn("MultiMsgCollector get incorrect multipart msg with type {} but expected type is {}", reply.getType(), msgType);
-        }
-
         replyCollection.add(reply);
-        if (!reply.getFlags().isOFPMPFREQMORE()) {
+
+        if (!reqMore) {
             endCollecting(eventIdentifier);
         }
     }
 
-    public void endCollecting() {
-        endCollecting(null);
-    }
+    @Override
+    public void endCollecting(@Nullable final EventIdentifier eventIdentifier) {
+        final RpcResult<List<T>> rpcResult = RpcResultBuilder.success(replyCollection).build();
 
-    public void endCollecting(final EventIdentifier eventIdentifier) {
-        final RpcResult<List<MultipartReply>> rpcResult = RpcResultBuilder.success(replyCollection).build();
-        if (null != eventIdentifier) {
+        if (Objects.nonNull(eventIdentifier)) {
             EventsTimeCounter.markEnd(eventIdentifier);
         }
+
         requestContext.setResult(rpcResult);
         requestContext.close();
         deviceReplyProcessor.processReply(requestContext.getXid(), replyCollection);
index 58ff11884096e79af2a8d431768027f376872370..e88138385fb8fa119309b5a09a3499af78c85187 100644 (file)
@@ -24,7 +24,10 @@ public class DeserializerInjector {
         MatchDeserializerInjector.injectDeserializers(provider);
         ActionDeserializerInjector.injectDeserializers(provider);
         InstructionDeserializerInjector.injectDeserializers(provider);
-        MessageDeserializerInjector.injectDeserializers(provider);
         MultipartDeserializerInjector.injectDeserializers(provider);
+
+        // Message deserializers are not used, so disable them here
+        // Uncomment to enable
+        // MessageDeserializerInjector.injectDeserializers(provider);
     }
 }
index abd9df9c86a1f3f9a56b20d79c39c163e37d5739..14795a8c9637401878ed0058d5be2f23d6585060 100644 (file)
@@ -53,6 +53,7 @@ public class MultipartReplyGroupDescDeserializer implements OFDeserializer<Multi
 
             message.skipBytes(PADDING_IN_GROUP_DESC_HEADER);
             itemBuilder.setGroupId(new GroupId(message.readUnsignedInt()));
+            itemBuilder.setKey(new GroupDescStatsKey(itemBuilder.getGroupId()));
 
             final List<Bucket> subItems = new ArrayList<>();
             int actualLength = GROUP_DESC_HEADER_LENGTH;
@@ -68,8 +69,6 @@ public class MultipartReplyGroupDescDeserializer implements OFDeserializer<Multi
                     .setWatchPort(message.readUnsignedInt())
                     .setWatchGroup(message.readUnsignedInt());
 
-                bucketKey++;
-
                 message.skipBytes(PADDING_IN_BUCKETS_HEADER);
                 final List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list
                     .Action> actions = new ArrayList<>();
@@ -90,11 +89,11 @@ public class MultipartReplyGroupDescDeserializer implements OFDeserializer<Multi
 
                 bucketBuilder.setAction(actions);
                 subItems.add(bucketBuilder.build());
+                bucketKey++;
                 actualLength += bucketsLength;
             }
 
             items.add(itemBuilder
-                .setKey(new GroupDescStatsKey(itemBuilder.getGroupId()))
                 .setBuckets(new BucketsBuilder()
                     .setBucket(subItems)
                     .build())
@@ -5,31 +5,34 @@
  * 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.openflowplugin.impl.statistics.services;
+package org.opendaylight.openflowplugin.impl.services;
 
 import com.google.common.base.MoreObjects;
+import java.util.concurrent.Future;
 import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.impl.services.AbstractMultipartService;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchReactor;
 import org.opendaylight.openflowplugin.openflow.md.util.FlowCreatorUtil;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestAggregateCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.aggregate._case.MultipartRequestAggregateBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
 
-final class MatchingFlowsInTableService extends AbstractMultipartService<GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput> {
+public abstract class AbstractAggregateFlowMultipartService<T extends OfHeader>
+    extends AbstractMultipartService<GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput, T> {
 
     private final ConvertorExecutor convertorExecutor;
 
-    public MatchingFlowsInTableService(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final ConvertorExecutor convertorExecutor) {
+    public AbstractAggregateFlowMultipartService(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final ConvertorExecutor convertorExecutor) {
         super(requestContextStack, deviceContext);
         this.convertorExecutor = convertorExecutor;
     }
@@ -38,7 +41,7 @@ final class MatchingFlowsInTableService extends AbstractMultipartService<GetAggr
     protected OfHeader buildRequest(final Xid xid, final GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput input) throws ServiceException {
         final MultipartRequestAggregateCaseBuilder multipartRequestAggregateCaseBuilder = new MultipartRequestAggregateCaseBuilder();
         final MultipartRequestAggregateBuilder mprAggregateRequestBuilder = new MultipartRequestAggregateBuilder();
-        final short tableId = MoreObjects.firstNonNull(input.getTableId(), OFConstants.OFPTT_ALL).shortValue();
+        final short tableId = MoreObjects.firstNonNull(input.getTableId(), OFConstants.OFPTT_ALL);
         mprAggregateRequestBuilder.setTableId(tableId);
         long outputPortValue = MoreObjects.firstNonNull(input.getOutPort(), OFConstants.OFPP_ANY).longValue();
         mprAggregateRequestBuilder.setOutPort(outputPortValue);
@@ -57,7 +60,7 @@ final class MatchingFlowsInTableService extends AbstractMultipartService<GetAggr
             } else {
                 mprAggregateRequestBuilder.setCookieMask(MoreObjects.firstNonNull(input.getCookieMask().getValue(), OFConstants.DEFAULT_COOKIE_MASK));
             }
-            long outGroup = MoreObjects.firstNonNull(input.getOutGroup(), OFConstants.OFPG_ANY).longValue();
+            long outGroup = MoreObjects.firstNonNull(input.getOutGroup(), OFConstants.OFPG_ANY);
             mprAggregateRequestBuilder.setOutGroup(outGroup);
         } else {
             mprAggregateRequestBuilder.setOutGroup(OFConstants.OFPG_ANY);
@@ -80,4 +83,13 @@ final class MatchingFlowsInTableService extends AbstractMultipartService<GetAggr
 
         return mprInput.build();
     }
+
+    /**
+     * Process input and return reply
+     * @param input input
+     * @return reply
+     */
+    public abstract Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>> handleAndReply(
+        final GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput input);
+
 }
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractExperimenterMultipartService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractExperimenterMultipartService.java
new file mode 100644 (file)
index 0000000..a2fc142
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+
+import java.util.Objects;
+import java.util.concurrent.Future;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.extension.api.ConvertorMessageToOFJava;
+import org.opendaylight.openflowplugin.extension.api.TypeVersionKey;
+import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
+import org.opendaylight.openflowplugin.extension.api.exception.ConversionException;
+import org.opendaylight.openflowplugin.extension.api.exception.ConverterNotFoundException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.experimenter.core.ExperimenterDataOfChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestExperimenterCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.experimenter._case.MultipartRequestExperimenterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.experimenter.types.rev151020.experimenter.core.message.ExperimenterMessageOfChoice;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+public abstract class AbstractExperimenterMultipartService<T extends OfHeader> extends AbstractMultipartService<SendExperimenterMpRequestInput, T> {
+
+    private final ExtensionConverterProvider extensionConverterProvider;
+
+    protected AbstractExperimenterMultipartService(RequestContextStack requestContextStack, DeviceContext deviceContext,
+                                                   ExtensionConverterProvider extensionConverterProvider) {
+        super(requestContextStack, deviceContext);
+        this.extensionConverterProvider = extensionConverterProvider;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    protected OfHeader buildRequest(Xid xid, SendExperimenterMpRequestInput input) throws ServiceException {
+        final TypeVersionKey key = new TypeVersionKey<>(
+                input.getExperimenterMessageOfChoice().getImplementedInterface(),
+                getVersion());
+
+        final ConvertorMessageToOFJava<ExperimenterMessageOfChoice, ExperimenterDataOfChoice> messageConverter =
+                getExtensionConverterProvider().getMessageConverter(key);
+
+        if (Objects.isNull(messageConverter)) {
+            throw new ServiceException(new ConverterNotFoundException(key.toString()));
+        }
+
+        try {
+            return RequestInputUtils
+                .createMultipartHeader(MultipartType.OFPMPEXPERIMENTER, xid.getValue(), getVersion())
+                .setMultipartRequestBody(new MultipartRequestExperimenterCaseBuilder()
+                        .setMultipartRequestExperimenter(new MultipartRequestExperimenterBuilder()
+                                .setExperimenter(messageConverter.getExperimenterId())
+                                .setExpType(messageConverter.getType())
+                                .setExperimenterDataOfChoice(messageConverter
+                                        .convert(input.getExperimenterMessageOfChoice()))
+                                .build())
+                        .build())
+                .build();
+        } catch (final ConversionException e) {
+            throw new ServiceException(e);
+        }
+    }
+
+    /**
+     * Get extension converter provider
+     * @return extension converter provider
+     */
+    protected ExtensionConverterProvider getExtensionConverterProvider() {
+        return extensionConverterProvider;
+    }
+
+    /**
+     * Process experimenter input and result experimenter output
+     * @param input experimenter input
+     * @return experimenter output
+     */
+    public abstract Future<RpcResult<SendExperimenterMpRequestOutput>> handleAndReply(SendExperimenterMpRequestInput input);
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractMessageService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractMessageService.java
deleted file mode 100644 (file)
index 96e8c40..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
-
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
-import org.opendaylight.yangtools.concepts.Builder;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-
-abstract class AbstractMessageService<R extends DataObject, I extends Builder<? extends R>, O extends DataObject>
-        extends AbstractSimpleService<R, O> {
-    private final boolean useSingleLayerSerialization;
-
-    protected AbstractMessageService(RequestContextStack requestContextStack, DeviceContext deviceContext, Class<O> clazz) {
-        super(requestContextStack, deviceContext, clazz);
-        useSingleLayerSerialization = deviceContext.isUseSingleLayerSerialization();
-    }
-
-    @Override
-    public ListenableFuture<RpcResult<O>> handleServiceCall(R input) {
-        return Futures.withFallback(super.handleServiceCall(input), t -> RpcResultBuilder.<O>failed().buildFuture());
-    }
-
-    /**
-     * Check if this service is supported in current OpenFlowPlugin configuration
-     * @return true if supported and single layer serialization is turned on
-     */
-    public boolean isSupported() {
-        return useSingleLayerSerialization;
-    }
-}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractMultipartCollectorService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractMultipartCollectorService.java
new file mode 100644 (file)
index 0000000..c643bf8
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+
+import com.google.common.util.concurrent.FutureCallback;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.impl.common.MultipartRequestInputFactory;
+import org.opendaylight.openflowplugin.impl.util.DeviceInitializationUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+
+public abstract class AbstractMultipartCollectorService<T extends OfHeader> extends AbstractMultipartService<MultipartType, T> {
+
+    protected AbstractMultipartCollectorService(final RequestContextStack requestContextStack, final DeviceContext deviceContext) {
+        super(requestContextStack, deviceContext);
+    }
+
+    @Override
+    protected FutureCallback<OfHeader> createCallback(RequestContext<List<T>> context, Class<?> requestType) {
+        final FutureCallback<OfHeader> callback = super.createCallback(context, requestType);
+
+        return new FutureCallback<OfHeader>() {
+            @Override
+            public void onSuccess(@Nullable final OfHeader result) {
+                callback.onSuccess(result);
+            }
+
+            @Override
+            public void onFailure(@Nonnull final Throwable t) {
+                // If we failed getting table features, at least create empty tables
+                if (MultipartType.OFPMPTABLEFEATURES.getClass().equals(requestType)) {
+                    DeviceInitializationUtil.makeEmptyTables(
+                        getTxFacade(),
+                        getDeviceInfo(),
+                        getDeviceContext().getPrimaryConnectionContext().getFeatures().getTables());
+                }
+
+                callback.onFailure(t);
+            }
+        };
+    }
+
+    @Override
+    protected OfHeader buildRequest(final Xid xid, final MultipartType input) {
+        return MultipartRequestInputFactory.makeMultipartRequestInput(xid.getValue(), getVersion(), input);
+    }
+}
index 06ccafd774f1d90495b6d0e7158206bf8d3fd9e8..9873807cb670190d8d7a07d28a74e0e7fc66e5d9 100644 (file)
@@ -13,25 +13,31 @@ import java.util.List;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.services.multilayer.MultiLayerFlowMultipartRequestOnTheFlyCallback;
+import org.opendaylight.openflowplugin.impl.services.singlelayer.SingleLayerFlowMultipartRequestOnTheFlyCallback;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 
-public abstract class AbstractMultipartOnTheFlyService<I> extends AbstractService<I, List<MultipartReply>> {
+public abstract class AbstractMultipartOnTheFlyService<I, T extends OfHeader> extends AbstractMultipartService<I, T> {
+
     private final ConvertorExecutor convertorExecutor;
+    private final MultipartWriterProvider statisticsWriterProvider;
 
-    protected AbstractMultipartOnTheFlyService(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final ConvertorExecutor convertorExecutor) {
+    protected AbstractMultipartOnTheFlyService(final RequestContextStack requestContextStack,
+                                               final DeviceContext deviceContext,
+                                               final ConvertorExecutor convertorExecutor,
+                                               final MultipartWriterProvider statisticsWriterProvider) {
         super(requestContextStack, deviceContext);
         this.convertorExecutor = convertorExecutor;
+        this.statisticsWriterProvider = statisticsWriterProvider;
     }
 
     @Override
-    protected final FutureCallback<OfHeader> createCallback(final RequestContext<List<MultipartReply>> context, final Class<?> requestType) {
-        return new MultipartRequestOnTheFlyCallback(context, requestType,
-                getMessageSpy(), getEventIdentifier(), getDeviceInfo(),
-                getDeviceContext().getDeviceFlowRegistry(), getTxFacade(),
-                convertorExecutor);
+    protected final FutureCallback<OfHeader> createCallback(final RequestContext<List<T>> context, final Class<?> requestType) {
+        return canUseSingleLayerSerialization()
+            ? new SingleLayerFlowMultipartRequestOnTheFlyCallback<>(context, requestType, getDeviceContext(), getEventIdentifier(), statisticsWriterProvider)
+            : new MultiLayerFlowMultipartRequestOnTheFlyCallback<>(context, requestType, getDeviceContext(), getEventIdentifier(), statisticsWriterProvider, convertorExecutor);
     }
 
-
 }
@@ -8,51 +8,65 @@
 package org.opendaylight.openflowplugin.impl.services;
 
 import java.util.List;
+import java.util.Objects;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-final class MultipartRequestCallback extends AbstractRequestCallback<List<MultipartReply>> {
-    private static final Logger LOG = LoggerFactory.getLogger(MultipartRequestCallback.class);
-    private final MultiMsgCollector collector;
+public abstract class AbstractMultipartRequestCallback<T extends OfHeader> extends AbstractRequestCallback<List<T>> {
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractMultipartRequestCallback.class);
+    private final MultiMsgCollector<T> collector;
 
-    public MultipartRequestCallback(final RequestContext<List<MultipartReply>> context, final Class<?> requestType, final DeviceContext deviceContext) {
-        super(context, requestType, deviceContext.getMessageSpy());
-        collector = deviceContext.getMultiMsgCollector(context);
-    }
-
-    public MultipartRequestCallback(final RequestContext<List<MultipartReply>> context,
-                                    final Class<?> requestType,
-                                    final DeviceContext deviceContext,
-                                    final EventIdentifier eventIdentifier) {
+    public AbstractMultipartRequestCallback(
+            final RequestContext<List<T>> context,
+            final Class<?> requestType,
+            final DeviceContext deviceContext,
+            final EventIdentifier eventIdentifier) {
         super(context, requestType, deviceContext.getMessageSpy(), eventIdentifier);
         collector = deviceContext.getMultiMsgCollector(context);
     }
 
     @Override
+    @SuppressWarnings("unchecked")
     public void onSuccess(final OfHeader result) {
-        if (result == null) {
-            LOG.info("Ofheader was null.");
+        if (Objects.isNull(result)) {
+            LOG.info("Response received was null.");
             collector.endCollecting(getEventIdentifier());
             return;
         }
 
-        if (!(result instanceof MultipartReply)) {
+        if (!isMultipart(result)) {
             LOG.info("Unexpected response type received {}.", result.getClass());
-            final RpcResultBuilder<List<MultipartReply>> rpcResultBuilder =
-                    RpcResultBuilder.<List<MultipartReply>>failed().withError(RpcError.ErrorType.APPLICATION,
-                            String.format("Unexpected response type received %s.", result.getClass()));
-            setResult(rpcResultBuilder.build());
+
+            setResult(RpcResultBuilder
+                    .<List<T>>failed()
+                    .withError(RpcError.ErrorType.APPLICATION,
+                            String.format("Unexpected response type received %s.", result.getClass()))
+                    .build());
         } else {
-            collector.addMultipartMsg((MultipartReply) result, getEventIdentifier());
+            final T resultCast = (T) result;
+            collector.addMultipartMsg(resultCast, isReqMore(resultCast), getEventIdentifier());
         }
     }
 
+    /**
+     * Check if result is multipart
+     * @param result result
+     * @return true if result is multipart
+     */
+    protected abstract boolean isMultipart(final OfHeader result);
+
+    /**
+     * Check if result requests more multiparts
+     * @param result result
+     * @return true if result requests more multiparts
+     */
+    protected abstract boolean isReqMore(final T result);
+
 }
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractMultipartRequestOnTheFlyCallback.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractMultipartRequestOnTheFlyCallback.java
new file mode 100644 (file)
index 0000000..36ece3d
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.openflowplugin.impl.services;
+
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.EventsTimeCounter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractMultipartRequestOnTheFlyCallback<T extends OfHeader> extends AbstractMultipartRequestCallback<T> {
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractMultipartRequestOnTheFlyCallback.class);
+    private final DeviceInfo deviceInfo;
+    private boolean finished = false;
+    private final EventIdentifier doneEventIdentifier;
+    private final TxFacade txFacade;
+    private final MultipartWriterProvider statisticsWriterProvider;
+
+    public AbstractMultipartRequestOnTheFlyCallback(final RequestContext<List<T>> context, Class<?> requestType,
+                                                    final DeviceContext deviceContext,
+                                                    final EventIdentifier eventIdentifier,
+                                                    final MultipartWriterProvider statisticsWriterProvider) {
+        super(context, requestType, deviceContext, eventIdentifier);
+        deviceInfo = deviceContext.getDeviceInfo();
+        doneEventIdentifier = new EventIdentifier(getMultipartType().name(), deviceContext.getDeviceInfo().getNodeId().toString());
+        txFacade = deviceContext;
+        this.statisticsWriterProvider = statisticsWriterProvider;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public void onSuccess(final OfHeader result) {
+        if (Objects.isNull(result)) {
+            LOG.info("OfHeader was null.");
+            if (!finished) {
+                endCollecting();
+                return;
+            }
+        } else if (finished) {
+            LOG.debug("Unexpected multipart response received: xid={}, {}", result.getXid(), result.getImplementedInterface());
+            return;
+        }
+
+        if (!isMultipart(result)) {
+            LOG.info("Unexpected response type received {}.", result.getClass());
+            setResult(RpcResultBuilder.<List<T>>failed().withError(RpcError.ErrorType.APPLICATION,
+                String.format("Unexpected response type received %s.", result.getClass())).build());
+            endCollecting();
+        } else {
+            final T resultCast = (T) result;
+
+            Futures.transform(processStatistics(resultCast), (Function<Optional<? extends MultipartReplyBody>, Void>) input -> {
+                input.ifPresent(reply -> {
+                    try {
+                        statisticsWriterProvider
+                            .lookup(getMultipartType())
+                            .ifPresent(writer -> writer.write(reply, false));
+                    } catch (final Exception ex) {
+                        LOG.warn("Stats processing of type {} for node {} failed during write-to-tx step",
+                            getMultipartType(), deviceInfo.getLOGValue(), ex);
+                    }
+                });
+
+                if (!isReqMore(resultCast)) {
+                    endCollecting();
+                }
+
+                return null;
+            });
+        }
+    }
+
+    /**
+     * Get tx facade
+     * @return tx facade
+     */
+    protected TxFacade getTxFacade() {
+        return txFacade;
+    }
+
+    /**
+     * Ends collecting of multipart data
+     */
+    private void endCollecting() {
+        EventsTimeCounter.markEnd(doneEventIdentifier);
+        EventsTimeCounter.markEnd(getEventIdentifier());
+        spyMessage(MessageSpy.STATISTIC_GROUP.FROM_SWITCH_TRANSLATE_OUT_SUCCESS);
+        txFacade.submitTransaction();
+        setResult(RpcResultBuilder.success(Collections.<T>emptyList()).build());
+        finished = true;
+    }
+
+    /**
+     * Process statistics.
+     *
+     * @param result result
+     */
+    protected abstract ListenableFuture<Optional<? extends MultipartReplyBody>> processStatistics(final T result);
+
+    /**
+     * Get multipart type
+     * @return multipart type
+     */
+    protected abstract MultipartType getMultipartType();
+
+
+}
index f2949cef162ac4cd505401b744e752902d36120c..d16f3b7ccf12434b897be81875586ac987db7c5f 100644 (file)
@@ -8,22 +8,40 @@
 package org.opendaylight.openflowplugin.impl.services;
 
 import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.ListenableFuture;
 import java.util.List;
+import java.util.function.Function;
+import javax.annotation.Nonnull;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.openflowplugin.impl.services.multilayer.MultiLayerMultipartRequestCallback;
+import org.opendaylight.openflowplugin.impl.services.singlelayer.SingleLayerMultipartRequestCallback;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+public abstract class AbstractMultipartService<I, T extends OfHeader> extends AbstractService<I, List<T>> {
+
+    private static final Function<OfHeader, Boolean> ALTERNATE_IS_COMPLETE = message ->
+        !(message instanceof MultipartReply) || !((MultipartReply) message).isRequestMore();
 
-public abstract class AbstractMultipartService<I> extends AbstractService<I, List<MultipartReply>> {
     protected AbstractMultipartService(final RequestContextStack requestContextStack, final DeviceContext deviceContext) {
         super(requestContextStack, deviceContext);
     }
 
     @Override
-    protected final FutureCallback<OfHeader> createCallback(final RequestContext<List<MultipartReply>> context, final Class<?> requestType) {
-        return new MultipartRequestCallback(context, requestType, getDeviceContext(), getEventIdentifier());
+    protected FutureCallback<OfHeader> createCallback(RequestContext<List<T>> context, Class<?> requestType) {
+        return canUseSingleLayerSerialization()
+            ? new SingleLayerMultipartRequestCallback<>(context, requestType, getDeviceContext(), getEventIdentifier())
+            : new MultiLayerMultipartRequestCallback<>(context, requestType, getDeviceContext(), getEventIdentifier());
     }
 
+    @Override
+    public final ListenableFuture<RpcResult<List<T>>> handleServiceCall(@Nonnull final I input) {
+        return canUseSingleLayerSerialization()
+            ? super.handleServiceCall(input, ALTERNATE_IS_COMPLETE)
+            : super.handleServiceCall(input);
+    }
 
 }
index ca6ddd759dca10f6b814bc8c4ee570666145126f..8992a7b5e1350d79155b1708331c930c9bb7be5a 100644 (file)
@@ -16,6 +16,7 @@ import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy.STATISTIC_GROUP;
+import org.opendaylight.openflowplugin.impl.services.util.RequestContextUtil;
 import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.EventsTimeCounter;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.Error;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
@@ -23,19 +24,12 @@ import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
-abstract class AbstractRequestCallback<T> implements FutureCallback<OfHeader> {
+public abstract class AbstractRequestCallback<T> implements FutureCallback<OfHeader> {
     private final RequestContext<T> context;
     private final Class<?> requestType;
     private final MessageSpy spy;
     private EventIdentifier eventIdentifier;
 
-
-    protected AbstractRequestCallback(final RequestContext<T> context, final Class<?> requestType, final MessageSpy spy) {
-        this.context = Preconditions.checkNotNull(context);
-        this.requestType = Preconditions.checkNotNull(requestType);
-        this.spy = Preconditions.checkNotNull(spy);
-    }
-
     protected AbstractRequestCallback(final RequestContext<T> context,
                                       final Class<?> requestType,
                                       final MessageSpy spy,
@@ -60,7 +54,7 @@ abstract class AbstractRequestCallback<T> implements FutureCallback<OfHeader> {
     }
 
     @Override
-    public final void onFailure(final Throwable t) {
+    public final void onFailure(@Nonnull final Throwable t) {
         final RpcResultBuilder<T> builder;
         if (null != eventIdentifier) {
             EventsTimeCounter.markEnd(eventIdentifier);
index 94804be16ca92b56f1aa5a9e3842ccb827a24004..3c267c9b42ef2db5655d2458320641c1dad002f8 100644 (file)
@@ -16,6 +16,7 @@ import java.math.BigInteger;
 import java.util.Objects;
 import java.util.function.Function;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
@@ -26,6 +27,8 @@ import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
+import org.opendaylight.openflowplugin.impl.services.util.RequestContextUtil;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.common.RpcError;
@@ -34,7 +37,7 @@ import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-abstract class AbstractService<I, O> {
+public abstract class AbstractService<I, O> {
     private static final Logger LOG = LoggerFactory.getLogger(AbstractService.class);
 
     private final short version;
@@ -54,6 +57,10 @@ abstract class AbstractService<I, O> {
         this.messageSpy = deviceContext.getMessageSpy();
     }
 
+    public boolean canUseSingleLayerSerialization() {
+        return deviceContext.canUseSingleLayerSerialization();
+    }
+
     public EventIdentifier getEventIdentifier() {
         return eventIdentifier;
     }
@@ -79,7 +86,7 @@ abstract class AbstractService<I, O> {
         return deviceContext;
     }
 
-    protected DeviceRegistry getDeviceRegistry() {
+    public DeviceRegistry getDeviceRegistry() {
         return deviceContext;
     }
 
@@ -104,26 +111,28 @@ abstract class AbstractService<I, O> {
     }
 
     public ListenableFuture<RpcResult<O>> handleServiceCall(@Nonnull final I input,
-            @Nonnull final Function<OfHeader, Boolean> isComplete) {
+            @Nullable final Function<OfHeader, Boolean> isComplete) {
         Preconditions.checkNotNull(input);
 
-        final Class<?> requestType;
-        if (input instanceof DataContainer) {
-            requestType = ((DataContainer) input).getImplementedInterface();
-        } else {
-            requestType = input.getClass();
-        }
+        final Class<?> requestType = input instanceof DataContainer
+            ? DataContainer.class.cast(input).getImplementedInterface()
+            : input.getClass();
+
         getMessageSpy().spyMessage(requestType, MessageSpy.STATISTIC_GROUP.TO_SWITCH_ENTERED);
 
         LOG.trace("Handling general service call");
         final RequestContext<O> requestContext = requestContextStack.createRequestContext();
-        if (requestContext == null) {
+
+        if (Objects.isNull(requestContext)) {
             LOG.trace("Request context refused.");
             getMessageSpy().spyMessage(AbstractService.class, MessageSpy.STATISTIC_GROUP.TO_SWITCH_DISREGARDED);
-            return failedFuture();
+            return Futures.immediateFuture(RpcResultBuilder
+                    .<O>failed()
+                    .withError(RpcError.ErrorType.APPLICATION, "", "Request quota exceeded")
+                    .build());
         }
 
-        if (requestContext.getXid() == null) {
+        if (Objects.isNull(requestContext.getXid())) {
             getMessageSpy().spyMessage(requestContext.getClass(), MessageSpy.STATISTIC_GROUP.TO_SWITCH_RESERVATION_REJECTED);
             return RequestContextUtil.closeRequestContextWithRpcError(requestContext, "Outbound queue wasn't able to reserve XID.");
         }
@@ -150,10 +159,4 @@ abstract class AbstractService<I, O> {
 
         return requestContext.getFuture();
     }
-
-    protected static <T> ListenableFuture<RpcResult<T>> failedFuture() {
-        final RpcResult<T> rpcResult = RpcResultBuilder.<T>failed()
-            .withError(RpcError.ErrorType.APPLICATION, "", "Request quota exceeded").build();
-        return Futures.immediateFuture(rpcResult);
-    }
 }
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractSilentErrorService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractSilentErrorService.java
new file mode 100644 (file)
index 0000000..6ef58b7
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.function.Function;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+public abstract class AbstractSilentErrorService<I, O extends DataObject>
+        extends AbstractSimpleService<I, O> {
+
+    protected AbstractSilentErrorService(RequestContextStack requestContextStack, DeviceContext deviceContext, Class<O> clazz) {
+        super(requestContextStack, deviceContext, clazz);
+    }
+
+    @Override
+    public ListenableFuture<RpcResult<O>> handleServiceCall(@Nonnull I input,
+                                                            @Nullable final Function<OfHeader, Boolean> isComplete) {
+        return Futures.withFallback(
+                super.handleServiceCall(input, isComplete),
+                t -> RpcResultBuilder.<O>failed().buildFuture());
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractTableMultipartService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/AbstractTableMultipartService.java
new file mode 100644 (file)
index 0000000..b712cbe
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.Future;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestTableFeaturesCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.table.features._case.MultipartRequestTableFeaturesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.table.features._case.multipart.request.table.features.TableFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.TableUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+public abstract class AbstractTableMultipartService<T extends OfHeader> extends AbstractMultipartService<UpdateTableInput, T> {
+
+    private final ConvertorExecutor convertorExecutor;
+    private final MultipartWriterProvider multipartWriterProvider;
+    private final VersionConvertorData data;
+
+    protected AbstractTableMultipartService(final RequestContextStack requestContextStack,
+                                            final DeviceContext deviceContext,
+                                            final ConvertorExecutor convertorExecutor,
+                                            final MultipartWriterProvider multipartWriterProvider) {
+        super(requestContextStack, deviceContext);
+        this.convertorExecutor = convertorExecutor;
+        this.multipartWriterProvider = multipartWriterProvider;
+        data = new VersionConvertorData(getVersion());
+    }
+
+    @Override
+    protected OfHeader buildRequest(final Xid xid, final UpdateTableInput input) throws ServiceException {
+        final Optional<List<TableFeatures>> tableFeatures = getConvertorExecutor().convert(input.getUpdatedTable(), data);
+
+        return RequestInputUtils.createMultipartHeader(MultipartType.OFPMPTABLEFEATURES, xid.getValue(), getVersion())
+            .setMultipartRequestBody(new MultipartRequestTableFeaturesCaseBuilder()
+                .setMultipartRequestTableFeatures(new MultipartRequestTableFeaturesBuilder()
+                    .setTableFeatures(tableFeatures
+                        .orElseGet(Collections::emptyList))
+                    .build())
+                .build())
+            .build();
+    }
+
+    /**
+     * Get convertor executor
+     * @return convertor executor
+     */
+    protected ConvertorExecutor getConvertorExecutor() {
+        return convertorExecutor;
+    }
+
+    /**
+     * Get data
+     * @return data
+     */
+    protected VersionConvertorData getData() {
+        return data;
+    }
+
+    /**
+     * Stores table features to operational datastore
+     */
+    protected void storeStatistics(List<org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures> result) {
+        multipartWriterProvider
+            .lookup(MultipartType.OFPMPTABLEFEATURES)
+            .ifPresent(writer -> {
+                writer.write(
+                    new TableUpdatedBuilder()
+                        .setTableFeatures(result)
+                        .build(),
+                    false);
+
+                getTxFacade().submitTransaction();
+            });
+    }
+
+    /**
+     * Process experimenter input and result experimenter output
+     * @param input experimenter input
+     * @return experimenter output
+     */
+    public abstract Future<RpcResult<UpdateTableOutput>> handleAndReply(UpdateTableInput input);
+
+}
index 15ca0d1b9dfb26082e73831437e53d26ac75714f..a24fcda674f2f2d85fa05413e170ce9269b66542 100644 (file)
@@ -12,9 +12,8 @@ import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 
-public abstract class AbstractVoidService<T extends DataObject> extends AbstractService<T, Void> {
+public abstract class AbstractVoidService<T> extends AbstractService<T, Void> {
     protected AbstractVoidService(final RequestContextStack requestContextStack, final DeviceContext deviceContext) {
         super(requestContextStack, deviceContext);
     }
index 0bf4a5bba7232cd00041aa2ae7ade503f1e8e98e..b0334fb0f64067122c10bf81a75ce111b43eb9ed 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.openflowplugin.impl.services;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
@@ -26,4 +27,4 @@ public class EchoService extends AbstractSimpleService<EchoInputBuilder, EchoOut
                 .setVersion(getVersion())
                 .build();
     }
-}
\ No newline at end of file
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/MultipartRequestOnTheFlyCallback.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/MultipartRequestOnTheFlyCallback.java
deleted file mode 100644 (file)
index 9b1c0e7..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.openflowplugin.impl.services;
-
-import com.google.common.base.Function;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.Collections;
-import java.util.List;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
-import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
-import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
-import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
-import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
-import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
-import org.opendaylight.openflowplugin.impl.statistics.SinglePurposeMultipartReplyTranslator;
-import org.opendaylight.openflowplugin.impl.statistics.StatisticsGatheringUtils;
-import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.EventsTimeCounter;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdate;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-final class MultipartRequestOnTheFlyCallback extends AbstractRequestCallback<List<MultipartReply>> {
-    private static final Logger LOG = LoggerFactory.getLogger(MultipartRequestOnTheFlyCallback.class);
-    private final SinglePurposeMultipartReplyTranslator multipartReplyTranslator;
-    private final DeviceInfo deviceInfo;
-    private final DeviceFlowRegistry registry;
-    private boolean virgin = true;
-    private boolean finished = false;
-    private final EventIdentifier doneEventIdentifier;
-    private final TxFacade txFacade;
-
-
-    public MultipartRequestOnTheFlyCallback(final RequestContext<List<MultipartReply>> context,
-                                            final Class<?> requestType,
-                                            final MessageSpy messageSpy,
-                                            final EventIdentifier eventIdentifier,
-                                            final DeviceInfo deviceInfo,
-                                            final DeviceFlowRegistry registry,
-                                            final TxFacade txFacade,
-                                            final ConvertorExecutor convertorExecutor) {
-        super(context, requestType, messageSpy, eventIdentifier);
-
-        this.deviceInfo = deviceInfo;
-        this.registry = registry;
-        this.txFacade = txFacade;
-
-        multipartReplyTranslator = new SinglePurposeMultipartReplyTranslator(convertorExecutor);
-
-        //TODO: this is focused on flow stats only - need more general approach if used for more than flow stats
-        doneEventIdentifier = new EventIdentifier(MultipartType.OFPMPFLOW.name(), deviceInfo.getNodeId().toString());
-    }
-
-    public EventIdentifier getDoneEventIdentifier() {
-        return doneEventIdentifier;
-    }
-
-    @Override
-    public void onSuccess(final OfHeader result) {
-        if (result == null) {
-            LOG.info("Ofheader was null.");
-            if (!finished) {
-                endCollecting();
-                return;
-            }
-        } else if (finished) {
-            LOG.debug("Unexpected multipart response received: xid={}, {}", result.getXid(), result.getImplementedInterface());
-            return;
-        }
-
-        if (!(result instanceof MultipartReply)) {
-            LOG.info("Unexpected response type received {}.", result.getClass());
-            final RpcResultBuilder<List<MultipartReply>> rpcResultBuilder =
-                    RpcResultBuilder.<List<MultipartReply>>failed().withError(RpcError.ErrorType.APPLICATION,
-                            String.format("Unexpected response type received %s.", result.getClass()));
-            setResult(rpcResultBuilder.build());
-            endCollecting();
-        } else {
-            final MultipartReply multipartReply = (MultipartReply) result;
-
-            final MultipartReply singleReply = multipartReply;
-            final List<? extends DataObject> multipartDataList = multipartReplyTranslator.translate(
-                    deviceInfo.getDatapathId(), deviceInfo.getVersion(), singleReply);
-            final Iterable<? extends DataObject> allMultipartData = multipartDataList;
-
-            //TODO: following part is focused on flow stats only - need more general approach if used for more than flow stats
-            ListenableFuture<Void> future;
-            if (virgin) {
-                future = StatisticsGatheringUtils.deleteAllKnownFlows(deviceInfo, registry, txFacade);
-                virgin = false;
-            } else {
-                future = Futures.immediateFuture(null);
-            }
-
-            Futures.transform(future, new Function<Void, Void>() {
-
-                @Override
-                public Void apply(final Void input) {
-                    StatisticsGatheringUtils.writeFlowStatistics((Iterable<FlowsStatisticsUpdate>) allMultipartData,
-                            deviceInfo, registry, txFacade);
-
-                    if (!multipartReply.getFlags().isOFPMPFREQMORE()) {
-                        endCollecting();
-                    }
-                    return input;
-                }
-            });
-        }
-    }
-
-    private void endCollecting() {
-        EventsTimeCounter.markEnd(getDoneEventIdentifier());
-        EventsTimeCounter.markEnd(getEventIdentifier());
-        final RpcResult<List<MultipartReply>> rpcResult = RpcResultBuilder.success(Collections.<MultipartReply>emptyList()).build();
-        spyMessage(MessageSpy.STATISTIC_GROUP.FROM_SWITCH_TRANSLATE_OUT_SUCCESS);
-        txFacade.submitTransaction();
-        setResult(rpcResult);
-        finished = true;
-    }
-}
index c2653bf20803c14d2e6f491fd96608019f79a07a..446f8372a8da98e4e78bc9525b8de6430ec12870 100644 (file)
@@ -19,6 +19,7 @@ import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.impl.role.RoleChangeException;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ControllerRole;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
@@ -41,7 +42,7 @@ public class RoleService extends AbstractSimpleService<RoleRequestInputBuilder,
 
     private final DeviceContext deviceContext;
 
-    protected RoleService(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final Class<RoleRequestOutput> clazz) {
+    public RoleService(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final Class<RoleRequestOutput> clazz) {
         super(requestContextStack, deviceContext, clazz);
         this.deviceContext = deviceContext;
     }
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalTableServiceImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalTableServiceImpl.java
deleted file mode 100644 (file)
index ef757c9..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/**
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.openflowplugin.impl.services;
-
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-import java.util.concurrent.Future;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
-import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
-import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.MultipartReplyBody;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyTableFeaturesCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table.features._case.MultipartReplyTableFeatures;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestTableFeaturesCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.table.features._case.MultipartRequestTableFeaturesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.table.features._case.multipart.request.table.features.TableFeatures;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeaturesKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import org.slf4j.Logger;
-
-public final class SalTableServiceImpl extends AbstractMultipartService<UpdateTableInput> implements SalTableService {
-    private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(SalTableServiceImpl.class);
-    private final TxFacade txFacade;
-    private final ConvertorExecutor convertorExecutor;
-    private final VersionConvertorData data;
-
-    public SalTableServiceImpl(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final ConvertorExecutor convertorExecutor) {
-        super(requestContextStack, deviceContext);
-        this.txFacade = deviceContext;
-        this.convertorExecutor = convertorExecutor;
-        data = new VersionConvertorData(getVersion());
-    }
-
-    @Override
-    public Future<RpcResult<UpdateTableOutput>> updateTable(final UpdateTableInput input) {
-        final ListenableFuture<RpcResult<List<MultipartReply>>> multipartFuture = handleServiceCall(input);
-        final SettableFuture<RpcResult<UpdateTableOutput>> finalFuture = SettableFuture.create();
-
-        class CallBackImpl implements FutureCallback<RpcResult<List<MultipartReply>>> {
-            @Override
-            public void onSuccess(final RpcResult<List<MultipartReply>> result) {
-
-                if (result.isSuccessful()) {
-                    final List<MultipartReply> multipartReplies = result.getResult();
-                    if (multipartReplies.isEmpty()) {
-                        LOG.debug("Multipart reply to table features request shouldn't be empty list.");
-                        finalFuture.set(RpcResultBuilder.<UpdateTableOutput>failed()
-                                .withError(ErrorType.RPC, "Multipart reply list is empty.").build());
-                    } else {
-                        final Long xid = multipartReplies.get(0).getXid();
-                        LOG.debug(
-                                "OnSuccess, rpc result successful, multipart response for rpc update-table with xid {} obtained.",
-                                xid);
-                        final UpdateTableOutputBuilder updateTableOutputBuilder = new UpdateTableOutputBuilder();
-                        updateTableOutputBuilder.setTransactionId(new TransactionId(BigInteger.valueOf(xid)));
-                        finalFuture.set(RpcResultBuilder.success(updateTableOutputBuilder.build()).build());
-                        try {
-                            writeResponseToOperationalDatastore(multipartReplies);
-                        } catch (Exception e) {
-                            LOG.warn("Not able to write to operational datastore: {}", e.getMessage());
-                        }
-                    }
-                } else {
-                    LOG.debug("OnSuccess, rpc result unsuccessful, multipart response for rpc update-table was unsuccessful.");
-                    finalFuture.set(RpcResultBuilder.<UpdateTableOutput>failed().withRpcErrors(result.getErrors())
-                            .build());
-                }
-            }
-
-            @Override
-            public void onFailure(final Throwable t) {
-                LOG.error("Failure multipart response for table features request. Exception: {}", t);
-                finalFuture.set(RpcResultBuilder.<UpdateTableOutput>failed()
-                        .withError(ErrorType.RPC, "Future error", t).build());
-            }
-        }
-
-        Futures.addCallback(multipartFuture, new CallBackImpl());
-
-        return finalFuture;
-    }
-
-    /**
-     * @param multipartReplies
-     */
-    private void writeResponseToOperationalDatastore(final List<MultipartReply> multipartReplies) throws Exception {
-
-        final List<org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures> salTableFeatures = convertToSalTableFeatures(multipartReplies);
-
-        final InstanceIdentifier<FlowCapableNode> flowCapableNodeII = InstanceIdentifier.create(Nodes.class)
-                .child(Node.class, new NodeKey(getDeviceInfo().getNodeId())).augmentation(FlowCapableNode.class);
-        for (final org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures tableFeatureData : salTableFeatures) {
-            final Short tableId = tableFeatureData.getTableId();
-            final KeyedInstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures, TableFeaturesKey> tableFeaturesII = flowCapableNodeII
-                    .child(org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures.class,
-                            new TableFeaturesKey(tableId));
-            txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, tableFeaturesII,
-                    tableFeatureData);
-        }
-
-        txFacade.submitTransaction();
-    }
-
-    protected List<org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures> convertToSalTableFeatures(
-            final List<MultipartReply> multipartReplies) {
-        final List<org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures> salTableFeaturesAll = new ArrayList<>();
-        for (final MultipartReply multipartReply : multipartReplies) {
-            if (multipartReply.getType().equals(MultipartType.OFPMPTABLEFEATURES)) {
-                final MultipartReplyBody multipartReplyBody = multipartReply.getMultipartReplyBody();
-                if (multipartReplyBody instanceof MultipartReplyTableFeaturesCase) {
-                    final MultipartReplyTableFeaturesCase tableFeaturesCase = ((MultipartReplyTableFeaturesCase) multipartReplyBody);
-                    final MultipartReplyTableFeatures salTableFeatures = tableFeaturesCase
-                            .getMultipartReplyTableFeatures();
-
-                    final Optional<List<org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures>> salTableFeaturesPartial =
-                            convertorExecutor.convert(salTableFeatures, data);
-
-                    if (salTableFeaturesPartial.isPresent()) {
-                        salTableFeaturesAll.addAll(salTableFeaturesPartial.get());
-                    }
-
-                    LOG.debug("TableFeature {} for xid {}.", salTableFeatures, multipartReply.getXid());
-                }
-            }
-        }
-        return salTableFeaturesAll;
-    }
-
-    private MultipartRequestInputBuilder createMultipartHeader(final MultipartType multipart, final Long xid) {
-        final MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
-        mprInput.setType(multipart);
-        mprInput.setVersion(getVersion());
-        mprInput.setXid(xid);
-        mprInput.setFlags(new MultipartRequestFlags(false));
-        return mprInput;
-    }
-
-    @Override
-    protected OfHeader buildRequest(final Xid xid, final UpdateTableInput input) throws ServiceException {
-        final MultipartRequestTableFeaturesCaseBuilder caseBuilder = new MultipartRequestTableFeaturesCaseBuilder();
-        final MultipartRequestTableFeaturesBuilder requestBuilder = new MultipartRequestTableFeaturesBuilder();
-
-        final Optional<List<TableFeatures>> ofTableFeatureList = convertorExecutor.convert(input.getUpdatedTable(), data);
-        requestBuilder.setTableFeatures(ofTableFeatureList.orElse(Collections.emptyList()));
-        caseBuilder.setMultipartRequestTableFeatures(requestBuilder.build());
-
-        // Set request body to main multipart request
-        final MultipartRequestInputBuilder mprInput = createMultipartHeader(MultipartType.OFPMPTABLEFEATURES,
-            xid.getValue());
-        mprInput.setMultipartRequestBody(caseBuilder.build());
-
-        return mprInput.build();
-    }
-}
index 034d2fa3bfe7f0e74b65e2fe89f64a09d83eda3f..3f94add0070f014160fe4fd363b335f628b17490 100644 (file)
@@ -17,16 +17,16 @@ import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-final class SimpleRequestCallback<T extends DataObject> extends AbstractRequestCallback<T> {
+public final class SimpleRequestCallback<T extends DataObject> extends AbstractRequestCallback<T> {
     private static final Logger LOG = LoggerFactory.getLogger(SimpleRequestCallback.class);
     private final Class<T> clazz;
 
     private SimpleRequestCallback(final RequestContext<T> context, final Class<?> requestType, final MessageSpy spy, final Class<T> clazz) {
-        super(context, requestType, spy);
+        super(context, requestType, spy, null);
         this.clazz = Preconditions.checkNotNull(clazz);
     }
 
-    static <T extends DataObject> FutureCallback<OfHeader> create(final RequestContext<T> context, final Class<?> requestType, final MessageSpy spy, final Class<T> clazz) {
+    public static <T extends DataObject> FutureCallback<OfHeader> create(final RequestContext<T> context, final Class<?> requestType, final MessageSpy spy, final Class<T> clazz) {
         return new SimpleRequestCallback<>(context, requestType, spy, clazz);
     }
 
index 5860a183f891bae56cdec70700b9aa9bc23901a7..97109ad40197702e82002374e777956e7447b473 100644 (file)
@@ -14,11 +14,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
-final class VoidRequestCallback extends AbstractRequestCallback<Void> {
+public final class VoidRequestCallback extends AbstractRequestCallback<Void> {
     private static final RpcResult<Void> SUCCESS = RpcResultBuilder.<Void>success().build();
 
-    VoidRequestCallback(final RequestContext<Void> context, final Class<?> requestType, final MessageSpy spy) {
-        super(context, requestType, spy);
+    public VoidRequestCallback(final RequestContext<Void> context, final Class<?> requestType, final MessageSpy spy) {
+        super(context, requestType, spy, null);
     }
 
     @Override
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerAggregateFlowMultipartService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerAggregateFlowMultipartService.java
new file mode 100644 (file)
index 0000000..ee10af7
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services.multilayer;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import java.util.List;
+import java.util.concurrent.Future;
+import java.util.stream.Collectors;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
+import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
+import org.opendaylight.openflowplugin.impl.services.AbstractAggregateFlowMultipartService;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.get.aggregate.flow.statistics.from.flow.table._for.given.match.output.AggregatedFlowStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyAggregateCase;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+public class MultiLayerAggregateFlowMultipartService extends AbstractAggregateFlowMultipartService<MultipartReply> {
+
+    private final TranslatorLibrary translatorLibrary;
+
+    public MultiLayerAggregateFlowMultipartService(final RequestContextStack requestContextStack,
+                                                   final DeviceContext deviceContext,
+                                                   final ConvertorExecutor convertorExecutor,
+                                                   final TranslatorLibrary translatorLibrary) {
+        super(requestContextStack, deviceContext, convertorExecutor);
+        this.translatorLibrary = translatorLibrary;
+    }
+
+    @Override
+    public Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>> handleAndReply(final GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput input) {
+        return Futures.transform(handleServiceCall(input),
+            (Function<RpcResult<List<MultipartReply>>, RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>>) result -> {
+                if (Preconditions.checkNotNull(result).isSuccessful()) {
+                    final MessageTranslator<MultipartReply, AggregatedFlowStatistics> messageTranslator = translatorLibrary
+                        .lookupTranslator(new TranslatorKey(getVersion(), MultipartReplyAggregateCase.class.getName()));
+
+                    return RpcResultBuilder
+                        .success(new GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder()
+                            .setAggregatedFlowStatistics(result
+                                .getResult()
+                                .stream()
+                                .map(multipartReply -> messageTranslator
+                                    .translate(multipartReply, getDeviceInfo(), null))
+                                .collect(Collectors.toList())))
+                        .build();
+                }
+
+                return RpcResultBuilder
+                    .<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>failed()
+                    .withRpcErrors(result.getErrors())
+                    .build();
+            });
+    }
+
+}
@@ -1,67 +1,55 @@
 /*
- * Copyright (c) 2016 Pantheon Technologies s.r.o. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.multilayer;
 
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Objects;
 import java.util.concurrent.Future;
-
 import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
-import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.extension.api.ConvertorMessageFromOFJava;
-import org.opendaylight.openflowplugin.extension.api.ConvertorMessageToOFJava;
-import org.opendaylight.openflowplugin.extension.api.TypeVersionKey;
 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
 import org.opendaylight.openflowplugin.extension.api.exception.ConversionException;
-import org.opendaylight.openflowplugin.extension.api.exception.ConverterNotFoundException;
 import org.opendaylight.openflowplugin.extension.api.path.MessagePath;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SalExperimenterMpMessageService;
+import org.opendaylight.openflowplugin.impl.services.AbstractExperimenterMultipartService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestOutputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.send.experimenter.mp.request.output.ExperimenterCoreMessageItem;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.send.experimenter.mp.request.output.ExperimenterCoreMessageItemBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.experimenter.core.ExperimenterDataOfChoice;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyExperimenterCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.experimenter._case.MultipartReplyExperimenter;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestExperimenterCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.experimenter._case.MultipartRequestExperimenterBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.experimenter.types.rev151020.experimenter.core.message.ExperimenterMessageOfChoice;
 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
+public class MultiLayerExperimenterMultipartService extends AbstractExperimenterMultipartService<MultipartReply> {
 
-public class SalExperimenterMpMessageServiceImpl extends AbstractMultipartService<SendExperimenterMpRequestInput> implements SalExperimenterMpMessageService {
-    private final ExtensionConverterProvider extensionConverterProvider;
-    private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(SalExperimenterMpMessageServiceImpl.class);
+    private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(MultiLayerExperimenterMultipartService.class);
 
-    public SalExperimenterMpMessageServiceImpl(final RequestContextStack requestContextStack,
-                                                  final DeviceContext deviceContext,
-                                                  final ExtensionConverterProvider extensionConverterProvider) {
-        super(requestContextStack, deviceContext);
-        this.extensionConverterProvider = extensionConverterProvider;
+    public MultiLayerExperimenterMultipartService(RequestContextStack requestContextStack, DeviceContext deviceContext,
+                                                  ExtensionConverterProvider extensionConverterProvider) {
+        super(requestContextStack, deviceContext, extensionConverterProvider);
     }
 
     @Override
-    public Future<RpcResult<SendExperimenterMpRequestOutput>> sendExperimenterMpRequest(SendExperimenterMpRequestInput input) {
+    @SuppressWarnings("unchecked")
+    public Future<RpcResult<SendExperimenterMpRequestOutput>> handleAndReply(SendExperimenterMpRequestInput input) {
         final ListenableFuture<RpcResult<List<MultipartReply>>> multipartFuture = handleServiceCall(input);
         final SettableFuture<RpcResult<SendExperimenterMpRequestOutput>> finalFuture = SettableFuture.create();
 
@@ -87,7 +75,7 @@ public class SalExperimenterMpMessageServiceImpl extends AbstractMultipartServic
                                     getVersion(),
                                     (Class<? extends ExperimenterDataOfChoice>) vendorData.getImplementedInterface());
                             final ConvertorMessageFromOFJava<ExperimenterDataOfChoice, MessagePath> messageConverter =
-                                    extensionConverterProvider.getMessageConverter(key);
+                                    getExtensionConverterProvider().getMessageConverter(key);
                             if (messageConverter == null) {
                                 LOG.warn("Custom converter for {}[OF:{}] not found",
                                         vendorData.getImplementedInterface(),
@@ -127,34 +115,4 @@ public class SalExperimenterMpMessageServiceImpl extends AbstractMultipartServic
         return finalFuture;
     }
 
-    @Override
-    @SuppressWarnings("unchecked")
-    protected OfHeader buildRequest(Xid xid, SendExperimenterMpRequestInput input) throws ServiceException {
-        final TypeVersionKey key = new TypeVersionKey(
-                input.getExperimenterMessageOfChoice().getImplementedInterface(),
-                getVersion());
-
-        final ConvertorMessageToOFJava<ExperimenterMessageOfChoice, ExperimenterDataOfChoice> messageConverter =
-                extensionConverterProvider.getMessageConverter(key);
-
-        if (Objects.isNull(messageConverter)) {
-            throw new ServiceException(new ConverterNotFoundException(key.toString()));
-        }
-
-        try {
-            return RequestInputUtils
-                .createMultipartHeader(MultipartType.OFPMPEXPERIMENTER, xid.getValue(), getVersion())
-                .setMultipartRequestBody(new MultipartRequestExperimenterCaseBuilder()
-                        .setMultipartRequestExperimenter(new MultipartRequestExperimenterBuilder()
-                                .setExperimenter(messageConverter.getExperimenterId())
-                                .setExpType(messageConverter.getType())
-                                .setExperimenterDataOfChoice(messageConverter
-                                        .convert(input.getExperimenterMessageOfChoice()))
-                                .build())
-                        .build())
-                .build();
-        } catch (final ConversionException e) {
-            throw new ServiceException(e);
-        }
-    }
 }
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerFlowMultipartRequestOnTheFlyCallback.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerFlowMultipartRequestOnTheFlyCallback.java
new file mode 100644 (file)
index 0000000..982bb62
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services.multilayer;
+
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.List;
+import java.util.Optional;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
+import org.opendaylight.openflowplugin.impl.common.MultipartReplyTranslatorUtil;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.services.AbstractMultipartRequestOnTheFlyCallback;
+import org.opendaylight.openflowplugin.impl.statistics.StatisticsGatheringUtils;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+
+public class MultiLayerFlowMultipartRequestOnTheFlyCallback<T extends OfHeader> extends AbstractMultipartRequestOnTheFlyCallback<T> {
+
+    private final ConvertorExecutor convertorExecutor;
+    private final DeviceInfo deviceInfo;
+    private boolean virgin = true;
+
+    public MultiLayerFlowMultipartRequestOnTheFlyCallback(final RequestContext<List<T>> context,
+                                                          final Class<?> requestType,
+                                                          final DeviceContext deviceContext,
+                                                          final EventIdentifier eventIdentifier,
+                                                          final MultipartWriterProvider statisticsWriterProvider,
+                                                          final ConvertorExecutor convertorExecutor) {
+        super(context, requestType, deviceContext, eventIdentifier, statisticsWriterProvider);
+        this.convertorExecutor = convertorExecutor;
+        deviceInfo = deviceContext.getDeviceInfo();
+    }
+
+    @Override
+    protected boolean isMultipart(OfHeader result) {
+        return result instanceof MultipartReply
+            && MultipartReply.class.cast(result).getType().equals(getMultipartType());
+    }
+
+    @Override
+    protected boolean isReqMore(T result) {
+        return MultipartReply.class.cast(result).getFlags().isOFPMPFREQMORE();
+    }
+
+    @Override
+    protected MultipartType getMultipartType() {
+        return MultipartType.OFPMPFLOW;
+    }
+
+    @Override
+    protected ListenableFuture<Optional<? extends MultipartReplyBody>> processStatistics(T result) {
+        final ListenableFuture<Optional<? extends MultipartReplyBody>> future = Futures.transform(
+            StatisticsGatheringUtils.deleteAllKnownFlows(
+                getTxFacade(),
+                deviceInfo
+                    .getNodeInstanceIdentifier()
+                    .augmentation(FlowCapableNode.class),
+                !virgin),
+            (Function<Void, Optional<? extends MultipartReplyBody>>) input -> MultipartReplyTranslatorUtil
+                .translate(result, deviceInfo, convertorExecutor, null));
+
+        if (virgin) {
+            virgin = false;
+        }
+
+        return future;
+    }
+
+}
similarity index 83%
rename from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/FlowService.java
rename to openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerFlowService.java
index e865d903309eb989b4cccb051cab52eacd481c2e..c26638fae92fc88802ea5c6c99f704c9ca74c44f 100644 (file)
@@ -1,11 +1,11 @@
-/**
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.multilayer;
 
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
@@ -19,6 +19,8 @@ import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.impl.services.AbstractSimpleService;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionDatapathIdConvertorData;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
@@ -29,12 +31,12 @@ import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
-final class FlowService<O extends DataObject> extends AbstractSimpleService<FlowModInputBuilder, O> {
+public final class MultiLayerFlowService<O extends DataObject> extends AbstractSimpleService<FlowModInputBuilder, O> {
 
     private final ConvertorExecutor convertorExecutor;
     private final VersionDatapathIdConvertorData data;
 
-    protected FlowService(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final Class<O> clazz, final ConvertorExecutor convertorExecutor) {
+    public MultiLayerFlowService(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final Class<O> clazz, final ConvertorExecutor convertorExecutor) {
         super(requestContextStack, deviceContext, clazz);
         this.convertorExecutor = convertorExecutor;
         data = new VersionDatapathIdConvertorData(getVersion());
@@ -47,12 +49,12 @@ final class FlowService<O extends DataObject> extends AbstractSimpleService<Flow
         return input.build();
     }
 
-    List<FlowModInputBuilder> toFlowModInputs(final Flow input) {
+    public List<FlowModInputBuilder> toFlowModInputs(final Flow input) {
         final Optional<List<FlowModInputBuilder>> flowModInputBuilders = convertorExecutor.convert(input, data);
         return flowModInputBuilders.orElse(Collections.emptyList());
     }
 
-    ListenableFuture<RpcResult<O>> processFlowModInputBuilders(final List<FlowModInputBuilder> ofFlowModInputs) {
+    public ListenableFuture<RpcResult<O>> processFlowModInputBuilders(final List<FlowModInputBuilder> ofFlowModInputs) {
         final List<ListenableFuture<RpcResult<O>>> partialFutures = new ArrayList<>(ofFlowModInputs.size());
 
         for (final FlowModInputBuilder flowModInputBuilder : ofFlowModInputs) {
similarity index 75%
rename from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/GroupService.java
rename to openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerGroupService.java
index aa1ebe15ccf02e0fcb808fe3c9321f63f68f350b..c2a3355e8809908d3d2a43b28c0b617dfde4180b 100644 (file)
@@ -1,16 +1,18 @@
-/**
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.multilayer;
 
 import java.util.Optional;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.impl.services.AbstractSimpleService;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.GroupConvertor;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionDatapathIdConvertorData;
@@ -19,11 +21,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 
-final class GroupService<I extends Group, O extends DataObject> extends AbstractSimpleService<I, O> {
+public final class MultiLayerGroupService<I extends Group, O extends DataObject> extends AbstractSimpleService<I, O> {
     private final ConvertorExecutor convertorExecutor;
     private final VersionDatapathIdConvertorData data;
 
-    GroupService(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final Class<O> clazz, final ConvertorExecutor convertorExecutor) {
+    public MultiLayerGroupService(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final Class<O> clazz, final ConvertorExecutor convertorExecutor) {
         super(requestContextStack, deviceContext, clazz);
         this.convertorExecutor = convertorExecutor;
         data = new VersionDatapathIdConvertorData(getVersion());
similarity index 74%
rename from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/MeterService.java
rename to openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerMeterService.java
index 7b6fc8e69b7f123fbdf8cec2717638cda287f5b8..9ef9d0b9b1393df71abd4e17e51d11145e933460 100644 (file)
@@ -1,16 +1,18 @@
-/**
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.multilayer;
 
 import java.util.Optional;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.impl.services.AbstractSimpleService;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.MeterConvertor;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData;
@@ -19,12 +21,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 
-final class MeterService<I extends Meter, O extends DataObject> extends AbstractSimpleService<I, O> {
+public final class MultiLayerMeterService<I extends Meter, O extends DataObject> extends AbstractSimpleService<I, O> {
 
     private final ConvertorExecutor convertorExecutor;
     private final VersionConvertorData data;
 
-    MeterService(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final Class<O> clazz, final ConvertorExecutor convertorExecutor) {
+    public MultiLayerMeterService(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final Class<O> clazz, final ConvertorExecutor convertorExecutor) {
         super(requestContextStack, deviceContext, clazz);
         this.convertorExecutor = convertorExecutor;
         data = new VersionConvertorData(getVersion());
@@ -39,4 +41,4 @@ final class MeterService<I extends Meter, O extends DataObject> extends Abstract
         meterModInputBuilder.setXid(xid.getValue());
         return meterModInputBuilder.build();
     }
-}
\ No newline at end of file
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerMultipartCollectorService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerMultipartCollectorService.java
new file mode 100644 (file)
index 0000000..f41e7f9
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services.multilayer;
+
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.services.AbstractMultipartCollectorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+
+public class MultiLayerMultipartCollectorService extends AbstractMultipartCollectorService<MultipartReply> {
+
+    public MultiLayerMultipartCollectorService(final RequestContextStack requestContextStack, final DeviceContext deviceContext) {
+        super(requestContextStack, deviceContext);
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerMultipartRequestCallback.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerMultipartRequestCallback.java
new file mode 100644 (file)
index 0000000..d8bf0b1
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services.multilayer;
+
+import java.util.List;
+import java.util.Objects;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
+import org.opendaylight.openflowplugin.impl.services.AbstractMultipartRequestCallback;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+
+public class MultiLayerMultipartRequestCallback<T extends OfHeader> extends AbstractMultipartRequestCallback<T> {
+
+    public MultiLayerMultipartRequestCallback(RequestContext<List<T>> context, Class<?> requestType, DeviceContext deviceContext, EventIdentifier eventIdentifier) {
+        super(context, requestType, deviceContext, eventIdentifier);
+    }
+
+    @Override
+    protected boolean isMultipart(OfHeader result) {
+        return result instanceof MultipartReply;
+    }
+
+    @Override
+    protected boolean isReqMore(T result) {
+        final MultipartRequestFlags flags = MultipartReply.class.cast(result).getFlags();
+        return Objects.nonNull(flags) && flags.isOFPMPFREQMORE();
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerTableMultipartService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/multilayer/MultiLayerTableMultipartService.java
new file mode 100644 (file)
index 0000000..1310431
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services.multilayer;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.Future;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.services.AbstractTableMultipartService;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.MultipartReplyBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyTableFeaturesCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table.features._case.MultipartReplyTableFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MultiLayerTableMultipartService extends AbstractTableMultipartService<MultipartReply> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(MultiLayerTableMultipartService.class);
+
+    public MultiLayerTableMultipartService(RequestContextStack requestContextStack,
+                                           DeviceContext deviceContext,
+                                           ConvertorExecutor convertorExecutor,
+                                           MultipartWriterProvider multipartWriterProvider) {
+        super(requestContextStack, deviceContext, convertorExecutor, multipartWriterProvider);
+    }
+
+    @Override
+    public Future<RpcResult<UpdateTableOutput>> handleAndReply(UpdateTableInput input) {
+        final ListenableFuture<RpcResult<List<MultipartReply>>> multipartFuture = handleServiceCall(input);
+        final SettableFuture<RpcResult<UpdateTableOutput>> finalFuture = SettableFuture.create();
+
+        class CallBackImpl implements FutureCallback<RpcResult<List<MultipartReply>>> {
+            @Override
+            public void onSuccess(final RpcResult<List<MultipartReply>> result) {
+
+                if (result.isSuccessful()) {
+                    final List<MultipartReply> multipartReplies = result.getResult();
+                    if (multipartReplies.isEmpty()) {
+                        LOG.debug("Multipart reply to table features request shouldn't be empty list.");
+                        finalFuture.set(RpcResultBuilder.<UpdateTableOutput>failed()
+                            .withError(ErrorType.RPC, "Multipart reply list is empty.").build());
+                    } else {
+                        final Long xid = multipartReplies.get(0).getXid();
+                        LOG.debug(
+                            "OnSuccess, rpc result successful, multipart response for rpc update-table with xid {} obtained.",
+                            xid);
+                        final UpdateTableOutputBuilder updateTableOutputBuilder = new UpdateTableOutputBuilder();
+                        updateTableOutputBuilder.setTransactionId(new TransactionId(BigInteger.valueOf(xid)));
+                        finalFuture.set(RpcResultBuilder.success(updateTableOutputBuilder.build()).build());
+                        try {
+                            storeStatistics(convertToSalTableFeatures(multipartReplies));
+                        } catch (Exception e) {
+                            LOG.warn("Not able to write to operational datastore: {}", e.getMessage());
+                        }
+                    }
+                } else {
+                    LOG.debug("OnSuccess, rpc result unsuccessful, multipart response for rpc update-table was unsuccessful.");
+                    finalFuture.set(RpcResultBuilder.<UpdateTableOutput>failed().withRpcErrors(result.getErrors())
+                        .build());
+                }
+            }
+
+            @Override
+            public void onFailure(final Throwable t) {
+                LOG.error("Failure multipart response for table features request. Exception: {}", t);
+                finalFuture.set(RpcResultBuilder.<UpdateTableOutput>failed()
+                    .withError(ErrorType.RPC, "Future error", t).build());
+            }
+        }
+
+        Futures.addCallback(multipartFuture, new CallBackImpl());
+
+        return finalFuture;
+    }
+
+    protected List<org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures> convertToSalTableFeatures(
+            final List<MultipartReply> multipartReplies) {
+        final List<org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures> salTableFeaturesAll = new ArrayList<>();
+        for (final MultipartReply multipartReply : multipartReplies) {
+            if (multipartReply.getType().equals(MultipartType.OFPMPTABLEFEATURES)) {
+                final MultipartReplyBody multipartReplyBody = multipartReply.getMultipartReplyBody();
+                if (multipartReplyBody instanceof MultipartReplyTableFeaturesCase) {
+                    final MultipartReplyTableFeaturesCase tableFeaturesCase = ((MultipartReplyTableFeaturesCase) multipartReplyBody);
+                    final MultipartReplyTableFeatures salTableFeatures = tableFeaturesCase
+                            .getMultipartReplyTableFeatures();
+
+                    final Optional<List<TableFeatures>> salTableFeaturesPartial =
+                            getConvertorExecutor().convert(salTableFeatures, getData());
+
+                    salTableFeaturesPartial.ifPresent(salTableFeaturesAll::addAll);
+
+                    LOG.debug("TableFeature {} for xid {}.", salTableFeatures, multipartReply.getXid());
+                }
+            }
+        }
+
+        return salTableFeaturesAll;
+    }
+}
@@ -5,12 +5,14 @@
  * 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import java.util.concurrent.Future;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.impl.services.AbstractVoidService;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.FlowCapableTransactionService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.SendBarrierInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInputBuilder;
similarity index 91%
rename from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/NodeConfigServiceImpl.java
rename to openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/NodeConfigServiceImpl.java
index 5a45f44336de19ddf9f3c92443a5bc7721c197bf..8e063fcbc7d4a2d22a5d2d07d6fea864de61c6a0 100644 (file)
@@ -5,12 +5,14 @@
  * 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import java.util.concurrent.Future;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.impl.services.AbstractSimpleService;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.module.config.rev141015.NodeConfigService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.module.config.rev141015.SetConfigInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.module.config.rev141015.SetConfigOutput;
@@ -5,13 +5,15 @@
  * 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import java.util.Optional;
 import java.util.concurrent.Future;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.impl.services.AbstractVoidService;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.PacketOutConvertor;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.PacketOutConvertorData;
similarity index 96%
rename from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalEchoServiceImpl.java
rename to openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalEchoServiceImpl.java
index 750a63a77269be2fb044e21f4921c6e5786d8728..b719ec417d79b78365aa43829a9d1b9e04900b3c 100644 (file)
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
@@ -15,6 +15,7 @@ import java.util.concurrent.Future;
 import javax.annotation.Nullable;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.services.EchoService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.echo.service.rev150305.SalEchoService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.echo.service.rev150305.SendEchoInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.echo.service.rev150305.SendEchoOutput;
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import java.util.concurrent.Future;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
@@ -16,6 +16,8 @@ import org.opendaylight.openflowplugin.extension.api.TypeVersionKey;
 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
 import org.opendaylight.openflowplugin.extension.api.exception.ConversionException;
 import org.opendaylight.openflowplugin.extension.api.exception.ConverterNotFoundException;
+import org.opendaylight.openflowplugin.impl.services.AbstractVoidService;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.message.service.rev151020.SalExperimenterMessageService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.message.service.rev151020.SendExperimenterInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterInputBuilder;
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalExperimenterMpMessageServiceImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalExperimenterMpMessageServiceImpl.java
new file mode 100755 (executable)
index 0000000..a0761fd
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services.sal;
+
+import java.util.concurrent.Future;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
+import org.opendaylight.openflowplugin.impl.services.multilayer.MultiLayerExperimenterMultipartService;
+import org.opendaylight.openflowplugin.impl.services.singlelayer.SingleLayerExperimenterMultipartService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SalExperimenterMpMessageService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestOutput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+public class SalExperimenterMpMessageServiceImpl implements SalExperimenterMpMessageService {
+    private final MultiLayerExperimenterMultipartService multiLayerService;
+    private final SingleLayerExperimenterMultipartService singleLayerService;
+
+    public SalExperimenterMpMessageServiceImpl(final RequestContextStack requestContextStack,
+                                               final DeviceContext deviceContext,
+                                               final ExtensionConverterProvider extensionConverterProvider) {
+        this.singleLayerService = new SingleLayerExperimenterMultipartService(requestContextStack, deviceContext,
+            extensionConverterProvider);
+        this.multiLayerService = new MultiLayerExperimenterMultipartService(requestContextStack, deviceContext,
+            extensionConverterProvider);
+    }
+
+    @Override
+    public Future<RpcResult<SendExperimenterMpRequestOutput>> sendExperimenterMpRequest(SendExperimenterMpRequestInput input) {
+        return singleLayerService.canUseSingleLayerSerialization()
+            ? singleLayerService.handleAndReply(input)
+            : multiLayerService.handleAndReply(input);
+    }
+
+}
similarity index 99%
rename from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalFlatBatchServiceImpl.java
rename to openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalFlatBatchServiceImpl.java
index 9945854e30d8ed31352361054a07ab3eeedf16a9..3eca9a73ac52210c11875d0e2ef12188efd2f715 100644 (file)
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
similarity index 91%
rename from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalFlowServiceImpl.java
rename to openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalFlowServiceImpl.java
index 50cd420b3610e79fe87e696740b730f64384d0d1..a164063badf5625e21a98ffe2a8aac25d23a6c5a 100644 (file)
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.util.concurrent.FutureCallback;
@@ -27,6 +27,8 @@ import org.opendaylight.openflowplugin.api.openflow.rpc.ItemLifeCycleSource;
 import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
 import org.opendaylight.openflowplugin.impl.registry.flow.FlowDescriptorFactory;
 import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
+import org.opendaylight.openflowplugin.impl.services.singlelayer.SingleLayerFlowService;
+import org.opendaylight.openflowplugin.impl.services.multilayer.MultiLayerFlowService;
 import org.opendaylight.openflowplugin.impl.util.ErrorUtil;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.openflowplugin.openflow.md.util.FlowCreatorUtil;
@@ -59,23 +61,23 @@ import org.slf4j.LoggerFactory;
 
 public class SalFlowServiceImpl implements SalFlowService, ItemLifeCycleSource {
     private static final Logger LOG = LoggerFactory.getLogger(SalFlowServiceImpl.class);
-    private final FlowService<UpdateFlowOutput> flowUpdate;
-    private final FlowService<AddFlowOutput> flowAdd;
-    private final FlowService<RemoveFlowOutput> flowRemove;
-    private final FlowMessageService<AddFlowOutput> flowAddMessage;
-    private final FlowMessageService<UpdateFlowOutput> flowUpdateMessage;
-    private final FlowMessageService<RemoveFlowOutput> flowRemoveMessage;
+    private final MultiLayerFlowService<UpdateFlowOutput> flowUpdate;
+    private final MultiLayerFlowService<AddFlowOutput> flowAdd;
+    private final MultiLayerFlowService<RemoveFlowOutput> flowRemove;
+    private final SingleLayerFlowService<AddFlowOutput> flowAddMessage;
+    private final SingleLayerFlowService<UpdateFlowOutput> flowUpdateMessage;
+    private final SingleLayerFlowService<RemoveFlowOutput> flowRemoveMessage;
     private final DeviceContext deviceContext;
     private ItemLifecycleListener itemLifecycleListener;
 
     public SalFlowServiceImpl(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final ConvertorExecutor convertorExecutor) {
         this.deviceContext = deviceContext;
-        flowRemove = new FlowService<>(requestContextStack, deviceContext, RemoveFlowOutput.class, convertorExecutor);
-        flowAdd = new FlowService<>(requestContextStack, deviceContext, AddFlowOutput.class, convertorExecutor);
-        flowUpdate = new FlowService<>(requestContextStack, deviceContext, UpdateFlowOutput.class, convertorExecutor);
-        flowAddMessage = new FlowMessageService<>(requestContextStack, deviceContext, AddFlowOutput.class);
-        flowUpdateMessage = new FlowMessageService<>(requestContextStack, deviceContext, UpdateFlowOutput.class);
-        flowRemoveMessage= new FlowMessageService<>(requestContextStack, deviceContext, RemoveFlowOutput.class);
+        flowRemove = new MultiLayerFlowService<>(requestContextStack, deviceContext, RemoveFlowOutput.class, convertorExecutor);
+        flowAdd = new MultiLayerFlowService<>(requestContextStack, deviceContext, AddFlowOutput.class, convertorExecutor);
+        flowUpdate = new MultiLayerFlowService<>(requestContextStack, deviceContext, UpdateFlowOutput.class, convertorExecutor);
+        flowAddMessage = new SingleLayerFlowService<>(requestContextStack, deviceContext, AddFlowOutput.class);
+        flowUpdateMessage = new SingleLayerFlowService<>(requestContextStack, deviceContext, UpdateFlowOutput.class);
+        flowRemoveMessage= new SingleLayerFlowService<>(requestContextStack, deviceContext, RemoveFlowOutput.class);
     }
 
     @Override
@@ -88,7 +90,7 @@ public class SalFlowServiceImpl implements SalFlowService, ItemLifeCycleSource {
         final FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(deviceContext.getDeviceInfo().getVersion(), input);
         final ListenableFuture<RpcResult<AddFlowOutput>> future;
 
-        if (flowAddMessage.isSupported()) {
+        if (flowAddMessage.canUseSingleLayerSerialization()) {
             future = flowAddMessage.handleServiceCall(input);
             Futures.addCallback(future, new AddFlowCallback(input, flowRegistryKey));
         } else {
@@ -103,7 +105,7 @@ public class SalFlowServiceImpl implements SalFlowService, ItemLifeCycleSource {
     public Future<RpcResult<RemoveFlowOutput>> removeFlow(final RemoveFlowInput input) {
         final ListenableFuture<RpcResult<RemoveFlowOutput>> future;
 
-        if (flowRemoveMessage.isSupported()) {
+        if (flowRemoveMessage.canUseSingleLayerSerialization()) {
             future = flowRemoveMessage.handleServiceCall(input);
             Futures.addCallback(future, new RemoveFlowCallback(input));
 
@@ -124,7 +126,7 @@ public class SalFlowServiceImpl implements SalFlowService, ItemLifeCycleSource {
         final List<FlowModInputBuilder> ofFlowModInputs;
 
         ListenableFuture<RpcResult<UpdateFlowOutput>> future;
-        if (flowUpdateMessage.isSupported()) {
+        if (flowUpdateMessage.canUseSingleLayerSerialization()) {
 
             if (!FlowCreatorUtil.canModifyFlow(original, updated, flowUpdateMessage.getVersion())) {
                 final SettableFuture<RpcResult<UpdateFlowOutput>> objectSettableFuture = SettableFuture.create();
similarity index 99%
rename from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalFlowsBatchServiceImpl.java
rename to openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalFlowsBatchServiceImpl.java
index 00f9fbc771cf560ccc75f6cd9e7596cbf92a1b71..73ca65df3bfd4a72d0dff6766a18ee54b6d8d303 100644 (file)
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.Futures;
similarity index 76%
rename from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalGroupServiceImpl.java
rename to openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalGroupServiceImpl.java
index 946c701b3951b006b1834028f08d58b07acaa973..ece2a7a6651d8bfda84838e7e85ea2ab89577dfb 100644 (file)
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
@@ -16,6 +16,8 @@ import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.rpc.ItemLifeCycleSource;
 import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
+import org.opendaylight.openflowplugin.impl.services.singlelayer.SingleLayerGroupService;
+import org.opendaylight.openflowplugin.impl.services.multilayer.MultiLayerGroupService;
 import org.opendaylight.openflowplugin.impl.util.ErrorUtil;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
@@ -39,25 +41,25 @@ import org.slf4j.LoggerFactory;
 
 public class SalGroupServiceImpl implements SalGroupService, ItemLifeCycleSource {
     private static final Logger LOG = LoggerFactory.getLogger(SalGroupServiceImpl.class);
-    private final GroupService<AddGroupInput, AddGroupOutput> addGroup;
-    private final GroupService<Group, UpdateGroupOutput> updateGroup;
-    private final GroupService<RemoveGroupInput, RemoveGroupOutput> removeGroup;
-    private final GroupMessageService<AddGroupOutput> addGroupMessage;
-    private final GroupMessageService<UpdateGroupOutput> updateGroupMessage;
-    private final GroupMessageService<RemoveGroupOutput> removeGroupMessage;
+    private final MultiLayerGroupService<AddGroupInput, AddGroupOutput> addGroup;
+    private final MultiLayerGroupService<Group, UpdateGroupOutput> updateGroup;
+    private final MultiLayerGroupService<RemoveGroupInput, RemoveGroupOutput> removeGroup;
+    private final SingleLayerGroupService<AddGroupOutput> addGroupMessage;
+    private final SingleLayerGroupService<UpdateGroupOutput> updateGroupMessage;
+    private final SingleLayerGroupService<RemoveGroupOutput> removeGroupMessage;
 
     private final DeviceContext deviceContext;
     private ItemLifecycleListener itemLifecycleListener;
 
     public SalGroupServiceImpl(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final ConvertorExecutor convertorExecutor) {
         this.deviceContext = deviceContext;
-        addGroup = new GroupService<>(requestContextStack, deviceContext, AddGroupOutput.class, convertorExecutor);
-        updateGroup = new GroupService<>(requestContextStack, deviceContext, UpdateGroupOutput.class, convertorExecutor);
-        removeGroup = new GroupService<>(requestContextStack, deviceContext, RemoveGroupOutput.class, convertorExecutor);
+        addGroup = new MultiLayerGroupService<>(requestContextStack, deviceContext, AddGroupOutput.class, convertorExecutor);
+        updateGroup = new MultiLayerGroupService<>(requestContextStack, deviceContext, UpdateGroupOutput.class, convertorExecutor);
+        removeGroup = new MultiLayerGroupService<>(requestContextStack, deviceContext, RemoveGroupOutput.class, convertorExecutor);
 
-        addGroupMessage = new GroupMessageService<>(requestContextStack, deviceContext, AddGroupOutput.class);
-        updateGroupMessage = new GroupMessageService<>(requestContextStack, deviceContext, UpdateGroupOutput.class);
-        removeGroupMessage = new GroupMessageService<>(requestContextStack, deviceContext, RemoveGroupOutput.class);
+        addGroupMessage = new SingleLayerGroupService<>(requestContextStack, deviceContext, AddGroupOutput.class);
+        updateGroupMessage = new SingleLayerGroupService<>(requestContextStack, deviceContext, UpdateGroupOutput.class);
+        removeGroupMessage = new SingleLayerGroupService<>(requestContextStack, deviceContext, RemoveGroupOutput.class);
     }
 
     @Override
@@ -67,7 +69,7 @@ public class SalGroupServiceImpl implements SalGroupService, ItemLifeCycleSource
 
     @Override
     public Future<RpcResult<AddGroupOutput>> addGroup(final AddGroupInput input) {
-        final ListenableFuture<RpcResult<AddGroupOutput>> resultFuture = addGroupMessage.isSupported()
+        final ListenableFuture<RpcResult<AddGroupOutput>> resultFuture = addGroupMessage.canUseSingleLayerSerialization()
             ? addGroupMessage.handleServiceCall(input)
             : addGroup.handleServiceCall(input);
 
@@ -83,7 +85,7 @@ public class SalGroupServiceImpl implements SalGroupService, ItemLifeCycleSource
                 } else {
                     if (LOG.isDebugEnabled()) {
                         LOG.debug("Group add with id={} failed, errors={}", input.getGroupId().getValue(),
-                                ErrorUtil.errorsToString(result.getErrors()));
+                            ErrorUtil.errorsToString(result.getErrors()));
                     }
                 }
             }
@@ -99,25 +101,24 @@ public class SalGroupServiceImpl implements SalGroupService, ItemLifeCycleSource
 
     @Override
     public Future<RpcResult<UpdateGroupOutput>> updateGroup(final UpdateGroupInput input) {
-        final ListenableFuture<RpcResult<UpdateGroupOutput>> resultFuture = updateGroupMessage.isSupported()
+        final ListenableFuture<RpcResult<UpdateGroupOutput>> resultFuture = updateGroupMessage.canUseSingleLayerSerialization()
             ? updateGroupMessage.handleServiceCall(input.getUpdatedGroup())
             : updateGroup.handleServiceCall(input.getUpdatedGroup());
 
         Futures.addCallback(resultFuture, new FutureCallback<RpcResult<UpdateGroupOutput>>() {
             @Override
-            public void onSuccess(@Nullable RpcResult<UpdateGroupOutput> result) {
+            public void onSuccess(RpcResult<UpdateGroupOutput> result) {
                 if (result.isSuccessful()) {
                     if (LOG.isDebugEnabled()) {
                         LOG.debug("Group update with original id={} finished without error",
-                                input.getOriginalGroup().getGroupId().getValue());
+                            input.getOriginalGroup().getGroupId().getValue());
                     }
                     removeIfNecessaryFromDS(input.getOriginalGroup().getGroupId());
                     addIfNecessaryToDS(input.getUpdatedGroup().getGroupId(), input.getUpdatedGroup());
                 } else {
-                    if (LOG.isDebugEnabled()) {
-                        LOG.debug("Group update with original id={} failed, errors={}",
-                                input.getOriginalGroup().getGroupId(), ErrorUtil.errorsToString(result.getErrors()));
-                    }
+                    LOG.warn("Group update with original id={} failed, errors={}",
+                        input.getOriginalGroup().getGroupId(), ErrorUtil.errorsToString(result.getErrors()));
+                    LOG.debug("Group input={}", input.getUpdatedGroup());
                 }
             }
 
@@ -132,13 +133,13 @@ public class SalGroupServiceImpl implements SalGroupService, ItemLifeCycleSource
 
     @Override
     public Future<RpcResult<RemoveGroupOutput>> removeGroup(final RemoveGroupInput input) {
-        final ListenableFuture<RpcResult<RemoveGroupOutput>> resultFuture = removeGroupMessage.isSupported()
+        final ListenableFuture<RpcResult<RemoveGroupOutput>> resultFuture = removeGroupMessage.canUseSingleLayerSerialization()
             ? removeGroupMessage.handleServiceCall(input)
             : removeGroup.handleServiceCall(input);
 
         Futures.addCallback(resultFuture, new FutureCallback<RpcResult<RemoveGroupOutput>>() {
             @Override
-            public void onSuccess(@Nullable RpcResult<RemoveGroupOutput> result) {
+            public void onSuccess(RpcResult<RemoveGroupOutput> result) {
                 if (result.isSuccessful()) {
                     if (LOG.isDebugEnabled()) {
                         LOG.debug("Group remove with id={} finished without error", input.getGroupId().getValue());
@@ -146,10 +147,9 @@ public class SalGroupServiceImpl implements SalGroupService, ItemLifeCycleSource
                     removeGroup.getDeviceRegistry().getDeviceGroupRegistry().markToBeremoved(input.getGroupId());
                     removeIfNecessaryFromDS(input.getGroupId());
                 } else {
-                    if (LOG.isDebugEnabled()) {
-                        LOG.debug("Group remove with id={} failed, errors={}", input.getGroupId().getValue(),
-                                ErrorUtil.errorsToString(result.getErrors()));
-                    }
+                    LOG.warn("Group remove with id={} failed, errors={}", input.getGroupId().getValue(),
+                        ErrorUtil.errorsToString(result.getErrors()));
+                    LOG.debug("Group input={}", input);
                 }
             }
 
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
similarity index 76%
rename from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalMeterServiceImpl.java
rename to openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalMeterServiceImpl.java
index 1e3715d45492c0f13d5d85deb9b506bf91e427a1..450746c51096fb76d32fd393b639e985792f4f6a 100644 (file)
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
@@ -16,6 +16,8 @@ import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.rpc.ItemLifeCycleSource;
 import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
+import org.opendaylight.openflowplugin.impl.services.singlelayer.SingleLayerMeterService;
+import org.opendaylight.openflowplugin.impl.services.multilayer.MultiLayerMeterService;
 import org.opendaylight.openflowplugin.impl.util.ErrorUtil;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
@@ -39,25 +41,25 @@ import org.slf4j.LoggerFactory;
 
 public class SalMeterServiceImpl implements SalMeterService, ItemLifeCycleSource {
     private static final Logger LOG = LoggerFactory.getLogger(SalMeterServiceImpl.class);
-    private final MeterService<AddMeterInput, AddMeterOutput> addMeter;
-    private final MeterService<Meter, UpdateMeterOutput> updateMeter;
-    private final MeterService<RemoveMeterInput, RemoveMeterOutput> removeMeter;
-    private final MeterMessageService<AddMeterOutput> addMeterMessage;
-    private final MeterMessageService<UpdateMeterOutput> updateMeterMessage;
-    private final MeterMessageService<RemoveMeterOutput> removeMeterMessage;
+    private final MultiLayerMeterService<AddMeterInput, AddMeterOutput> addMeter;
+    private final MultiLayerMeterService<Meter, UpdateMeterOutput> updateMeter;
+    private final MultiLayerMeterService<RemoveMeterInput, RemoveMeterOutput> removeMeter;
+    private final SingleLayerMeterService<AddMeterOutput> addMeterMessage;
+    private final SingleLayerMeterService<UpdateMeterOutput> updateMeterMessage;
+    private final SingleLayerMeterService<RemoveMeterOutput> removeMeterMessage;
 
     private ItemLifecycleListener itemLifecycleListener;
     private final DeviceContext deviceContext;
 
     public SalMeterServiceImpl(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final ConvertorExecutor convertorExecutor) {
         this.deviceContext = deviceContext;
-        addMeter = new MeterService<>(requestContextStack, deviceContext, AddMeterOutput.class, convertorExecutor);
-        updateMeter = new MeterService<>(requestContextStack, deviceContext, UpdateMeterOutput.class, convertorExecutor);
-        removeMeter = new MeterService<>(requestContextStack, deviceContext, RemoveMeterOutput.class, convertorExecutor);
+        addMeter = new MultiLayerMeterService<>(requestContextStack, deviceContext, AddMeterOutput.class, convertorExecutor);
+        updateMeter = new MultiLayerMeterService<>(requestContextStack, deviceContext, UpdateMeterOutput.class, convertorExecutor);
+        removeMeter = new MultiLayerMeterService<>(requestContextStack, deviceContext, RemoveMeterOutput.class, convertorExecutor);
 
-        addMeterMessage = new MeterMessageService<>(requestContextStack, deviceContext, AddMeterOutput.class);
-        updateMeterMessage = new MeterMessageService<>(requestContextStack, deviceContext, UpdateMeterOutput.class);
-        removeMeterMessage = new MeterMessageService<>(requestContextStack, deviceContext, RemoveMeterOutput.class);
+        addMeterMessage = new SingleLayerMeterService<>(requestContextStack, deviceContext, AddMeterOutput.class);
+        updateMeterMessage = new SingleLayerMeterService<>(requestContextStack, deviceContext, UpdateMeterOutput.class);
+        removeMeterMessage = new SingleLayerMeterService<>(requestContextStack, deviceContext, RemoveMeterOutput.class);
     }
 
     @Override
@@ -67,15 +69,15 @@ public class SalMeterServiceImpl implements SalMeterService, ItemLifeCycleSource
 
     @Override
     public Future<RpcResult<AddMeterOutput>> addMeter(final AddMeterInput input) {
-        final ListenableFuture<RpcResult<AddMeterOutput>> resultFuture = addMeterMessage.isSupported()
+        final ListenableFuture<RpcResult<AddMeterOutput>> resultFuture = addMeterMessage.canUseSingleLayerSerialization()
             ? addMeterMessage.handleServiceCall(input)
             : addMeter.handleServiceCall(input);
 
         Futures.addCallback(resultFuture, new FutureCallback<RpcResult<AddMeterOutput>>() {
             @Override
-            public void onSuccess(@Nullable RpcResult<AddMeterOutput> result) {
+            public void onSuccess(RpcResult<AddMeterOutput> result) {
                 if (result.isSuccessful()) {
-                   if (LOG.isDebugEnabled()) {
+                    if (LOG.isDebugEnabled()) {
                         LOG.debug("Meter add with id={} finished without error", input.getMeterId());
                     }
                     deviceContext.getDeviceMeterRegistry().store(input.getMeterId());
@@ -83,7 +85,7 @@ public class SalMeterServiceImpl implements SalMeterService, ItemLifeCycleSource
                 } else {
                     if (LOG.isDebugEnabled()) {
                         LOG.debug("Meter add with id={} failed, errors={}", input.getMeterId(),
-                                ErrorUtil.errorsToString(result.getErrors()));
+                            ErrorUtil.errorsToString(result.getErrors()));
                     }
                 }
             }
@@ -98,14 +100,14 @@ public class SalMeterServiceImpl implements SalMeterService, ItemLifeCycleSource
 
     @Override
     public Future<RpcResult<UpdateMeterOutput>> updateMeter(final UpdateMeterInput input) {
-        final ListenableFuture<RpcResult<UpdateMeterOutput>> resultFuture = updateMeterMessage.isSupported()
+        final ListenableFuture<RpcResult<UpdateMeterOutput>> resultFuture = updateMeterMessage.canUseSingleLayerSerialization()
             ? updateMeterMessage.handleServiceCall(input.getUpdatedMeter())
             : updateMeter.handleServiceCall(input.getUpdatedMeter());
 
         Futures.addCallback(resultFuture, new FutureCallback<RpcResult<UpdateMeterOutput>>() {
 
             @Override
-            public void onSuccess(@Nullable RpcResult<UpdateMeterOutput> result) {
+            public void onSuccess(RpcResult<UpdateMeterOutput> result) {
                 if (result.isSuccessful()) {
                     if (LOG.isDebugEnabled()) {
                         LOG.debug("Meter update with id={} finished without error", input.getOriginalMeter().getMeterId());
@@ -115,10 +117,9 @@ public class SalMeterServiceImpl implements SalMeterService, ItemLifeCycleSource
                         addIfNecessaryToDS(input.getUpdatedMeter().getMeterId(),input.getUpdatedMeter());
                     }
                 } else {
-                    if (LOG.isDebugEnabled()) {
-                        LOG.debug("Meter update with id={} failed, errors={}", input.getOriginalMeter().getMeterId(),
+                        LOG.warn("Meter update with id={} failed, errors={}", input.getOriginalMeter().getMeterId(),
                                 ErrorUtil.errorsToString(result.getErrors()));
-                    }
+                        LOG.debug("Meter input={}", input.getUpdatedMeter());
                 }
             }
 
@@ -133,24 +134,23 @@ public class SalMeterServiceImpl implements SalMeterService, ItemLifeCycleSource
 
     @Override
     public Future<RpcResult<RemoveMeterOutput>> removeMeter(final RemoveMeterInput input) {
-        removeMeter.getDeviceRegistry().getDeviceMeterRegistry().markToBeremoved(input.getMeterId());
-        final ListenableFuture<RpcResult<RemoveMeterOutput>> resultFuture = removeMeterMessage.isSupported()
+        final ListenableFuture<RpcResult<RemoveMeterOutput>> resultFuture = removeMeterMessage.canUseSingleLayerSerialization()
             ? removeMeterMessage.handleServiceCall(input)
             : removeMeter.handleServiceCall(input);
 
         Futures.addCallback(resultFuture, new FutureCallback<RpcResult<RemoveMeterOutput>>() {
             @Override
-            public void onSuccess(@Nullable RpcResult<RemoveMeterOutput> result) {
+            public void onSuccess(RpcResult<RemoveMeterOutput> result) {
                 if (result.isSuccessful()) {
                     if (LOG.isDebugEnabled()) {
                         LOG.debug("Meter remove with id={} finished without error", input.getMeterId());
                     }
+                    removeMeter.getDeviceRegistry().getDeviceMeterRegistry().markToBeremoved(input.getMeterId());
                     removeIfNecessaryFromDS(input.getMeterId());
                 } else {
-                    if (LOG.isDebugEnabled()) {
-                        LOG.debug("Meter remove with id={} failed, errors={}", input.getMeterId(),
-                                ErrorUtil.errorsToString(result.getErrors()));
-                    }
+                    LOG.warn("Meter remove with id={} failed, errors={}", input.getMeterId(),
+                        ErrorUtil.errorsToString(result.getErrors()));
+                    LOG.debug("Meter input={}", input);
                 }
             }
 
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
similarity index 84%
rename from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalPortServiceImpl.java
rename to openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalPortServiceImpl.java
index 8caae1981044c11af6df2d7089c83d54bf63ca2a..317a7cb101e8ea58159fc0006bd2f0c288ac862b 100644 (file)
@@ -5,13 +5,16 @@
  * 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import java.util.Optional;
 import java.util.concurrent.Future;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.impl.services.AbstractSimpleService;
+import org.opendaylight.openflowplugin.impl.services.singlelayer.SingleLayerPortService;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.PortConvertor;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData;
@@ -27,18 +30,18 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 public final class SalPortServiceImpl extends AbstractSimpleService<UpdatePortInput, UpdatePortOutput> implements SalPortService {
     private final ConvertorExecutor convertorExecutor;
     private final VersionConvertorData data;
-    private final PortMessageService<UpdatePortOutput> portMessage;
+    private final SingleLayerPortService<UpdatePortOutput> portMessage;
 
     public SalPortServiceImpl(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final ConvertorExecutor convertorExecutor) {
         super(requestContextStack, deviceContext, UpdatePortOutput.class);
         this.convertorExecutor = convertorExecutor;
         data = new VersionConvertorData(getVersion());
-        portMessage = new PortMessageService<>(requestContextStack, deviceContext, UpdatePortOutput.class);
+        portMessage = new SingleLayerPortService<>(requestContextStack, deviceContext, UpdatePortOutput.class);
     }
 
     @Override
     public Future<RpcResult<UpdatePortOutput>> updatePort(final UpdatePortInput input) {
-        return portMessage.isSupported()
+        return portMessage.canUseSingleLayerSerialization()
             ? portMessage.handleServiceCall(getPortFromInput(input))
             : handleServiceCall(input);
     }
similarity index 96%
rename from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalRoleServiceImpl.java
rename to openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalRoleServiceImpl.java
index 9906515af633106c39dd1f239c6e653ff2d35722..20f063f5c24fac2c03f9ab20501880b3356c164b 100644 (file)
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.AsyncFunction;
@@ -23,6 +23,9 @@ import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.impl.role.RoleChangeException;
+import org.opendaylight.openflowplugin.impl.services.AbstractSimpleService;
+import org.opendaylight.openflowplugin.impl.services.RoleService;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
@@ -80,7 +83,7 @@ public final class SalRoleServiceImpl extends AbstractSimpleService<SetRoleInput
             return RpcResultBuilder.<SetRoleOutput> success().buildFuture();
         }
 
-        final SettableFuture<RpcResult<SetRoleOutput>> resultFuture = SettableFuture.<RpcResult<SetRoleOutput>> create();
+        final SettableFuture<RpcResult<SetRoleOutput>> resultFuture = SettableFuture.create();
         repeaterForChangeRole(resultFuture, input, 0);
         /* Add Callback for release Guard */
         Futures.addCallback(resultFuture, new FutureCallback<RpcResult<SetRoleOutput>>() {
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalTableServiceImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalTableServiceImpl.java
new file mode 100644 (file)
index 0000000..bfa4069
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.openflowplugin.impl.services.sal;
+
+import java.util.concurrent.Future;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.services.multilayer.MultiLayerTableMultipartService;
+import org.opendaylight.openflowplugin.impl.services.singlelayer.SingleLayerTableMultipartService;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+public final class SalTableServiceImpl implements SalTableService {
+
+    private final SingleLayerTableMultipartService singleLayerService;
+    private final MultiLayerTableMultipartService multiLayerService;
+
+    public SalTableServiceImpl(final RequestContextStack requestContextStack,
+                               final DeviceContext deviceContext,
+                               final ConvertorExecutor convertorExecutor,
+                               final MultipartWriterProvider multipartWriterProvider) {
+        singleLayerService = new SingleLayerTableMultipartService(requestContextStack, deviceContext, convertorExecutor, multipartWriterProvider);
+        multiLayerService = new MultiLayerTableMultipartService(requestContextStack, deviceContext, convertorExecutor, multipartWriterProvider);
+    }
+
+    @Override
+    public Future<RpcResult<UpdateTableOutput>> updateTable(final UpdateTableInput input) {
+        return singleLayerService.canUseSingleLayerSerialization()
+            ? singleLayerService.handleAndReply(input)
+            : multiLayerService.handleAndReply(input);
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerAggregateFlowMultipartService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerAggregateFlowMultipartService.java
new file mode 100644 (file)
index 0000000..7a732fb
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services.singlelayer;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import java.util.List;
+import java.util.concurrent.Future;
+import java.util.stream.Collectors;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.services.AbstractAggregateFlowMultipartService;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.get.aggregate.flow.statistics.from.flow.table._for.given.match.output.AggregatedFlowStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.multipart.reply.multipart.reply.body.MultipartReplyFlowAggregateStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+public class SingleLayerAggregateFlowMultipartService
+    extends AbstractAggregateFlowMultipartService<MultipartReply> {
+
+    public SingleLayerAggregateFlowMultipartService(final RequestContextStack requestContextStack,
+                                                    final DeviceContext deviceContext,
+                                                    final ConvertorExecutor convertorExecutor) {
+        super(requestContextStack, deviceContext, convertorExecutor);
+    }
+
+    @Override
+    public Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>> handleAndReply(
+        final GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput input) {
+        return Futures.transform(handleServiceCall(input),
+            (Function<RpcResult<List<MultipartReply>>, RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>>) result -> {
+                if (Preconditions.checkNotNull(result).isSuccessful()) {
+                    return RpcResultBuilder
+                        .success(new GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder()
+                            .setAggregatedFlowStatistics(result
+                                .getResult()
+                                .stream()
+                                .map(MultipartReply::getMultipartReplyBody)
+                                .filter(MultipartReplyFlowAggregateStats.class::isInstance)
+                                .map(multipartReplyBody ->
+                                    new AggregatedFlowStatisticsBuilder(MultipartReplyFlowAggregateStats.class
+                                        .cast(multipartReplyBody))
+                                        .build())
+                                .collect(Collectors.toList())))
+                        .build();
+                }
+
+                return RpcResultBuilder
+                    .<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>failed()
+                    .withRpcErrors(result.getErrors())
+                    .build();
+            });
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerExperimenterMultipartService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerExperimenterMultipartService.java
new file mode 100644 (file)
index 0000000..4aec8d0
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services.singlelayer;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.SettableFuture;
+import java.util.List;
+import java.util.concurrent.Future;
+import java.util.stream.Collectors;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
+import org.opendaylight.openflowplugin.impl.services.AbstractExperimenterMultipartService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.send.experimenter.mp.request.output.ExperimenterCoreMessageItemBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.experimenter.types.rev151020.multipart.reply.multipart.reply.body.MultipartReplyExperimenter;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+
+public class SingleLayerExperimenterMultipartService extends AbstractExperimenterMultipartService<MultipartReply> {
+
+    private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(SingleLayerExperimenterMultipartService.class);
+
+    public SingleLayerExperimenterMultipartService(RequestContextStack requestContextStack, DeviceContext deviceContext,
+                                                   ExtensionConverterProvider extensionConverterProvider) {
+        super(requestContextStack, deviceContext, extensionConverterProvider);
+    }
+
+    @Override
+    public Future<RpcResult<SendExperimenterMpRequestOutput>> handleAndReply(SendExperimenterMpRequestInput input) {
+        final SettableFuture<RpcResult<SendExperimenterMpRequestOutput>> future = SettableFuture.create();
+
+        Futures.addCallback(handleServiceCall(input), new FutureCallback<RpcResult<List<MultipartReply>>>() {
+            @Override
+            public void onSuccess(final RpcResult<List<MultipartReply>> result) {
+                if (result.isSuccessful()) {
+                    future.set(RpcResultBuilder
+                        .success(new SendExperimenterMpRequestOutputBuilder()
+                            .setExperimenterCoreMessageItem(result
+                                .getResult()
+                                .stream()
+                                .map(MultipartReply::getMultipartReplyBody)
+                                .filter(MultipartReplyExperimenter.class::isInstance)
+                                .map(experimenter -> new ExperimenterCoreMessageItemBuilder()
+                                    .setExperimenterMessageOfChoice(MultipartReplyExperimenter.class
+                                        .cast(experimenter)
+                                        .getExperimenterMessageOfChoice())
+                                    .build())
+                                .collect(Collectors.toList()))
+                            .build())
+                        .build());
+                } else {
+                    LOG.warn("OnSuccess, rpc result unsuccessful, multipart response for rpc sendExperimenterMpRequest was unsuccessful.");
+                    future.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed().withRpcErrors(result.getErrors()).build());
+                }
+            }
+
+            @Override
+            public void onFailure(final Throwable t) {
+                LOG.warn("Failure multipart response for Experimenter-Mp request. Exception: {}", t);
+                future.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed().withError(ErrorType.RPC, "Future error", t).build());
+            }
+        });
+
+        return future;
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerFlowMultipartRequestOnTheFlyCallback.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerFlowMultipartRequestOnTheFlyCallback.java
new file mode 100644 (file)
index 0000000..b810a36
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services.singlelayer;
+
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.List;
+import java.util.Optional;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
+import org.opendaylight.openflowplugin.impl.common.MultipartReplyTranslatorUtil;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.services.AbstractMultipartRequestOnTheFlyCallback;
+import org.opendaylight.openflowplugin.impl.statistics.StatisticsGatheringUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.multipart.reply.multipart.reply.body.MultipartReplyFlowStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+
+public class SingleLayerFlowMultipartRequestOnTheFlyCallback<T extends OfHeader> extends AbstractMultipartRequestOnTheFlyCallback<T> {
+
+    private final DeviceInfo deviceInfo;
+    private boolean virgin = true;
+
+    public SingleLayerFlowMultipartRequestOnTheFlyCallback(final RequestContext<List<T>> context, Class<?> requestType,
+                                                           final DeviceContext deviceContext,
+                                                           final EventIdentifier eventIdentifier,
+                                                           final MultipartWriterProvider statisticsWriterProvider) {
+        super(context, requestType, deviceContext, eventIdentifier, statisticsWriterProvider);
+        deviceInfo = deviceContext.getDeviceInfo();
+    }
+
+    @Override
+    protected boolean isMultipart(OfHeader result) {
+        return result instanceof MultipartReply
+            && MultipartReply.class.cast(result).getMultipartReplyBody() instanceof MultipartReplyFlowStats;
+    }
+
+    @Override
+    protected boolean isReqMore(T result) {
+        return MultipartReply.class.cast(result).isRequestMore();
+    }
+
+    @Override
+    protected MultipartType getMultipartType() {
+        return MultipartType.OFPMPFLOW;
+    }
+
+    @Override
+    protected ListenableFuture<Optional<? extends MultipartReplyBody>> processStatistics(T result) {
+        final ListenableFuture<Optional<? extends MultipartReplyBody>> future = Futures.transform(
+            StatisticsGatheringUtils.deleteAllKnownFlows(
+                getTxFacade(),
+                deviceInfo
+                    .getNodeInstanceIdentifier()
+                    .augmentation(FlowCapableNode.class),
+                !virgin),
+            (Function<Void, Optional<? extends MultipartReplyBody>>) input -> MultipartReplyTranslatorUtil
+                .translate(result, deviceInfo, null, null));
+
+        if (virgin) {
+            virgin = false;
+        }
+
+        return future;
+    }
+
+}
similarity index 82%
rename from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/FlowMessageService.java
rename to openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerFlowService.java
index 6282abb91aa7c541cffb74700a316fae34df1c98..6c924cd5ed403cda78818e30c32c46c2c315810c 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -6,12 +6,13 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.singlelayer;
 
-import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.impl.services.AbstractSilentErrorService;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlow;
@@ -23,8 +24,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 
-final class FlowMessageService<O extends DataObject> extends AbstractMessageService<Flow, FlowMessageBuilder, O> {
-    protected FlowMessageService(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final Class<O> clazz) {
+public final class SingleLayerFlowService<O extends DataObject> extends AbstractSilentErrorService<Flow, O> {
+    public SingleLayerFlowService(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final Class<O> clazz) {
         super(requestContextStack, deviceContext, clazz);
     }
 
@@ -49,9 +50,4 @@ final class FlowMessageService<O extends DataObject> extends AbstractMessageServ
                 .build();
     }
 
-    @Override
-    public boolean isSupported() {
-        return super.isSupported() && getVersion() >= OFConstants.OFP_VERSION_1_3;
-    }
-
 }
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -6,12 +6,13 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.singlelayer;
 
-import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.impl.services.AbstractSimpleService;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroup;
@@ -23,12 +24,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 
-final class GroupMessageService<O extends DataObject> extends AbstractMessageService<Group, GroupMessageBuilder, O> {
+public final class SingleLayerGroupService<O extends DataObject> extends AbstractSimpleService<Group, O> {
 
-    protected GroupMessageService(
-            final RequestContextStack requestContextStack,
-            final DeviceContext deviceContext,
-            final Class<O> clazz) {
+    public SingleLayerGroupService(
+        final RequestContextStack requestContextStack,
+        final DeviceContext deviceContext,
+        final Class<O> clazz) {
         super(requestContextStack, deviceContext, clazz);
     }
 
@@ -37,9 +38,10 @@ final class GroupMessageService<O extends DataObject> extends AbstractMessageSer
         final GroupMessageBuilder groupMessageBuilder = new GroupMessageBuilder(input);
         final Class<? extends DataContainer> clazz = input.getImplementedInterface();
 
-        if (clazz.equals(AddGroupInput.class)
-                || clazz.equals(UpdatedGroup.class)) {
+        if (clazz.equals(AddGroupInput.class)) {
             groupMessageBuilder.setCommand(GroupModCommand.OFPGCADD);
+        } else if (clazz.equals(UpdatedGroup.class)) {
+            groupMessageBuilder.setCommand(GroupModCommand.OFPGCMODIFY);
         } else if (clazz.equals(RemoveGroupInput.class)
                 || clazz.equals(OriginalGroup.class)) {
             groupMessageBuilder.setCommand(GroupModCommand.OFPGCDELETE);
@@ -51,9 +53,4 @@ final class GroupMessageService<O extends DataObject> extends AbstractMessageSer
                 .build();
     }
 
-    @Override
-    public boolean isSupported() {
-        return super.isSupported() && getVersion() >= OFConstants.OFP_VERSION_1_3;
-    }
-
 }
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -6,12 +6,13 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.singlelayer;
 
-import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.impl.services.AbstractSilentErrorService;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeter;
@@ -23,37 +24,32 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 
-final class MeterMessageService<O extends DataObject> extends AbstractMessageService<Meter, MeterMessageBuilder, O> {
+public final class SingleLayerMeterService<O extends DataObject> extends AbstractSilentErrorService<Meter, O> {
 
-    protected MeterMessageService(
-            final RequestContextStack requestContextStack,
-            final DeviceContext deviceContext,
-            final Class<O> clazz) {
+    public SingleLayerMeterService(
+        final RequestContextStack requestContextStack,
+        final DeviceContext deviceContext,
+        final Class<O> clazz) {
         super(requestContextStack, deviceContext, clazz);
     }
 
     @Override
     protected OfHeader buildRequest(final Xid xid, final Meter input) throws ServiceException {
-        final MeterMessageBuilder groupMessageBuilder = new MeterMessageBuilder(input);
+        final MeterMessageBuilder meterMessageBuilder = new MeterMessageBuilder(input);
         final Class<? extends DataContainer> clazz = input.getImplementedInterface();
 
         if (clazz.equals(AddMeterInput.class)
                 || clazz.equals(UpdatedMeter.class)) {
-            groupMessageBuilder.setCommand(MeterModCommand.OFPMCADD);
+            meterMessageBuilder.setCommand(MeterModCommand.OFPMCADD);
         } else if (clazz.equals(RemoveMeterInput.class)
                 || clazz.equals(OriginalMeter.class)) {
-            groupMessageBuilder.setCommand(MeterModCommand.OFPMCDELETE);
+            meterMessageBuilder.setCommand(MeterModCommand.OFPMCDELETE);
         }
 
-        return groupMessageBuilder
+        return meterMessageBuilder
                 .setVersion(getVersion())
                 .setXid(xid.getValue())
                 .build();
     }
 
-    @Override
-    public boolean isSupported() {
-        return super.isSupported() && getVersion() >= OFConstants.OFP_VERSION_1_3;
-    }
-
 }
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerMultipartCollectorService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerMultipartCollectorService.java
new file mode 100644 (file)
index 0000000..2d1b783
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services.singlelayer;
+
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.services.AbstractMultipartCollectorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply;
+
+public class SingleLayerMultipartCollectorService extends AbstractMultipartCollectorService<MultipartReply> {
+
+    public SingleLayerMultipartCollectorService(final RequestContextStack requestContextStack, final DeviceContext deviceContext) {
+        super(requestContextStack, deviceContext);
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerMultipartRequestCallback.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerMultipartRequestCallback.java
new file mode 100644 (file)
index 0000000..407637d
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services.singlelayer;
+
+import java.util.List;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
+import org.opendaylight.openflowplugin.impl.services.AbstractMultipartRequestCallback;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+
+public class SingleLayerMultipartRequestCallback<T extends OfHeader> extends AbstractMultipartRequestCallback<T> {
+
+    public SingleLayerMultipartRequestCallback(RequestContext<List<T>> context, Class<?> requestType, DeviceContext deviceContext, EventIdentifier eventIdentifier) {
+        super(context, requestType, deviceContext, eventIdentifier);
+    }
+
+    @Override
+    protected boolean isMultipart(OfHeader result) {
+        return result instanceof MultipartReply;
+    }
+
+    @Override
+    protected boolean isReqMore(T result) {
+        return MultipartReply.class.cast(result).isRequestMore();
+    }
+
+}
similarity index 68%
rename from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/PortMessageService.java
rename to openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerPortService.java
index 4d17f6d120bea3fcdbcff0e102fd14677aca6570..814e5a0304cccf36efd81883c990d84591b67e08 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -6,23 +6,24 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.singlelayer;
 
-import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.impl.services.AbstractSimpleService;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.CommonPort;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortMessageBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 
-final class PortMessageService<O extends DataObject> extends AbstractMessageService<CommonPort, PortMessageBuilder, O> {
+public final class SingleLayerPortService<O extends DataObject> extends AbstractSimpleService<CommonPort, O> {
 
-    protected PortMessageService(
-            final RequestContextStack requestContextStack,
-            final DeviceContext deviceContext,
-            final Class<O> clazz) {
+    public SingleLayerPortService(
+        final RequestContextStack requestContextStack,
+        final DeviceContext deviceContext,
+        final Class<O> clazz) {
         super(requestContextStack, deviceContext, clazz);
     }
 
@@ -34,9 +35,4 @@ final class PortMessageService<O extends DataObject> extends AbstractMessageServ
                 .build();
     }
 
-    @Override
-    public boolean isSupported() {
-        return super.isSupported() && getVersion() >= OFConstants.OFP_VERSION_1_3;
-    }
-
 }
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerTableMultipartService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/singlelayer/SingleLayerTableMultipartService.java
new file mode 100644 (file)
index 0000000..a1a93a3
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services.singlelayer;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.SettableFuture;
+import java.math.BigInteger;
+import java.util.List;
+import java.util.concurrent.Future;
+import java.util.stream.Collectors;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.services.AbstractTableMultipartService;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.multipart.reply.multipart.reply.body.MultipartReplyTableFeatures;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SingleLayerTableMultipartService extends AbstractTableMultipartService<MultipartReply> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SingleLayerTableMultipartService.class);
+
+    public SingleLayerTableMultipartService(RequestContextStack requestContextStack,
+                                            DeviceContext deviceContext,
+                                            ConvertorExecutor convertorExecutor,
+                                            MultipartWriterProvider multipartWriterProvider) {
+        super(requestContextStack, deviceContext, convertorExecutor, multipartWriterProvider);
+    }
+
+    @Override
+    public Future<RpcResult<UpdateTableOutput>> handleAndReply(UpdateTableInput input) {
+        final SettableFuture<RpcResult<UpdateTableOutput>> finalFuture = SettableFuture.create();
+
+        Futures.addCallback(handleServiceCall(input), new FutureCallback<RpcResult<List<MultipartReply>>>() {
+            @Override
+            public void onSuccess(final RpcResult<List<MultipartReply>> result) {
+                if (result.isSuccessful()) {
+                    final List<MultipartReply> multipartReplies = result.getResult();
+                    if (multipartReplies.isEmpty()) {
+                        LOG.debug("Multipart reply to table features request shouldn't be empty list.");
+                        finalFuture.set(RpcResultBuilder.<UpdateTableOutput>failed()
+                            .withError(ErrorType.RPC, "Multipart reply list is empty.").build());
+                    } else {
+                        finalFuture.set(RpcResultBuilder
+                            .success(new UpdateTableOutputBuilder()
+                                .setTransactionId(new TransactionId(BigInteger.valueOf(multipartReplies.get(0).getXid())))
+                                .build())
+                            .build());
+
+                        try {
+                            storeStatistics(multipartReplies
+                                .stream()
+                                .map(MultipartReply::getMultipartReplyBody)
+                                .filter(MultipartReplyTableFeatures.class::isInstance)
+                                .flatMap(multipartReplyBody -> MultipartReplyTableFeatures.class
+                                    .cast(multipartReplyBody)
+                                    .getTableFeatures()
+                                    .stream())
+                                .collect(Collectors.toList()));
+                        } catch (Exception e) {
+                            LOG.warn("Not able to write to operational datastore: {}", e.getMessage());
+                        }
+                    }
+                } else {
+                    LOG.debug("OnSuccess, rpc result unsuccessful, multipart response for rpc update-table was unsuccessful.");
+                    finalFuture.set(RpcResultBuilder.<UpdateTableOutput>failed().withRpcErrors(result.getErrors())
+                        .build());
+                }
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LOG.error("Failure multipart response for table features request. Exception: {}", t);
+                finalFuture.set(RpcResultBuilder.<UpdateTableOutput>failed()
+                    .withError(ErrorType.RPC, "Future error", t).build());
+            }
+        });
+
+        return finalFuture;
+    }
+
+}
similarity index 96%
rename from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/RequestContextUtil.java
rename to openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/util/RequestContextUtil.java
index 25c6ec555fb16d2a866874b087281c40d24b12bd..a14f565638babff9b15b94b6d5e8ed7558451c78 100644 (file)
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.util;
 
 import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
similarity index 95%
rename from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/RequestInputUtils.java
rename to openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/util/RequestInputUtils.java
index b8aa9949fe80d1f17853769d579dcd109ed744c8..421cecd7500465e7239b1d7a492b2fc5227ba693 100644 (file)
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.util;
 
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
similarity index 91%
rename from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/ServiceException.java
rename to openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/util/ServiceException.java
index 7804e0bf6d098a59d676ade0903ce8e49fb1055e..56c8c12df93e749c98232656ee35fbcbcb089c54 100644 (file)
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.util;
 
 /**
  * Exception thrown by {@link org.opendaylight.openflowplugin.impl.services.AbstractService#buildRequest(org.opendaylight.openflowplugin.api.openflow.device.Xid, Object)}
index 4b5b7be9ca84ba0be030879e7521eb8b4a6821ab..4c9996a62106bc2b2954aee42500ee054fe262f5 100644 (file)
@@ -43,15 +43,17 @@ import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext
 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
 import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext;
 import org.opendaylight.openflowplugin.impl.rpc.listener.ItemLifecycleListenerImpl;
-import org.opendaylight.openflowplugin.impl.services.RequestContextUtil;
+import org.opendaylight.openflowplugin.impl.services.util.RequestContextUtil;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
 import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.StatisticsGatheringOnTheFlyService;
 import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.StatisticsGatheringService;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-class StatisticsContextImpl implements StatisticsContext {
+class StatisticsContextImpl<T extends OfHeader> implements StatisticsContext {
 
     private static final Logger LOG = LoggerFactory.getLogger(StatisticsContextImpl.class);
     private static final String CONNECTION_CLOSED = "Connection closed.";
@@ -62,13 +64,14 @@ class StatisticsContextImpl implements StatisticsContext {
     private final DeviceState devState;
     private final ListenableFuture<Boolean> emptyFuture;
     private final boolean isStatisticsPollingOn;
-    private final SinglePurposeMultipartReplyTranslator multipartReplyTranslator;
     private final Object collectionStatTypeLock = new Object();
+    private final ConvertorExecutor convertorExecutor;
+    private final MultipartWriterProvider statisticsWriterProvider;
     @GuardedBy("collectionStatTypeLock")
     private List<MultipartType> collectingStatType;
 
-    private StatisticsGatheringService statisticsGatheringService;
-    private StatisticsGatheringOnTheFlyService statisticsGatheringOnTheFlyService;
+    private StatisticsGatheringService<T> statisticsGatheringService;
+    private StatisticsGatheringOnTheFlyService<T> statisticsGatheringOnTheFlyService;
     private Timeout pollTimeout;
     private final DeviceInfo deviceInfo;
     private final StatisticsManager myManager;
@@ -85,21 +88,24 @@ class StatisticsContextImpl implements StatisticsContext {
                           final boolean isStatisticsPollingOn,
                           @Nonnull final LifecycleService lifecycleService,
                           @Nonnull final ConvertorExecutor convertorExecutor,
-                          @Nonnull final StatisticsManager myManager) {
+                          @Nonnull final StatisticsManager myManager,
+                          @Nonnull final MultipartWriterProvider statisticsWriterProvider) {
         this.lifecycleService = lifecycleService;
         this.deviceContext = lifecycleService.getDeviceContext();
         this.devState = Preconditions.checkNotNull(deviceContext.getDeviceState());
         this.isStatisticsPollingOn = isStatisticsPollingOn;
-        multipartReplyTranslator = new SinglePurposeMultipartReplyTranslator(convertorExecutor);
+        this.convertorExecutor = convertorExecutor;
         emptyFuture = Futures.immediateFuture(false);
-        statisticsGatheringService = new StatisticsGatheringService(this, deviceContext);
-        statisticsGatheringOnTheFlyService = new StatisticsGatheringOnTheFlyService(this, deviceContext, convertorExecutor);
+        statisticsGatheringService = new StatisticsGatheringService<>(this, deviceContext);
+        statisticsGatheringOnTheFlyService = new StatisticsGatheringOnTheFlyService<>(this,
+            deviceContext, convertorExecutor, statisticsWriterProvider);
         itemLifeCycleListener = new ItemLifecycleListenerImpl(deviceContext);
         statListForCollectingInitialization();
         this.state = CONTEXT_STATE.INITIALIZATION;
         this.deviceInfo = deviceInfo;
         this.myManager = myManager;
         this.lastDataGathering = null;
+        this.statisticsWriterProvider = statisticsWriterProvider;
     }
 
     @Override
@@ -275,7 +281,7 @@ class StatisticsContextImpl implements StatisticsContext {
     private void statChainFuture(final Iterator<MultipartType> iterator, final SettableFuture<Boolean> resultFuture, final boolean initial) {
         if (ConnectionContext.CONNECTION_STATE.RIP.equals(deviceContext.getPrimaryConnectionContext().getConnectionState())) {
             final String errMsg = String.format("Device connection is closed for Node : %s.",
-                    getDeviceInfo().getNodeId());
+                getDeviceInfo().getNodeId());
             LOG.debug(errMsg);
             resultFuture.setException(new ConnectionException(errMsg));
             return;
@@ -306,7 +312,7 @@ class StatisticsContextImpl implements StatisticsContext {
      * Method checks a device state. It returns null for be able continue. Otherwise it returns immediateFuture
      * which has to be returned from caller too
      *
-     * @return
+     * @return future
      */
     @VisibleForTesting
     ListenableFuture<Boolean> deviceConnectionCheck() {
@@ -315,7 +321,7 @@ class StatisticsContextImpl implements StatisticsContext {
             switch (deviceContext.getPrimaryConnectionContext().getConnectionState()) {
                 case RIP:
                     final String errMsg = String.format("Device connection doesn't exist anymore. Primary connection status : %s",
-                            deviceContext.getPrimaryConnectionContext().getConnectionState());
+                        deviceContext.getPrimaryConnectionContext().getConnectionState());
                     resultingFuture = Futures.immediateFailedFuture(new Throwable(errMsg));
                     break;
                 default:
@@ -330,92 +336,107 @@ class StatisticsContextImpl implements StatisticsContext {
     //TODO: Refactor twice sending deviceContext into gatheringStatistics
     private ListenableFuture<Boolean> collectFlowStatistics(final MultipartType multipartType, final boolean initial) {
         return devState.isFlowStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
-                statisticsGatheringOnTheFlyService,
-                getDeviceInfo(),
-                /*MultipartType.OFPMPFLOW*/ multipartType,
-                deviceContext,
-                deviceContext,
-                initial, multipartReplyTranslator) : emptyFuture;
+            statisticsGatheringOnTheFlyService,
+            getDeviceInfo(),
+            /*MultipartType.OFPMPFLOW*/ multipartType,
+            deviceContext,
+            deviceContext,
+            initial,
+            convertorExecutor,
+            statisticsWriterProvider) : emptyFuture;
     }
 
     private ListenableFuture<Boolean> collectTableStatistics(final MultipartType multipartType) {
         return devState.isTableStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
-                statisticsGatheringService,
-                getDeviceInfo(),
+            statisticsGatheringService,
+            getDeviceInfo(),
                 /*MultipartType.OFPMPTABLE*/ multipartType,
-                deviceContext,
-                deviceContext,
-                false, multipartReplyTranslator) : emptyFuture;
+            deviceContext,
+            deviceContext,
+            false,
+            convertorExecutor,
+            statisticsWriterProvider) : emptyFuture;
     }
 
     private ListenableFuture<Boolean> collectPortStatistics(final MultipartType multipartType) {
         return devState.isPortStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
-                statisticsGatheringService,
-                getDeviceInfo(),
+            statisticsGatheringService,
+            getDeviceInfo(),
                 /*MultipartType.OFPMPPORTSTATS*/ multipartType,
-                deviceContext,
-                deviceContext,
-                false, multipartReplyTranslator) : emptyFuture;
+            deviceContext,
+            deviceContext,
+            false,
+            convertorExecutor,
+            statisticsWriterProvider) : emptyFuture;
     }
 
     private ListenableFuture<Boolean> collectQueueStatistics(final MultipartType multipartType) {
         return !devState.isQueueStatisticsAvailable() ? emptyFuture : StatisticsGatheringUtils.gatherStatistics(
-                statisticsGatheringService,
-                getDeviceInfo(),
+            statisticsGatheringService,
+            getDeviceInfo(),
                 /*MultipartType.OFPMPQUEUE*/ multipartType,
-                deviceContext,
-                deviceContext,
-                false, multipartReplyTranslator);
+            deviceContext,
+            deviceContext,
+            false,
+            convertorExecutor,
+            statisticsWriterProvider);
     }
 
     private ListenableFuture<Boolean> collectGroupDescStatistics(final MultipartType multipartType) {
         return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics(
-                statisticsGatheringService,
-                getDeviceInfo(),
+            statisticsGatheringService,
+            getDeviceInfo(),
                 /*MultipartType.OFPMPGROUPDESC*/ multipartType,
-                deviceContext,
-                deviceContext,
-                false, multipartReplyTranslator) : emptyFuture;
+            deviceContext,
+            deviceContext,
+            false,
+            convertorExecutor,
+            statisticsWriterProvider) : emptyFuture;
     }
 
     private ListenableFuture<Boolean> collectGroupStatistics(final MultipartType multipartType) {
         return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics(
-                statisticsGatheringService,
-                getDeviceInfo(),
+            statisticsGatheringService,
+            getDeviceInfo(),
                 /*MultipartType.OFPMPGROUP*/ multipartType,
-                deviceContext,
-                deviceContext,
-                false, multipartReplyTranslator) : emptyFuture;
+            deviceContext,
+            deviceContext,
+            false,
+            convertorExecutor,
+            statisticsWriterProvider) : emptyFuture;
     }
 
     private ListenableFuture<Boolean> collectMeterConfigStatistics(final MultipartType multipartType) {
         return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics(
-                statisticsGatheringService,
-                getDeviceInfo(),
+            statisticsGatheringService,
+            getDeviceInfo(),
                 /*MultipartType.OFPMPMETERCONFIG*/ multipartType,
-                deviceContext,
-                deviceContext,
-                false, multipartReplyTranslator) : emptyFuture;
+            deviceContext,
+            deviceContext,
+            false,
+            convertorExecutor,
+            statisticsWriterProvider) : emptyFuture;
     }
 
     private ListenableFuture<Boolean> collectMeterStatistics(final MultipartType multipartType) {
         return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics(
-                statisticsGatheringService,
-                getDeviceInfo(),
+            statisticsGatheringService,
+            getDeviceInfo(),
                 /*MultipartType.OFPMPMETER*/ multipartType,
-                deviceContext,
-                deviceContext,
-                false, multipartReplyTranslator) : emptyFuture;
+            deviceContext,
+            deviceContext,
+            false,
+            convertorExecutor,
+            statisticsWriterProvider) : emptyFuture;
     }
 
     @VisibleForTesting
-    void setStatisticsGatheringService(final StatisticsGatheringService statisticsGatheringService) {
+    void setStatisticsGatheringService(final StatisticsGatheringService<T> statisticsGatheringService) {
         this.statisticsGatheringService = statisticsGatheringService;
     }
 
     @VisibleForTesting
-    void setStatisticsGatheringOnTheFlyService(final StatisticsGatheringOnTheFlyService
-                                                             statisticsGatheringOnTheFlyService) {
+    void setStatisticsGatheringOnTheFlyService(final StatisticsGatheringOnTheFlyService<T> statisticsGatheringOnTheFlyService) {
         this.statisticsGatheringOnTheFlyService = statisticsGatheringOnTheFlyService;
     }
 
@@ -500,7 +521,7 @@ class StatisticsContextImpl implements StatisticsContext {
             }
 
             @Override
-            public void onFailure(Throwable throwable) {
+            public void onFailure(@Nonnull Throwable throwable) {
                 LOG.warn("Initial gathering statistics unsuccessful for node {}", deviceInfo.getLOGValue());
                 lifecycleService.closeConnection();
             }
@@ -517,4 +538,4 @@ class StatisticsContextImpl implements StatisticsContext {
     public void setInitialSubmitHandler(final ClusterInitializationPhaseHandler initialSubmitHandler) {
         this.initialSubmitHandler = initialSubmitHandler;
     }
-}
\ No newline at end of file
+}
index e0dd990709409adce8828531d92d5cf0364ed19c..2704e06c1759fdc021d25f2e63b717ce4b04debb 100644 (file)
@@ -10,117 +10,60 @@ package org.opendaylight.openflowplugin.impl.statistics;
 
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
-import com.google.common.collect.Iterables;
 import com.google.common.util.concurrent.AsyncFunction;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.FutureFallback;
 import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.JdkFutureAdapters;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.text.SimpleDateFormat;
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainClosedException;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceRegistry;
 import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
-import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
-import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
-import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
 import org.opendaylight.openflowplugin.api.openflow.registry.group.DeviceGroupRegistry;
 import org.opendaylight.openflowplugin.api.openflow.registry.meter.DeviceMeterRegistry;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.StatisticsGatherer;
-import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
 import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.EventsTimeCounter;
+import org.opendaylight.openflowplugin.impl.common.MultipartReplyTranslatorUtil;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
 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.FlowCapableStatisticsGatheringStatus;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableStatisticsGatheringStatusBuilder;
-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.snapshot.gathering.status.grouping.SnapshotGatheringStatusEnd;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.snapshot.gathering.status.grouping.SnapshotGatheringStatusEndBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.snapshot.gathering.status.grouping.SnapshotGatheringStatusStartBuilder;
 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.FlowStatisticsData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsDataBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdate;
-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.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.FlowTableStatisticsUpdate;
-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.group.statistics.rev131111.GroupDescStatsUpdated;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdated;
-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.statistics.GroupStatistics;
-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.GroupId;
-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.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.MeterConfigStatsUpdated;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterStatisticsUpdated;
-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.nodes.node.meter.MeterStatistics;
-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.MeterId;
-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.openflow.common.types.rev130731.MultipartType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdate;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatistics;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatisticsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.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.QueueStatisticsUpdate;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.flow.capable.node.connector.queue.statistics.FlowCapableNodeConnectorQueueStatistics;
-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.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Utils for gatherig statistics
+ * Utils for gathering statistics
  */
 public final class StatisticsGatheringUtils {
 
-    private static String DATE_AND_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
-
+    private static final String DATE_AND_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
     private static final Logger LOG = LoggerFactory.getLogger(StatisticsGatheringUtils.class);
     private static final String QUEUE2_REQCTX = "QUEUE2REQCTX-";
 
@@ -128,363 +71,196 @@ public final class StatisticsGatheringUtils {
         throw new IllegalStateException("This class should not be instantiated.");
     }
 
-    //TODO: Flow-,Group- and Meter- registry should be not in device context, consider move it in separate class
-    static ListenableFuture<Boolean> gatherStatistics(final StatisticsGatherer statisticsGatheringService,
-                                                      final DeviceInfo deviceInfo,
-                                                      final MultipartType type,
-                                                      final TxFacade txFacade,
-                                                      final DeviceRegistry registry,
-                                                      final Boolean initial,
-                                                      final SinglePurposeMultipartReplyTranslator multipartReplyTranslator) {
-        EventIdentifier wholeProcessEventIdentifier = null;
+    static <T extends OfHeader>ListenableFuture<Boolean> gatherStatistics(final StatisticsGatherer<T> statisticsGatheringService,
+                                                                          final DeviceInfo deviceInfo,
+                                                                          final MultipartType type,
+                                                                          final TxFacade txFacade,
+                                                                          final DeviceRegistry registry,
+                                                                          final Boolean initial,
+                                                                          final ConvertorExecutor convertorExecutor,
+                                                                          final MultipartWriterProvider statisticsWriterProvider) {
+
+        final EventIdentifier eventIdentifier;
         if (MultipartType.OFPMPFLOW.equals(type)) {
-            wholeProcessEventIdentifier = new EventIdentifier(type.toString(), deviceInfo.getNodeId().getValue());
-            EventsTimeCounter.markStart(wholeProcessEventIdentifier);
+            eventIdentifier = new EventIdentifier(type.toString(), deviceInfo.getNodeId().getValue());
+            EventsTimeCounter.markStart(eventIdentifier);
+        } else {
+            eventIdentifier = null;
         }
-        final EventIdentifier ofpQueuToRequestContextEventIdentifier = new EventIdentifier(QUEUE2_REQCTX + type.toString(), deviceInfo.getNodeId().toString());
-        final ListenableFuture<RpcResult<List<MultipartReply>>> statisticsDataInFuture =
-                JdkFutureAdapters.listenInPoolThread(statisticsGatheringService.getStatisticsOfType(
-                        ofpQueuToRequestContextEventIdentifier, type));
-        return transformAndStoreStatisticsData(statisticsDataInFuture, deviceInfo, wholeProcessEventIdentifier, type, txFacade, registry, initial, multipartReplyTranslator);
-    }
 
-    private static ListenableFuture<Boolean> transformAndStoreStatisticsData(final ListenableFuture<RpcResult<List<MultipartReply>>> statisticsDataInFuture,
-                                                                             final DeviceInfo deviceInfo,
-                                                                             final EventIdentifier eventIdentifier,
-                                                                             final MultipartType type,
-                                                                             final TxFacade txFacade,
-                                                                             final DeviceRegistry registry,
-                                                                             final boolean initial,
-                                                                             final SinglePurposeMultipartReplyTranslator multipartReplyTranslator) {
-        return Futures.transform(statisticsDataInFuture, new AsyncFunction<RpcResult<List<MultipartReply>>, Boolean>() {
-            @Nullable
-            @Override
-            public ListenableFuture<Boolean> apply(final RpcResult<List<MultipartReply>> rpcResult) {
-                boolean isMultipartProcessed = Boolean.TRUE;
-                if (rpcResult.isSuccessful()) {
-                    LOG.debug("Stats reply successfully received for node {} of type {}", deviceInfo.getNodeId(), type);
-
-                    // TODO: in case the result value is null then multipart data probably got processed on the fly -
-                    // TODO: this contract should by clearly stated and enforced - now simple true value is returned
-                    if (null != rpcResult.getResult()) {
-                        Iterable<? extends DataObject> allMultipartData = Collections.emptyList();
-                        DataObject multipartData = null;
-
-
-                        try {
-                            for (final MultipartReply singleReply : rpcResult.getResult()) {
-                                final List<? extends DataObject> multipartDataList = multipartReplyTranslator.translate(
-                                        deviceInfo.getDatapathId(),
-                                        deviceInfo.getVersion(), singleReply);
-                                multipartData = multipartDataList.get(0);
-                                allMultipartData = Iterables.concat(allMultipartData, multipartDataList);
+        return Futures.transform(
+            statisticsGatheringService.getStatisticsOfType(
+                new EventIdentifier(QUEUE2_REQCTX + type.toString(), deviceInfo.getNodeId().toString()),
+                type),
+            new AsyncFunction<RpcResult<List<T>>, Boolean>() {
+                @Nullable
+                @Override
+                public ListenableFuture<Boolean> apply(@Nonnull final RpcResult<List<T>> rpcResult) {
+                    boolean isMultipartProcessed = Boolean.TRUE;
+
+                    if (rpcResult.isSuccessful()) {
+                        LOG.debug("Stats reply successfully received for node {} of type {}", deviceInfo.getNodeId(), type);
+
+                        // TODO: in case the result value is null then multipart data probably got processed on the fly -
+                        // TODO: this contract should by clearly stated and enforced - now simple true value is returned
+                        if (Objects.nonNull(rpcResult.getResult()) && !rpcResult.getResult().isEmpty()) {
+                            final List<DataContainer> allMultipartData;
+
+                            try {
+                                allMultipartData = rpcResult
+                                    .getResult()
+                                    .stream()
+                                    .map(reply ->  MultipartReplyTranslatorUtil
+                                        .translate(reply, deviceInfo, convertorExecutor, null))
+                                    .filter(java.util.Optional::isPresent)
+                                    .map(java.util.Optional::get)
+                                    .collect(Collectors.toList());
+                            } catch (final Exception e) {
+                                LOG.warn("Stats processing of type {} for node {} failed during transformation step",
+                                    type, deviceInfo.getLOGValue(), e);
+                                return Futures.immediateFailedFuture(e);
                             }
-                        } catch (final Exception e) {
-                            LOG.warn("stats processing of type {} for node {} failed during transfomation step",
-                                    type, deviceInfo.getNodeId(), e);
-                            return Futures.immediateFailedFuture(e);
-                        }
 
-
-                        try {
-                            if (multipartData instanceof GroupStatisticsUpdated) {
-                                processGroupStatistics((Iterable<GroupStatisticsUpdated>) allMultipartData, deviceInfo, txFacade);
-                            } else if (multipartData instanceof MeterStatisticsUpdated) {
-                                processMetersStatistics((Iterable<MeterStatisticsUpdated>) allMultipartData, deviceInfo, txFacade);
-                            } else if (multipartData instanceof NodeConnectorStatisticsUpdate) {
-                                processNodeConnectorStatistics((Iterable<NodeConnectorStatisticsUpdate>) allMultipartData, deviceInfo, txFacade);
-                            } else if (multipartData instanceof FlowTableStatisticsUpdate) {
-                                processFlowTableStatistics((Iterable<FlowTableStatisticsUpdate>) allMultipartData, deviceInfo, txFacade);
-                            } else if (multipartData instanceof QueueStatisticsUpdate) {
-                                processQueueStatistics((Iterable<QueueStatisticsUpdate>) allMultipartData, deviceInfo, txFacade);
-                            } else if (multipartData instanceof FlowsStatisticsUpdate) {
-                                /* FlowStat Processing is realized by NettyThread only by initPhase, otherwise it is realized
-                                 * by MD-SAL thread */
-                                return processFlowStatistics((Iterable<FlowsStatisticsUpdate>) allMultipartData, deviceInfo, txFacade, registry.getDeviceFlowRegistry(), initial, eventIdentifier);
-
-                            } else if (multipartData instanceof GroupDescStatsUpdated) {
-                                processGroupDescStats((Iterable<GroupDescStatsUpdated>) allMultipartData, deviceInfo, txFacade, registry.getDeviceGroupRegistry());
-                            } else if (multipartData instanceof MeterConfigStatsUpdated) {
-                                processMeterConfigStatsUpdated((Iterable<MeterConfigStatsUpdated>) allMultipartData, deviceInfo, txFacade, registry.getDeviceMeterRegistry());
-                            } else {
-                                isMultipartProcessed = Boolean.FALSE;
-                            }
-                        } catch (final Exception e) {
-                            LOG.warn("stats processing of type {} for node {} failed during write-to-tx step",
+                            try {
+                                return processStatistics(type, allMultipartData, txFacade, registry, deviceInfo,
+                                    statisticsWriterProvider,
+                                    eventIdentifier, initial);
+                            } catch (final Exception e) {
+                                LOG.warn("Stats processing of type {} for node {} failed during processing step",
                                     type, deviceInfo.getNodeId(), e);
-                            return Futures.immediateFailedFuture(e);
+                                return Futures.immediateFailedFuture(e);
+                            }
+                        } else {
+                            LOG.debug("Stats reply was empty for node {} of type {}", deviceInfo.getNodeId(), type);
                         }
-
-                        LOG.debug("Stats reply added to transaction for node {} of type {}", deviceInfo.getNodeId(), type);
-
-                        //TODO : implement experimenter
                     } else {
-                        LOG.debug("Stats reply was empty for node {} of type {}", deviceInfo.getNodeId(), type);
+                        LOG.warn("Stats reply FAILED for node {} of type {}: {}", deviceInfo.getNodeId(), type,
+                            rpcResult.getErrors());
+                        isMultipartProcessed = Boolean.FALSE;
                     }
 
-                } else {
-                    LOG.debug("Stats reply FAILED for node {} of type {}: {}", deviceInfo.getNodeId(), type, rpcResult.getErrors());
-                    isMultipartProcessed = Boolean.FALSE;
+                    return Futures.immediateFuture(isMultipartProcessed);
                 }
-                return Futures.immediateFuture(isMultipartProcessed);
-            }
-        });
+            });
     }
 
-    private static void processMeterConfigStatsUpdated(final Iterable<MeterConfigStatsUpdated> data,
-                                                       final DeviceInfo deviceInfo,
-                                                       final TxFacade txFacade,
-                                                       final DeviceMeterRegistry meterRegistry) throws Exception {
-        final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceInfo);
-        deleteAllKnownMeters(meterRegistry, fNodeIdent, txFacade);
-        for (final MeterConfigStatsUpdated meterConfigStatsUpdated : data) {
-            for (final MeterConfigStats meterConfigStats : meterConfigStatsUpdated.getMeterConfigStats()) {
-                final MeterId meterId = meterConfigStats.getMeterId();
-                final InstanceIdentifier<Meter> meterInstanceIdentifier = fNodeIdent.child(Meter.class, new MeterKey(meterId));
-
-                final MeterBuilder meterBuilder = new MeterBuilder(meterConfigStats);
-                meterBuilder.setKey(new MeterKey(meterId));
-                meterBuilder.addAugmentation(NodeMeterStatistics.class, new NodeMeterStatisticsBuilder().build());
-                meterRegistry.store(meterId);
-                txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, meterInstanceIdentifier, meterBuilder.build());
-            }
+    private static ListenableFuture<Boolean> processStatistics(final MultipartType type,
+                                                               final List<? extends DataContainer> statistics,
+                                                               final TxFacade txFacade,
+                                                               final DeviceRegistry deviceRegistry,
+                                                               final DeviceInfo deviceInfo,
+                                                               final MultipartWriterProvider statisticsWriterProvider,
+                                                               final EventIdentifier eventIdentifier,
+                                                               final boolean initial) {
+
+        ListenableFuture<Void> future = Futures.immediateFuture(null);
+
+        final InstanceIdentifier<FlowCapableNode> instanceIdentifier = deviceInfo
+            .getNodeInstanceIdentifier()
+            .augmentation(FlowCapableNode.class);
+
+        switch (type) {
+            case OFPMPFLOW:
+                future = deleteAllKnownFlows(txFacade, instanceIdentifier, initial);
+                break;
+            case OFPMPMETERCONFIG:
+                deleteAllKnownMeters(txFacade, instanceIdentifier, deviceRegistry.getDeviceMeterRegistry());
+                break;
+            case OFPMPGROUPDESC:
+                deleteAllKnownGroups(txFacade, instanceIdentifier, deviceRegistry.getDeviceGroupRegistry());
+                break;
         }
-        txFacade.submitTransaction();
-    }
 
-    private static ListenableFuture<Boolean> processFlowStatistics(final Iterable<FlowsStatisticsUpdate> data,
-                                                                   final DeviceInfo deviceInfo,
-                                                                   final TxFacade txFacade,
-                                                                   final DeviceFlowRegistry flowRegistry,
-                                                                   final boolean initial,
-                                                                   final EventIdentifier eventIdentifier) {
-        final ListenableFuture<Void> deleteFuture = initial ? Futures.immediateFuture(null) : deleteAllKnownFlows(deviceInfo,
-                flowRegistry, txFacade);
-        return Futures.transform(deleteFuture, new Function<Void, Boolean>() {
-
-            @Override
-            public Boolean apply(final Void input) {
-                writeFlowStatistics(data, deviceInfo, flowRegistry, txFacade);
+        return Futures.transform(future, (Function<Void, Boolean>) input -> {
+            if (writeStatistics(type, statistics, deviceInfo, statisticsWriterProvider)) {
                 txFacade.submitTransaction();
-                EventsTimeCounter.markEnd(eventIdentifier);
+
+                if (MultipartType.OFPMPFLOW.equals(type)) {
+                    EventsTimeCounter.markEnd(eventIdentifier);
+                }
+
+                LOG.debug("Stats reply added to transaction for node {} of type {}", deviceInfo.getNodeId(), type);
                 return Boolean.TRUE;
             }
+
+            LOG.warn("Stats processing of type {} for node {} failed during write-to-tx step", type, deviceInfo.getLOGValue());
+            return Boolean.FALSE;
         });
     }
 
-    public static void writeFlowStatistics(final Iterable<FlowsStatisticsUpdate> data,
-                                           final DeviceInfo deviceInfo,
-                                           final DeviceFlowRegistry registry,
-                                           final TxFacade txFacade) {
-        final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceInfo);
+    private static boolean writeStatistics(final MultipartType type,
+                                          final List<? extends DataContainer> statistics,
+                                          final DeviceInfo deviceInfo,
+                                          final MultipartWriterProvider statisticsWriterProvider) {
+        final AtomicBoolean result = new AtomicBoolean(false);
+
         try {
-            for (final FlowsStatisticsUpdate flowsStatistics : data) {
-                for (final FlowAndStatisticsMapList flowStat : flowsStatistics.getFlowAndStatisticsMapList()) {
-                    final FlowBuilder flowBuilder = new FlowBuilder(flowStat);
-                    flowBuilder.addAugmentation(FlowStatisticsData.class, refineFlowStatisticsAugmentation(flowStat).build());
-
-                    final short tableId = flowStat.getTableId();
-                    final FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(deviceInfo.getVersion(), flowBuilder.build());
-                    final FlowId flowId = registry.storeIfNecessary(flowRegistryKey);
-
-                    final FlowKey flowKey = new FlowKey(flowId);
-                    flowBuilder.setKey(flowKey);
-                    final TableKey tableKey = new TableKey(tableId);
-                    final InstanceIdentifier<Flow> flowIdent = fNodeIdent.child(Table.class, tableKey).child(Flow.class, flowKey);
-                    txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, flowIdent, flowBuilder.build());
+            statistics.forEach(stat -> statisticsWriterProvider.lookup(type).ifPresent(p -> {
+                final boolean write = p.write(stat, false);
+
+                if (!result.get()) {
+                    result.set(write);
                 }
-            }
-        } catch (Exception e) {
-            LOG.warn("Not able to write to transaction: {}", e.getMessage());
+            }));
+        } catch (final Exception ex) {
+            LOG.warn("Stats processing of type {} for node {} failed during write-to-tx step", type, deviceInfo.getLOGValue(), ex);
         }
-    }
 
-    /**
-     * Method extracts flow statistics out of flowAndStatistics model
-     *
-     * @param flowAndStats
-     */
-    private static FlowStatisticsDataBuilder refineFlowStatisticsAugmentation(final FlowAndStatisticsMapList flowAndStats) {
-        final FlowStatisticsBuilder flowStatisticsBuilder = new FlowStatisticsBuilder(flowAndStats);
-        final FlowStatisticsDataBuilder flowStatisticsDataBld = new FlowStatisticsDataBuilder();
-        flowStatisticsDataBld.setFlowStatistics(flowStatisticsBuilder.build());
-        return flowStatisticsDataBld;
+        return result.get();
     }
 
-    public static ListenableFuture<Void> deleteAllKnownFlows(final DeviceInfo deviceInfo,
-                                                             final DeviceFlowRegistry registry,
-                                                             final TxFacade txFacade) {
-        final InstanceIdentifier<FlowCapableNode> flowCapableNodePath = assembleFlowCapableNodeInstanceIdentifier(deviceInfo);
-        final ReadOnlyTransaction readTx = txFacade.getReadTransaction();
-        final CheckedFuture<Optional<FlowCapableNode>, ReadFailedException> flowCapableNodeFuture = readTx.read(
-                LogicalDatastoreType.OPERATIONAL, flowCapableNodePath);
-
-        /* we wish to close readTx for fallBack */
-        Futures.withFallback(flowCapableNodeFuture, new FutureFallback<Optional<FlowCapableNode>>() {
+    public static ListenableFuture<Void> deleteAllKnownFlows(final TxFacade txFacade,
+                                                             final InstanceIdentifier<FlowCapableNode> instanceIdentifier,
+                                                             final boolean initial) {
+        if (initial) {
+            return Futures.immediateFuture(null);
+        }
 
-            @Override
-            public ListenableFuture<Optional<FlowCapableNode>> create(final Throwable t) throws Exception {
+        final ReadOnlyTransaction readTx = txFacade.getReadTransaction();
+        return Futures.transform(Futures
+            .withFallback(readTx.read(LogicalDatastoreType.OPERATIONAL, instanceIdentifier), t -> {
+                // we wish to close readTx for fallBack
                 readTx.close();
                 return Futures.immediateFailedFuture(t);
-            }
-        });
-        /*
-         * we have to read actual tables with all information before we set empty Flow list, merge is expensive and
-         * not applicable for lists
-         */
-        return Futures.transform(flowCapableNodeFuture, new AsyncFunction<Optional<FlowCapableNode>, Void>() {
-
-            @Override
-            public ListenableFuture<Void> apply(final Optional<FlowCapableNode> flowCapNodeOpt) throws Exception {
-                if (flowCapNodeOpt.isPresent()) {
+            }), (Function<Optional<FlowCapableNode>, Void>)
+            flowCapNodeOpt -> {
+                // we have to read actual tables with all information before we set empty Flow list, merge is expensive and
+                // not applicable for lists
+                if (flowCapNodeOpt != null && flowCapNodeOpt.isPresent()) {
                     for (final Table tableData : flowCapNodeOpt.get().getTable()) {
-                        final Table table = new TableBuilder(tableData).setFlow(Collections.<Flow>emptyList()).build();
-                        final InstanceIdentifier<Table> iiToTable = flowCapableNodePath.child(Table.class, tableData.getKey());
+                        final Table table = new TableBuilder(tableData).setFlow(Collections.emptyList()).build();
+                        final InstanceIdentifier<Table> iiToTable = instanceIdentifier.child(Table.class, tableData.getKey());
                         txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, iiToTable, table);
                     }
                 }
-                readTx.close();
-                return Futures.immediateFuture(null);
-            }
 
-        });
-    }
-
-    private static void processQueueStatistics(final Iterable<QueueStatisticsUpdate> data, final DeviceInfo deviceInfo, final TxFacade txFacade) throws Exception {
-        // TODO: clean all queues of all node-connectors before writing up-to-date stats
-        final InstanceIdentifier<Node> nodeIdent = deviceInfo.getNodeInstanceIdentifier();
-        for (final QueueStatisticsUpdate queueStatisticsUpdate : data) {
-            for (final QueueIdAndStatisticsMap queueStat : queueStatisticsUpdate.getQueueIdAndStatisticsMap()) {
-                if (queueStat.getQueueId() != null) {
-                    final FlowCapableNodeConnectorQueueStatistics statChild =
-                            new FlowCapableNodeConnectorQueueStatisticsBuilder(queueStat).build();
-                    final FlowCapableNodeConnectorQueueStatisticsDataBuilder statBuild =
-                            new FlowCapableNodeConnectorQueueStatisticsDataBuilder();
-                    statBuild.setFlowCapableNodeConnectorQueueStatistics(statChild);
-                    final QueueKey qKey = new QueueKey(queueStat.getQueueId());
-                    final InstanceIdentifier<Queue> queueIdent = nodeIdent
-                            .child(NodeConnector.class, new NodeConnectorKey(queueStat.getNodeConnectorId()))
-                            .augmentation(FlowCapableNodeConnector.class)
-                            .child(Queue.class, qKey);
-                    final QueueBuilder queueBuilder = new QueueBuilder()
-                            .setKey(qKey)
-                            .setQueueId(queueStat.getQueueId())
-                            // node-connector-id is already contained in parent node and the port-id here is of incompatible format
-                            .addAugmentation(FlowCapableNodeConnectorQueueStatisticsData.class, statBuild.build());
-                    txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, queueIdent, queueBuilder.build());
-                }
-            }
-        }
-        txFacade.submitTransaction();
-    }
-
-    private static void processFlowTableStatistics(final Iterable<FlowTableStatisticsUpdate> data, final DeviceInfo deviceInfo, final TxFacade txFacade) throws Exception {
-        final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceInfo);
-        for (final FlowTableStatisticsUpdate flowTableStatisticsUpdate : data) {
-
-            for (final FlowTableAndStatisticsMap tableStat : flowTableStatisticsUpdate.getFlowTableAndStatisticsMap()) {
-                final InstanceIdentifier<FlowTableStatistics> tStatIdent = fNodeIdent.child(Table.class, new TableKey(tableStat.getTableId().getValue()))
-                        .augmentation(FlowTableStatisticsData.class).child(FlowTableStatistics.class);
-                final FlowTableStatistics stats = new FlowTableStatisticsBuilder(tableStat).build();
-                txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, tStatIdent, stats);
-            }
-        }
-        txFacade.submitTransaction();
-    }
-
-    private static void processNodeConnectorStatistics(final Iterable<NodeConnectorStatisticsUpdate> data, final DeviceInfo deviceInfo, final TxFacade txFacade) throws Exception {
-        final InstanceIdentifier<Node> nodeIdent = deviceInfo.getNodeInstanceIdentifier();
-        for (final NodeConnectorStatisticsUpdate nodeConnectorStatisticsUpdate : data) {
-            for (final NodeConnectorStatisticsAndPortNumberMap nConnectPort : nodeConnectorStatisticsUpdate.getNodeConnectorStatisticsAndPortNumberMap()) {
-                final FlowCapableNodeConnectorStatistics stats = new FlowCapableNodeConnectorStatisticsBuilder(nConnectPort).build();
-                final NodeConnectorKey key = new NodeConnectorKey(nConnectPort.getNodeConnectorId());
-                final InstanceIdentifier<NodeConnector> nodeConnectorIdent = nodeIdent.child(NodeConnector.class, key);
-                final InstanceIdentifier<FlowCapableNodeConnectorStatisticsData> nodeConnStatIdent = nodeConnectorIdent
-                        .augmentation(FlowCapableNodeConnectorStatisticsData.class);
-                final InstanceIdentifier<FlowCapableNodeConnectorStatistics> flowCapNodeConnStatIdent =
-                        nodeConnStatIdent.child(FlowCapableNodeConnectorStatistics.class);
-                txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, flowCapNodeConnStatIdent, stats);
-            }
-        }
-        txFacade.submitTransaction();
+                readTx.close();
+                return null;
+            });
     }
 
-    private static void processMetersStatistics(final Iterable<MeterStatisticsUpdated> data,
-                                                final DeviceInfo deviceInfo,
-                                                final TxFacade txFacade) throws Exception {
-        final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceInfo);
-        for (final MeterStatisticsUpdated meterStatisticsUpdated : data) {
-            for (final MeterStats mStat : meterStatisticsUpdated.getMeterStats()) {
-                final MeterStatistics stats = new MeterStatisticsBuilder(mStat).build();
-                final MeterId meterId = mStat.getMeterId();
-                final InstanceIdentifier<Meter> meterIdent = fNodeIdent.child(Meter.class, new MeterKey(meterId));
-                final InstanceIdentifier<NodeMeterStatistics> nodeMeterStatIdent = meterIdent
-                        .augmentation(NodeMeterStatistics.class);
-                final InstanceIdentifier<MeterStatistics> msIdent = nodeMeterStatIdent.child(MeterStatistics.class);
-                txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, msIdent, stats);
-            }
-        }
-        txFacade.submitTransaction();
-    }
+    private static void deleteAllKnownMeters(final TxFacade txFacade,
+                                             final InstanceIdentifier<FlowCapableNode> instanceIdentifier,
+                                             final DeviceMeterRegistry meterRegistry) {
+        meterRegistry.getAllMeterIds().forEach(meterId -> txFacade
+            .addDeleteToTxChain(
+                LogicalDatastoreType.OPERATIONAL,
+                instanceIdentifier.child(Meter.class, new MeterKey(meterId))));
 
-    private static void deleteAllKnownMeters(final DeviceMeterRegistry meterRegistry, final InstanceIdentifier<FlowCapableNode> fNodeIdent, final TxFacade txFacade) throws Exception {
-        for (final MeterId meterId : meterRegistry.getAllMeterIds()) {
-            final InstanceIdentifier<Meter> meterIdent = fNodeIdent.child(Meter.class, new MeterKey(meterId));
-            txFacade.addDeleteToTxChain(LogicalDatastoreType.OPERATIONAL, meterIdent);
-        }
         meterRegistry.removeMarked();
     }
 
-    private static void processGroupDescStats(final Iterable<GroupDescStatsUpdated> data, final DeviceInfo deviceInfo, final TxFacade txFacade, final DeviceGroupRegistry groupRegistry) throws Exception {
-        final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceInfo);
-        deleteAllKnownGroups(txFacade, fNodeIdent, groupRegistry);
-
-        for (final GroupDescStatsUpdated groupDescStatsUpdated : data) {
-            for (final GroupDescStats groupDescStats : groupDescStatsUpdated.getGroupDescStats()) {
-                final GroupId groupId = groupDescStats.getGroupId();
-
-                final GroupBuilder groupBuilder = new GroupBuilder(groupDescStats);
-                groupBuilder.setKey(new GroupKey(groupId));
-                groupBuilder.addAugmentation(NodeGroupStatistics.class, new NodeGroupStatisticsBuilder().build());
+    private static void deleteAllKnownGroups(final TxFacade txFacade,
+                                             final InstanceIdentifier<FlowCapableNode> instanceIdentifier,
+                                             final DeviceGroupRegistry groupRegistry) {
+        groupRegistry.getAllGroupIds().forEach(groupId -> txFacade
+            .addDeleteToTxChain(
+                LogicalDatastoreType.OPERATIONAL,
+                instanceIdentifier.child(Group.class, new GroupKey(groupId))));
 
-                final InstanceIdentifier<Group> groupIdent = fNodeIdent.child(Group.class, new GroupKey(groupId));
-
-                groupRegistry.store(groupId);
-                txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, groupIdent, groupBuilder.build());
-            }
-        }
-        txFacade.submitTransaction();
-    }
-
-    private static void deleteAllKnownGroups(final TxFacade txFacade, final InstanceIdentifier<FlowCapableNode> fNodeIdent, final DeviceGroupRegistry groupRegistry) throws Exception {
-        for (final GroupId groupId : groupRegistry.getAllGroupIds()) {
-            final InstanceIdentifier<Group> groupIdent = fNodeIdent.child(Group.class, new GroupKey(groupId));
-            txFacade.addDeleteToTxChain(LogicalDatastoreType.OPERATIONAL, groupIdent);
-        }
         groupRegistry.removeMarked();
     }
 
-    private static void processGroupStatistics(final Iterable<GroupStatisticsUpdated> data, final DeviceInfo deviceInfo, final TxFacade txFacade) throws Exception {
-        final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceInfo);
-        for (final GroupStatisticsUpdated groupStatistics : data) {
-            for (final GroupStats groupStats : groupStatistics.getGroupStats()) {
-
-                final InstanceIdentifier<Group> groupIdent = fNodeIdent.child(Group.class, new GroupKey(groupStats.getGroupId()));
-                final InstanceIdentifier<NodeGroupStatistics> nGroupStatIdent = groupIdent
-                        .augmentation(NodeGroupStatistics.class);
-
-                final InstanceIdentifier<GroupStatistics> gsIdent = nGroupStatIdent.child(GroupStatistics.class);
-                final GroupStatistics stats = new GroupStatisticsBuilder(groupStats).build();
-                txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, gsIdent, stats);
-            }
-        }
-        txFacade.submitTransaction();
-    }
-
-    private static InstanceIdentifier<FlowCapableNode> assembleFlowCapableNodeInstanceIdentifier(final DeviceInfo deviceInfo) {
-        return deviceInfo.getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
-    }
-
     /**
      * Writes snapshot gathering start timestamp + cleans end mark
      *
@@ -492,15 +268,15 @@ public final class StatisticsGatheringUtils {
      */
     static void markDeviceStateSnapshotStart(final DeviceContext deviceContext) {
         final InstanceIdentifier<FlowCapableStatisticsGatheringStatus> statusPath = deviceContext.getDeviceInfo()
-                .getNodeInstanceIdentifier().augmentation(FlowCapableStatisticsGatheringStatus.class);
+            .getNodeInstanceIdentifier().augmentation(FlowCapableStatisticsGatheringStatus.class);
 
         final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_AND_TIME_FORMAT);
         final FlowCapableStatisticsGatheringStatus gatheringStatus = new FlowCapableStatisticsGatheringStatusBuilder()
-                .setSnapshotGatheringStatusStart(new SnapshotGatheringStatusStartBuilder()
-                        .setBegin(new DateAndTime(simpleDateFormat.format(new Date())))
-                        .build())
-                .setSnapshotGatheringStatusEnd(null) // TODO: reconsider if really need to clean end mark here
-                .build();
+            .setSnapshotGatheringStatusStart(new SnapshotGatheringStatusStartBuilder()
+                .setBegin(new DateAndTime(simpleDateFormat.format(new Date())))
+                .build())
+            .setSnapshotGatheringStatusEnd(null) // TODO: reconsider if really need to clean end mark here
+            .build();
         try {
             deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, statusPath, gatheringStatus);
         } catch (final TransactionChainClosedException e) {
@@ -519,14 +295,14 @@ public final class StatisticsGatheringUtils {
      */
     static void markDeviceStateSnapshotEnd(final DeviceContext deviceContext, final boolean succeeded) {
         final InstanceIdentifier<SnapshotGatheringStatusEnd> statusEndPath = deviceContext.getDeviceInfo()
-                .getNodeInstanceIdentifier().augmentation(FlowCapableStatisticsGatheringStatus.class)
-                .child(SnapshotGatheringStatusEnd.class);
+            .getNodeInstanceIdentifier().augmentation(FlowCapableStatisticsGatheringStatus.class)
+            .child(SnapshotGatheringStatusEnd.class);
 
         final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_AND_TIME_FORMAT);
         final SnapshotGatheringStatusEnd gatheringStatus = new SnapshotGatheringStatusEndBuilder()
-                .setEnd(new DateAndTime(simpleDateFormat.format(new Date())))
-                .setSucceeded(succeeded)
-                .build();
+            .setEnd(new DateAndTime(simpleDateFormat.format(new Date())))
+            .setSucceeded(succeeded)
+            .build();
         try {
             deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, statusEndPath, gatheringStatus);
         } catch (TransactionChainClosedException e) {
index 7127bb5eda639aa46f17513956ff77511d0639a1..3a67890bae97aed0672b39637e12b1eea46db619 100644 (file)
@@ -15,6 +15,9 @@ import com.google.common.collect.Iterators;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import io.netty.util.HashedWheelTimer;
+import io.netty.util.Timeout;
+import io.netty.util.TimerTask;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Optional;
@@ -38,7 +41,10 @@ import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
 import org.opendaylight.openflowplugin.api.openflow.rpc.ItemLifeCycleSource;
 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProviderFactory;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.ChangeStatisticsWorkModeInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.GetStatisticsWorkModeOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.GetStatisticsWorkModeOutputBuilder;
@@ -49,9 +55,6 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import io.netty.util.HashedWheelTimer;
-import io.netty.util.Timeout;
-import io.netty.util.TimerTask;
 
 public class StatisticsManagerImpl implements StatisticsManager, StatisticsManagerControlService {
 
@@ -59,7 +62,6 @@ public class StatisticsManagerImpl implements StatisticsManager, StatisticsManag
 
     private static final long DEFAULT_STATS_TIMEOUT_SEC = 50L;
     private final ConvertorExecutor converterExecutor;
-
     private DeviceInitializationPhaseHandler deviceInitPhaseHandler;
     private DeviceTerminationPhaseHandler deviceTerminationPhaseHandler;
 
@@ -103,13 +105,26 @@ public class StatisticsManagerImpl implements StatisticsManager, StatisticsManag
     public void onDeviceContextLevelUp(final DeviceInfo deviceInfo,
                                        final LifecycleService lifecycleService) throws Exception {
 
+        final MultipartWriterProvider statisticsWriterProvider = MultipartWriterProviderFactory
+            .createDefaultProvider(lifecycleService.getDeviceContext());
+
         final StatisticsContext statisticsContext =
-                new StatisticsContextImpl(
-                        deviceInfo,
-                        isStatisticsPollingOn,
-                        lifecycleService,
-                        converterExecutor,
-                        this);
+            lifecycleService.getDeviceContext().canUseSingleLayerSerialization() ?
+                new StatisticsContextImpl<MultipartReply>(
+                    deviceInfo,
+                    isStatisticsPollingOn,
+                    lifecycleService,
+                    converterExecutor,
+                    this,
+                    statisticsWriterProvider) :
+                new StatisticsContextImpl<org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
+                    .MultipartReply>(
+                    deviceInfo,
+                    isStatisticsPollingOn,
+                    lifecycleService,
+                    converterExecutor,
+                    this,
+                    statisticsWriterProvider);
 
         Verify.verify(
                 contexts.putIfAbsent(deviceInfo, statisticsContext) == null,
index 5d8fa400d71cee9467a0f7cb627956ca89afe1e8..73554ee59bf2d6e339f58e63640822432e05c723 100644 (file)
@@ -17,8 +17,8 @@ import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.AbstractCompatibleStatService;
 import org.opendaylight.openflowplugin.openflow.md.util.FlowCreatorUtil;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsUpdate;
index c466f1dde37cbbef8bb7981f716cc2dae517c368..315c0799f95e2910e6000ea12b65e7937e9169cf 100644 (file)
@@ -13,8 +13,8 @@ import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.AbstractCompatibleStatService;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.FlowStatisticsToNotificationTransformer;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
index ca24e480074629a953971229f135d8c4c6d88137..19aa517cdd432d175f0d81c4a2c04784dd450e42 100644 (file)
@@ -13,8 +13,8 @@ import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.AbstractCompatibleStatService;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.FlowStatisticsToNotificationTransformer;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
index 55e3368ddf5ca40c1978969c9303c19f3ab24ed6..547085fb082b64fd00f5751f841dbf4f11e4902d 100644 (file)
@@ -13,8 +13,8 @@ import org.opendaylight.openflowjava.protocol.api.util.BinContent;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.AbstractCompatibleStatService;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.GroupStatisticsToNotificationTransformer;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
index bb72f11925cf4ba1b25d31c7b0a2c08b53d1f421..278df7c692e476af2e89a333f824fb4b1fa03e79 100644 (file)
@@ -15,8 +15,8 @@ import org.opendaylight.openflowjava.protocol.api.util.BinContent;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.AbstractCompatibleStatService;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData;
@@ -98,4 +98,4 @@ final class AllMeterConfigStatsService
 
         return message.build();
     }
-}
\ No newline at end of file
+}
index ef80529f9c7addbc4b55354de4a2aab01cb37eb4..cb99ea6f92285045e1ba4e261d05def2627ffc6f 100644 (file)
@@ -13,8 +13,8 @@ import org.opendaylight.openflowjava.protocol.api.util.BinContent;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.AbstractCompatibleStatService;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.MeterStatisticsToNotificationTransformer;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
index 393dc43b95770831a678a663162048110ea60cd4..b43925b9c39b84cb0dfb726ec983ff3dba5a5e98 100644 (file)
@@ -13,8 +13,8 @@ import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.AbstractCompatibleStatService;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.NodeConnectorStatisticsToNotificationTransformer;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
index 054a99ac36cd77121ac77774005f9c2895afeb7b..60686c97c9ffabfea83a7a5944d590c5122ec452 100644 (file)
@@ -13,8 +13,8 @@ import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.AbstractCompatibleStatService;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.QueueStatisticsToNotificationTransformer;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
index 0372c699f822fd734724279a1969e7ab7c74730a..e73411ce28b85b370db9246805ddc5877ea471ac 100644 (file)
@@ -14,8 +14,8 @@ import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.AbstractCompatibleStatService;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.QueueStatisticsToNotificationTransformer;
 import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
index 58f5c45df8f43350a9fd8dbe9a13ce29b6268e32..a875c0d6e316a5785becf5cb4b40806b599778e4 100644 (file)
@@ -13,8 +13,8 @@ import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.AbstractCompatibleStatService;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.FlowStatisticsToNotificationTransformer;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
index 2e6ca05a69debca42c280f22f6c1f7710ae119de..c1c79e44bf6d68dd6934253c4c455ed98861d3d6 100644 (file)
@@ -14,8 +14,8 @@ import java.util.concurrent.atomic.AtomicLong;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.AbstractCompatibleStatService;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData;
index 80dfc7bb8b17b34182be4ca1b83979a1bb016f53..fbd98649e1701676b41b86c4dd23daafae89c94a 100644 (file)
@@ -15,8 +15,8 @@ import java.util.concurrent.atomic.AtomicLong;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.AbstractCompatibleStatService;
 import org.opendaylight.openflowplugin.impl.util.GroupUtil;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
index ce95e5f75e0fb9246a044cc9e819a6c4f63eafea..1ffb55533adafec42023174dd2ee5129b56228fe 100644 (file)
@@ -12,8 +12,8 @@ import java.util.concurrent.atomic.AtomicLong;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.AbstractCompatibleStatService;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.GroupStatisticsToNotificationTransformer;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
index cd97a7364b39d126be87c11cd65c62d6e527b22d..f41e1a72f39a32323757962b0a17446e4814cbc0 100644 (file)
@@ -15,8 +15,8 @@ import java.util.concurrent.atomic.AtomicLong;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.AbstractCompatibleStatService;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
index 2a0b96969f9e196f38d94f2319f2fc2a23427f6f..5a0d8ef2c815298097caceee31aae2810631c3e2 100644 (file)
@@ -12,8 +12,8 @@ import java.util.concurrent.atomic.AtomicLong;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.AbstractCompatibleStatService;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.MeterStatisticsToNotificationTransformer;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
index 12ebb39efc4f8165ebdbd0551bcce7712f7c9471..139f9b5d2027a6168b84bd9677526b890a7b0805 100644 (file)
@@ -13,8 +13,8 @@ import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.AbstractCompatibleStatService;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.QueueStatisticsToNotificationTransformer;
 import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
index 4d9a2b3ce16a452923cb6c7e0eca7d29b77265bc..79d621d9ede9d4fbb1e9df5f2ddf7161196b156b 100644 (file)
@@ -7,24 +7,18 @@
  */
 package org.opendaylight.openflowplugin.impl.statistics.services;
 
-import com.google.common.base.Function;
-import com.google.common.util.concurrent.Futures;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.concurrent.Future;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
-import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
-import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
 import org.opendaylight.openflowplugin.api.openflow.statistics.compatibility.Delegator;
+import org.opendaylight.openflowplugin.impl.services.multilayer.MultiLayerAggregateFlowMultipartService;
+import org.opendaylight.openflowplugin.impl.services.singlelayer.SingleLayerAggregateFlowMultipartService;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsFromFlowTableInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsFromFlowTableOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesInput;
@@ -32,54 +26,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.G
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableInput;
 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.statistics.rev130819.get.aggregate.flow.statistics.from.flow.table._for.given.match.output.AggregatedFlowStatistics;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyAggregateCase;
 import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
 /**
  * @author joe
  */
 public class OpendaylightFlowStatisticsServiceImpl implements OpendaylightFlowStatisticsService, Delegator<OpendaylightFlowStatisticsService> {
 
-    private final Function<RpcResult<List<MultipartReply>>, RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>> matchingConvertor =
-            new Function<RpcResult<List<MultipartReply>>, RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>>() {
-                @Override
-                public RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput> apply(final RpcResult<List<MultipartReply>> input) {
-                    final DeviceInfo deviceInfo = matchingFlowsInTable.getDeviceInfo();
-                    final RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput> rpcResult;
-                    if (input.isSuccessful()) {
-                        MultipartReply reply = input.getResult().get(0);
-                        final TranslatorKey translatorKey = new TranslatorKey(reply.getVersion(), MultipartReplyAggregateCase.class.getName());
-                        final MessageTranslator<MultipartReply, AggregatedFlowStatistics> messageTranslator = translatorLibrary.lookupTranslator(translatorKey);
-                        List<AggregatedFlowStatistics> aggregStats = new ArrayList<AggregatedFlowStatistics>();
-
-                        for (MultipartReply multipartReply : input.getResult()) {
-                            aggregStats.add(messageTranslator.translate(multipartReply, deviceInfo, null));
-                        }
-
-                        GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder getAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder =
-                                new GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder();
-                        getAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder.setAggregatedFlowStatistics(aggregStats);
-
-                        rpcResult = RpcResultBuilder
-                                .<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>success()
-                                .withResult(getAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder.build())
-                                .build();
-
-                    } else {
-                        rpcResult = RpcResultBuilder
-                                .<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>failed()
-                                .withRpcErrors(input.getErrors())
-                                .build();
-                    }
-                    return rpcResult;
-                }
-    };
-
-    private final MatchingFlowsInTableService matchingFlowsInTable;
-    private final TranslatorLibrary translatorLibrary;
+    private final SingleLayerAggregateFlowMultipartService singleLayerService;
+    private final MultiLayerAggregateFlowMultipartService multiLayerService;
     private OpendaylightFlowStatisticsService delegate;
 
     public static OpendaylightFlowStatisticsServiceImpl createWithOook(final RequestContextStack requestContextStack,
@@ -87,10 +42,14 @@ public class OpendaylightFlowStatisticsServiceImpl implements OpendaylightFlowSt
         return new OpendaylightFlowStatisticsServiceImpl(requestContextStack, deviceContext, deviceContext.oook(), convertorExecutor);
     }
 
-    public OpendaylightFlowStatisticsServiceImpl(final RequestContextStack requestContextStack, final DeviceContext deviceContext,
-                                                 final TranslatorLibrary translatorLibrary, final ConvertorExecutor convertorExecutor) {
-        matchingFlowsInTable = new MatchingFlowsInTableService(requestContextStack, deviceContext, convertorExecutor);
-        this.translatorLibrary = translatorLibrary;
+    public OpendaylightFlowStatisticsServiceImpl(final RequestContextStack requestContextStack,
+                                                 final DeviceContext deviceContext,
+                                                 final TranslatorLibrary translatorLibrary,
+                                                 final ConvertorExecutor convertorExecutor) {
+        singleLayerService = new SingleLayerAggregateFlowMultipartService(requestContextStack, deviceContext,
+            convertorExecutor);
+        multiLayerService = new MultiLayerAggregateFlowMultipartService(requestContextStack, deviceContext,
+            convertorExecutor, translatorLibrary);
     }
 
     @Override
@@ -115,7 +74,9 @@ public class OpendaylightFlowStatisticsServiceImpl implements OpendaylightFlowSt
     @Override
     public Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>> getAggregateFlowStatisticsFromFlowTableForGivenMatch(
             final GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput input) {
-        return Futures.transform(matchingFlowsInTable.handleServiceCall(input), matchingConvertor);
+        return singleLayerService.canUseSingleLayerSerialization()
+            ? singleLayerService.handleAndReply(input)
+            : multiLayerService.handleAndReply(input);
     }
 
     /**
index efc8e6fcb2e61e3c84c7c4373d50bd26c9431ab1..0f8ea8ae8365a2b3823ef10a3f2ac324824d6c30 100644 (file)
@@ -15,8 +15,8 @@ import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.AbstractCompatibleStatService;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64;
index 8355c96e0da1d6bd94a2027f5cc71220efa536b5..f4686c831bb15b65d2022a3875c1055182ae815b 100644 (file)
@@ -13,8 +13,8 @@ import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.AbstractCompatibleStatService;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.NodeConnectorStatisticsToNotificationTransformer;
 import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
index 1a5c5a1d5f3473d87f372a5c50b55885e46c2c4b..e0340bac59a7275218eda8f7f568aa3a5e68af04 100644 (file)
@@ -23,6 +23,7 @@ import org.opendaylight.openflowplugin.api.openflow.statistics.compatibility.Bac
 import org.opendaylight.openflowplugin.impl.services.AbstractMultipartService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.Notification;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
@@ -32,7 +33,7 @@ import org.slf4j.LoggerFactory;
 /**
  * pulled up common functionality of notification emitting stats services (backward compatibility relic)
  */
-public abstract class AbstractCompatibleStatService<I, O, N extends Notification> extends AbstractMultipartService<I> implements BackwardCompatibleAtomicService<I, O> {
+public abstract class AbstractCompatibleStatService<I extends DataContainer, O, N extends Notification> extends AbstractMultipartService<I, MultipartReply> implements BackwardCompatibleAtomicService<I, O> {
 
     private static final Logger LOG = LoggerFactory.getLogger(AbstractCompatibleStatService.class);
 
index a88e405b7c71372a3cb846253e2f7c52713c525f..4d944231e8a38e3ed716c52482263057707a46b6 100644 (file)
@@ -8,8 +8,8 @@
 
 package org.opendaylight.openflowplugin.impl.statistics.services.dedicated;
 
+import com.google.common.util.concurrent.ListenableFuture;
 import java.util.List;
-import java.util.concurrent.Future;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
@@ -17,11 +17,11 @@ import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.Event
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.StatisticsGatherer;
 import org.opendaylight.openflowplugin.impl.common.MultipartRequestInputFactory;
 import org.opendaylight.openflowplugin.impl.services.AbstractMultipartOnTheFlyService;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
 import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.EventsTimeCounter;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
@@ -30,16 +30,21 @@ import org.slf4j.LoggerFactory;
 /**
  * collects statistics and processes them on the fly
  */
-public class StatisticsGatheringOnTheFlyService extends AbstractMultipartOnTheFlyService<MultipartType> implements StatisticsGatherer {
+public class StatisticsGatheringOnTheFlyService<T extends OfHeader>
+    extends AbstractMultipartOnTheFlyService<MultipartType, T>
+    implements StatisticsGatherer<T> {
 
     private static final Logger LOG = LoggerFactory.getLogger(StatisticsGatheringOnTheFlyService.class);
 
-    public StatisticsGatheringOnTheFlyService(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final ConvertorExecutor convertorExecutor) {
-        super(requestContextStack, deviceContext, convertorExecutor);
+    public StatisticsGatheringOnTheFlyService(final RequestContextStack requestContextStack,
+                                              final DeviceContext deviceContext,
+                                              final ConvertorExecutor convertorExecutor,
+                                              final MultipartWriterProvider statisticsWriterProvider) {
+        super(requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider);
     }
 
     @Override
-    public Future<RpcResult<List<MultipartReply>>> getStatisticsOfType(final EventIdentifier eventIdentifier, final MultipartType type) {
+    public ListenableFuture<RpcResult<List<T>>> getStatisticsOfType(final EventIdentifier eventIdentifier, final MultipartType type) {
         LOG.debug("Getting statistics (onTheFly) for node {} of type {}", getDeviceInfo().getNodeId(), type);
         EventsTimeCounter.markStart(eventIdentifier);
         setEventIdentifier(eventIdentifier);
@@ -50,4 +55,5 @@ public class StatisticsGatheringOnTheFlyService extends AbstractMultipartOnTheFl
     protected OfHeader buildRequest(final Xid xid, final MultipartType input) throws ServiceException {
         return MultipartRequestInputFactory.makeMultipartRequestInput(xid.getValue(), getVersion(), input);
     }
+
 }
index fc0f8d3f3ff3c09a6833ddc9efdab0eeb556be47..3f8e355f1ef1beecb6155c6d0bbd35e5f07017d4 100644 (file)
@@ -8,8 +8,8 @@
 
 package org.opendaylight.openflowplugin.impl.statistics.services.dedicated;
 
+import com.google.common.util.concurrent.ListenableFuture;
 import java.util.List;
-import java.util.concurrent.Future;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
@@ -17,19 +17,17 @@ import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.Event
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.StatisticsGatherer;
 import org.opendaylight.openflowplugin.impl.common.MultipartRequestInputFactory;
 import org.opendaylight.openflowplugin.impl.services.AbstractMultipartService;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
 import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.EventsTimeCounter;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-/**
- * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 4.4.2015.
- */
-public class StatisticsGatheringService extends AbstractMultipartService<MultipartType> implements StatisticsGatherer {
+public class StatisticsGatheringService<T extends OfHeader>
+    extends AbstractMultipartService<MultipartType, T>
+    implements StatisticsGatherer<T> {
 
     private static final Logger LOG = LoggerFactory.getLogger(StatisticsGatheringService.class);
 
@@ -38,7 +36,7 @@ public class StatisticsGatheringService extends AbstractMultipartService<Multipa
     }
 
     @Override
-    public Future<RpcResult<List<MultipartReply>>> getStatisticsOfType(final EventIdentifier eventIdentifier, final MultipartType type) {
+    public ListenableFuture<RpcResult<List<T>>> getStatisticsOfType(final EventIdentifier eventIdentifier, final MultipartType type) {
         LOG.debug("Getting statistics for node {} of type {}", getDeviceInfo().getNodeId(), type);
         EventsTimeCounter.markStart(eventIdentifier);
         setEventIdentifier(eventIdentifier);
@@ -49,4 +47,5 @@ public class StatisticsGatheringService extends AbstractMultipartService<Multipa
     protected OfHeader buildRequest(final Xid xid, final MultipartType input) throws ServiceException {
         return MultipartRequestInputFactory.makeMultipartRequestInput(xid.getValue(), getVersion(), input);
     }
+
 }
index d8ad2ae86b3e47b65709ffe78e0720e12424a9e6..82b8ddbe291ae761c58e6d91c109f5f0be94f6c1 100644 (file)
@@ -8,27 +8,27 @@
 
 package org.opendaylight.openflowplugin.impl.statistics.services.direct;
 
-import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.AsyncFunction;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.util.List;
 import java.util.concurrent.Future;
+import java.util.function.Function;
 import javax.annotation.Nullable;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
 import org.opendaylight.openflowplugin.impl.services.AbstractMultipartService;
-import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
-import org.opendaylight.openflowplugin.impl.services.ServiceException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.StoreStatsGrouping;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
@@ -39,55 +39,62 @@ import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
  * @param <I> the input type parameter
  * @param <O> the output type parameter
  */
-public abstract class AbstractDirectStatisticsService<I extends StoreStatsGrouping, O> extends AbstractMultipartService<I> {
+abstract class AbstractDirectStatisticsService<I extends StoreStatsGrouping, O extends DataContainer, T extends OfHeader>
+        extends AbstractMultipartService<I, T> {
 
-    private final Function<RpcResult<List<MultipartReply>>, RpcResult<O>> resultTransformFunction =
-            new Function<RpcResult<List<MultipartReply>>, RpcResult<O>>() {
+    private final Function<RpcResult<List<T>>, RpcResult<O>> resultTransformFunction =
+            new Function<RpcResult<List<T>>, RpcResult<O>>() {
                 @Nullable
                 @Override
-                public RpcResult<O> apply(@Nullable RpcResult<List<MultipartReply>> input) {
-                    Preconditions.checkNotNull(input);
-                    final O reply = buildReply(input.getResult(), input.isSuccessful());
-                    return RpcResultBuilder.success(reply).build();
+                public RpcResult<O> apply(@Nullable RpcResult<List<T>> input) {
+                    return Preconditions.checkNotNull(input).isSuccessful()
+                            ? RpcResultBuilder.success(buildReply(input.getResult(), input.isSuccessful())).build()
+                            : RpcResultBuilder.<O>failed().build();
                 }
             };
 
-    private final AsyncFunction<RpcResult<O>, RpcResult<O>> resultStoreFunction =
-            new AsyncFunction<RpcResult<O>, RpcResult<O>>() {
+    private final Function<RpcResult<O>, RpcResult<O>> resultStoreFunction =
+            new Function<RpcResult<O>, RpcResult<O>>() {
                 @Nullable
                 @Override
-                public ListenableFuture<RpcResult<O>> apply(@Nullable RpcResult<O> input) throws Exception {
+                public RpcResult<O> apply(@Nullable RpcResult<O> input)  {
                     Preconditions.checkNotNull(input);
 
                     if (input.isSuccessful()) {
-                        storeStatistics(input.getResult());
-                        getTxFacade().submitTransaction(); // TODO: If submitTransaction will ever return future, chain it
+                        multipartWriterProvider
+                            .lookup(multipartType)
+                            .ifPresent(writer -> {
+                                writer.write(input.getResult(), true);
+                                getTxFacade().submitTransaction();
+                            });
                     }
 
-                    return Futures.immediateFuture(input);
+                    return input;
                 }
             };
 
     private final MultipartType multipartType;
-    private final ConvertorExecutor convertorExecutor;
     private final OpenflowVersion ofVersion = OpenflowVersion.get(getVersion());
+    private final ConvertorExecutor convertorExecutor;
+    private final MultipartWriterProvider multipartWriterProvider;
+
     /**
      * Instantiates a new Abstract direct statistics service.
-     *
-     * @param multipartType       the multipart type
-     * @param requestContextStack the request context stack
-     * @param deviceContext       the device context
-     * @param convertorExecutor
+     * @param multipartType           the multipart type
+     * @param requestContextStack      the request context stack
+     * @param deviceContext            the device context
+     * @param convertorExecutor        convertor executor
+     * @param multipartWriterProvider statistics writer provider
      */
-    protected AbstractDirectStatisticsService(MultipartType multipartType, RequestContextStack requestContextStack,
-                                              DeviceContext deviceContext, ConvertorExecutor convertorExecutor) {
+    AbstractDirectStatisticsService(final MultipartType multipartType,
+                                    final RequestContextStack requestContextStack,
+                                    final DeviceContext deviceContext,
+                                    final ConvertorExecutor convertorExecutor,
+                                    final MultipartWriterProvider multipartWriterProvider) {
         super(requestContextStack, deviceContext);
         this.multipartType = multipartType;
         this.convertorExecutor = convertorExecutor;
-    }
-
-    protected ConvertorExecutor getConvertorExecutor() {
-        return convertorExecutor;
+        this.multipartWriterProvider = multipartWriterProvider;
     }
 
     /**
@@ -96,12 +103,12 @@ public abstract class AbstractDirectStatisticsService<I extends StoreStatsGroupi
      * @param input the input
      * @return the future
      */
-    public Future<RpcResult<O>> handleAndReply(final I input) {
-        final ListenableFuture<RpcResult<List<MultipartReply>>> rpcReply = handleServiceCall(input);
-        ListenableFuture<RpcResult<O>> rpcResult = Futures.transform(rpcReply, resultTransformFunction);
+    Future<RpcResult<O>> handleAndReply(final I input) {
+        final ListenableFuture<RpcResult<List<T>>> rpcReply = handleServiceCall(input);
+        ListenableFuture<RpcResult<O>> rpcResult = Futures.transform(rpcReply, resultTransformFunction::apply);
 
         if (Boolean.TRUE.equals(input.isStoreStats())) {
-            rpcResult = Futures.transform(rpcResult, resultStoreFunction);
+            rpcResult = Futures.transform(rpcResult, resultStoreFunction::apply);
         }
 
         return rpcResult;
@@ -114,6 +121,14 @@ public abstract class AbstractDirectStatisticsService<I extends StoreStatsGroupi
                 .build();
     }
 
+    /**
+     * Get convertor executor
+     * @return convertor executor
+     */
+    protected ConvertorExecutor getConvertorExecutor() {
+        return convertorExecutor;
+    }
+
     /**
      * Gets openflow version.
      *
@@ -129,7 +144,7 @@ public abstract class AbstractDirectStatisticsService<I extends StoreStatsGroupi
      * @param input the input
      * @return the multipart request body
      */
-    protected abstract MultipartRequestBody buildRequestBody(I input);
+    public abstract MultipartRequestBody buildRequestBody(I input);
 
     /**
      * Build output from multipart reply input.
@@ -137,15 +152,6 @@ public abstract class AbstractDirectStatisticsService<I extends StoreStatsGroupi
      * @param input the input
      * @return the output
      */
-    protected abstract O buildReply(List<MultipartReply> input, boolean success);
+    protected abstract O buildReply(List<T> input, boolean success);
 
-    /**
-     * Store statistics.
-     * TODO: Remove dependency on deviceContext from derived methods
-     * TODO: Return future, so we will be able to chain it
-     *
-     * @param output the output
-     * @throws Exception the exception
-     */
-    protected abstract void storeStatistics(O output) throws Exception;
 }
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractFlowDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractFlowDirectStatisticsService.java
new file mode 100644 (file)
index 0000000..6c7b4a1
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
+import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchReactor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsOutput;
+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.FlowBuilder;
+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.flow.and.statistics.map.list.FlowAndStatisticsMapList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.statistics.FlowStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestFlowCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.flow._case.MultipartRequestFlowBuilder;
+
+/**
+ * The Flow direct statistics service.
+ */
+public abstract class AbstractFlowDirectStatisticsService<T extends OfHeader>
+        extends AbstractDirectStatisticsService<GetFlowStatisticsInput, GetFlowStatisticsOutput, T> {
+
+    protected AbstractFlowDirectStatisticsService(final RequestContextStack requestContextStack,
+                                                  final DeviceContext deviceContext,
+                                                  final ConvertorExecutor convertorExecutor,
+                                                  final MultipartWriterProvider statisticsWriterProvider) {
+        super(MultipartType.OFPMPFLOW, requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider);
+    }
+
+    @Override
+    public MultipartRequestBody buildRequestBody(GetFlowStatisticsInput input) {
+        final MultipartRequestFlowBuilder mprFlowRequestBuilder = new MultipartRequestFlowBuilder();
+
+        if (input.getTableId() != null) {
+            mprFlowRequestBuilder.setTableId(input.getTableId());
+        } else {
+            mprFlowRequestBuilder.setTableId(OFConstants.OFPTT_ALL);
+        }
+
+        if (input.getOutPort() != null) {
+            mprFlowRequestBuilder.setOutPort(input.getOutPort().longValue());
+        } else {
+            mprFlowRequestBuilder.setOutPort(OFConstants.OFPP_ANY);
+        }
+
+        if (input.getOutGroup() != null) {
+            mprFlowRequestBuilder.setOutGroup(input.getOutGroup());
+        } else {
+            mprFlowRequestBuilder.setOutGroup(OFConstants.OFPG_ANY);
+        }
+
+        if (input.getCookie() != null) {
+            mprFlowRequestBuilder.setCookie(input.getCookie().getValue());
+        } else {
+            mprFlowRequestBuilder.setCookie(OFConstants.DEFAULT_COOKIE);
+        }
+
+        if (input.getCookieMask() != null) {
+            mprFlowRequestBuilder.setCookieMask(input.getCookieMask().getValue());
+        } else {
+            mprFlowRequestBuilder.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK);
+        }
+
+        MatchReactor.getInstance().convert(input.getMatch(), getVersion(), mprFlowRequestBuilder, getConvertorExecutor());
+
+        return new MultipartRequestFlowCaseBuilder()
+                .setMultipartRequestFlow(mprFlowRequestBuilder.build())
+                .build();
+    }
+
+    /**
+     * Get flow ID from #{@link org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry} or
+     * create alien ID
+     * @param flowStatistics flow statistics
+     * @return generated flow ID
+     */
+    protected FlowId generateFlowId(FlowAndStatisticsMapList flowStatistics) {
+        final FlowStatisticsDataBuilder flowStatisticsDataBld = new FlowStatisticsDataBuilder()
+                .setFlowStatistics(new FlowStatisticsBuilder(flowStatistics).build());
+
+        final FlowBuilder flowBuilder = new FlowBuilder(flowStatistics)
+                .addAugmentation(FlowStatisticsData.class, flowStatisticsDataBld.build());
+
+        final FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(getVersion(), flowBuilder.build());
+        return getDeviceRegistry().getDeviceFlowRegistry().storeIfNecessary(flowRegistryKey);
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractGroupDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractGroupDirectStatisticsService.java
new file mode 100644 (file)
index 0000000..32b2819
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestGroupCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.group._case.MultipartRequestGroupBuilder;
+
+/**
+ * The Group direct statistics service.
+ */
+public abstract class AbstractGroupDirectStatisticsService<T extends OfHeader>
+        extends AbstractDirectStatisticsService<GetGroupStatisticsInput, GetGroupStatisticsOutput, T> {
+
+    protected AbstractGroupDirectStatisticsService(final RequestContextStack requestContextStack,
+                                                   final DeviceContext deviceContext,
+                                                   final ConvertorExecutor convertorExecutor,
+                                                   final MultipartWriterProvider statisticsWriterProvider) {
+        super(MultipartType.OFPMPGROUP, requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider);
+    }
+
+    @Override
+    public MultipartRequestBody buildRequestBody(GetGroupStatisticsInput input) {
+        final MultipartRequestGroupBuilder mprGroupBuild = new MultipartRequestGroupBuilder();
+
+        if (input.getGroupId() != null) {
+            mprGroupBuild.setGroupId(new GroupId(input.getGroupId().getValue()));
+        } else {
+            mprGroupBuild.setGroupId(new GroupId(OFConstants.OFPG_ALL));
+        }
+
+        return new MultipartRequestGroupCaseBuilder()
+                .setMultipartRequestGroup(mprGroupBuild.build())
+                .build();
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractMeterDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractMeterDirectStatisticsService.java
new file mode 100644 (file)
index 0000000..d047752
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeterCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.meter._case.MultipartRequestMeterBuilder;
+
+/**
+ * The Meter direct statistics service.
+ */
+public abstract class AbstractMeterDirectStatisticsService<T extends OfHeader> extends
+        AbstractDirectStatisticsService<GetMeterStatisticsInput, GetMeterStatisticsOutput, T> {
+
+    public AbstractMeterDirectStatisticsService(final RequestContextStack requestContextStack,
+                                                final DeviceContext deviceContext,
+                                                final ConvertorExecutor convertorExecutor,
+                                                final MultipartWriterProvider statisticsWriterProvider) {
+        super(MultipartType.OFPMPMETER, requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider);
+    }
+
+    @Override
+    public MultipartRequestBody buildRequestBody(GetMeterStatisticsInput input) {
+        final MultipartRequestMeterBuilder mprMeterBuild = new MultipartRequestMeterBuilder();
+
+        if (input.getMeterId() != null) {
+            mprMeterBuild.setMeterId(new MeterId(input.getMeterId().getValue()));
+        } else {
+            mprMeterBuild.setMeterId(new MeterId(OFConstants.OFPM_ALL));
+        }
+
+        return new MultipartRequestMeterCaseBuilder()
+                .setMultipartRequestMeter(mprMeterBuild.build())
+                .build();
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractPortDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractPortDirectStatisticsService.java
new file mode 100644 (file)
index 0000000..9b55689
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestPortStatsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.port.stats._case.MultipartRequestPortStatsBuilder;
+
+/**
+ * The Node connector direct statistics service.
+ */
+public abstract class AbstractPortDirectStatisticsService<T extends OfHeader>
+        extends AbstractDirectStatisticsService<GetNodeConnectorStatisticsInput, GetNodeConnectorStatisticsOutput, T> {
+
+    public AbstractPortDirectStatisticsService(final RequestContextStack requestContextStack,
+                                               final DeviceContext deviceContext,
+                                               final ConvertorExecutor convertorExecutor,
+                                               final MultipartWriterProvider statisticsWriterProvider) {
+        super(MultipartType.OFPMPPORTSTATS, requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider);
+    }
+
+    @Override
+    public MultipartRequestBody buildRequestBody(GetNodeConnectorStatisticsInput input) {
+        final MultipartRequestPortStatsBuilder mprPortStatsBuilder = new MultipartRequestPortStatsBuilder();
+
+        if (input.getNodeConnectorId() != null) {
+            mprPortStatsBuilder.setPortNo(InventoryDataServiceUtil.portNumberfromNodeConnectorId(getOfVersion(), input.getNodeConnectorId()));
+        } else {
+            mprPortStatsBuilder.setPortNo(OFConstants.OFPP_ANY);
+        }
+
+        return new MultipartRequestPortStatsCaseBuilder()
+                .setMultipartRequestPortStats(mprPortStatsBuilder.build())
+                .build();
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractQueueDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/AbstractQueueDirectStatisticsService.java
new file mode 100644 (file)
index 0000000..79cd9a4
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestQueueCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.queue._case.MultipartRequestQueueBuilder;
+
+/**
+ * The Queue direct statistics service.
+ */
+public abstract class AbstractQueueDirectStatisticsService<T extends OfHeader>
+        extends AbstractDirectStatisticsService<GetQueueStatisticsInput, GetQueueStatisticsOutput, T> {
+
+    public AbstractQueueDirectStatisticsService(final RequestContextStack requestContextStack,
+                                                final DeviceContext deviceContext,
+                                                final ConvertorExecutor convertorExecutor,
+                                                final MultipartWriterProvider statisticsWriterProvider) {
+        super(MultipartType.OFPMPQUEUE, requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider);
+    }
+
+    @Override
+    public MultipartRequestBody buildRequestBody(GetQueueStatisticsInput input) {
+        final MultipartRequestQueueBuilder mprQueueBuilder = new MultipartRequestQueueBuilder();
+
+        if (input.getQueueId() != null) {
+            mprQueueBuilder.setQueueId(input.getQueueId().getValue());
+        } else {
+            mprQueueBuilder.setQueueId(OFConstants.OFPQ_ALL);
+        }
+
+        if (input.getNodeConnectorId() != null) {
+            mprQueueBuilder.setPortNo(InventoryDataServiceUtil.portNumberfromNodeConnectorId(getOfVersion(), input.getNodeConnectorId()));
+        } else {
+            mprQueueBuilder.setPortNo(OFConstants.OFPP_ANY);
+        }
+
+        return new MultipartRequestQueueCaseBuilder()
+                .setMultipartRequestQueue(mprQueueBuilder.build())
+                .build();
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/FlowDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/FlowDirectStatisticsService.java
deleted file mode 100644 (file)
index a106ad9..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.openflowplugin.impl.statistics.services.direct;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
-import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
-import org.opendaylight.openflowplugin.extension.api.path.MatchPath;
-import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.FlowStatsResponseConvertorData;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionDatapathIdConvertorData;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchReactor;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsOutputBuilder;
-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.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.and.statistics.map.list.FlowAndStatisticsMapListKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.statistics.FlowStatisticsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyFlowCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.MultipartReplyFlow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestFlowCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.flow._case.MultipartRequestFlowBuilder;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-/**
- * The Flow direct statistics service.
- */
-public class FlowDirectStatisticsService extends AbstractDirectStatisticsService<GetFlowStatisticsInput, GetFlowStatisticsOutput> {
-    private final FlowStatsResponseConvertorData data;
-
-    /**
-     * Instantiates a new Flow direct statistics service.
-     *  @param requestContextStack the request context stack
-     * @param deviceContext       the device context
-     * @param convertorExecutor
-     */
-    public FlowDirectStatisticsService(RequestContextStack requestContextStack, DeviceContext deviceContext, ConvertorExecutor convertorExecutor) {
-        super(MultipartType.OFPMPFLOW, requestContextStack, deviceContext, convertorExecutor);
-        data = new FlowStatsResponseConvertorData(getVersion());
-        data.setDatapathId(getDatapathId());
-        data.setMatchPath(MatchPath.RPCFLOWSSTATISTICS_FLOWANDSTATISTICSMAPLIST_MATCH);
-    }
-
-    @Override
-    protected MultipartRequestBody buildRequestBody(GetFlowStatisticsInput input) {
-        final MultipartRequestFlowBuilder mprFlowRequestBuilder = new MultipartRequestFlowBuilder();
-
-        if (input.getTableId() != null) {
-            mprFlowRequestBuilder.setTableId(input.getTableId());
-        } else {
-            mprFlowRequestBuilder.setTableId(OFConstants.OFPTT_ALL);
-        }
-
-        if (input.getOutPort() != null) {
-            mprFlowRequestBuilder.setOutPort(input.getOutPort().longValue());
-        } else {
-            mprFlowRequestBuilder.setOutPort(OFConstants.OFPP_ANY);
-        }
-
-        if (input.getOutGroup() != null) {
-            mprFlowRequestBuilder.setOutGroup(input.getOutGroup());
-        } else {
-            mprFlowRequestBuilder.setOutGroup(OFConstants.OFPG_ANY);
-        }
-
-        if (input.getCookie() != null) {
-            mprFlowRequestBuilder.setCookie(input.getCookie().getValue());
-        } else {
-            mprFlowRequestBuilder.setCookie(OFConstants.DEFAULT_COOKIE);
-        }
-
-        if (input.getCookieMask() != null) {
-            mprFlowRequestBuilder.setCookieMask(input.getCookieMask().getValue());
-        } else {
-            mprFlowRequestBuilder.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK);
-        }
-
-        MatchReactor.getInstance().convert(input.getMatch(), getVersion(), mprFlowRequestBuilder, getConvertorExecutor());
-
-        return new MultipartRequestFlowCaseBuilder()
-                .setMultipartRequestFlow(mprFlowRequestBuilder.build())
-                .build();
-    }
-
-    @Override
-    protected GetFlowStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
-        final List<FlowAndStatisticsMapList> statsList = new ArrayList<>();
-
-        if (success) {
-            for (final MultipartReply mpReply : input) {
-                final MultipartReplyFlowCase caseBody = (MultipartReplyFlowCase) mpReply.getMultipartReplyBody();
-                final MultipartReplyFlow replyBody = caseBody.getMultipartReplyFlow();
-                final Optional<List<FlowAndStatisticsMapList>> statsListPart = getConvertorExecutor().convert(
-                        replyBody.getFlowStats(), data);
-
-                if (statsListPart.isPresent()) {
-                    for (final FlowAndStatisticsMapList part : statsListPart.get()) {
-                        final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowId flowId =
-                                new org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowId(generateFlowId(part).getValue());
-
-                        statsList.add(new FlowAndStatisticsMapListBuilder(part)
-                                .setKey(new FlowAndStatisticsMapListKey(flowId))
-                                .setFlowId(flowId)
-                                .build());
-                    }
-                }
-            }
-        }
-
-        return new GetFlowStatisticsOutputBuilder()
-                .setFlowAndStatisticsMapList(statsList)
-                .build();
-    }
-
-    @Override
-    protected void storeStatistics(GetFlowStatisticsOutput output) throws Exception {
-        final InstanceIdentifier<FlowCapableNode> nodePath = getDeviceInfo().getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
-
-        for (final FlowAndStatisticsMapList flowStatistics : output.getFlowAndStatisticsMapList()) {
-            final FlowId flowId = generateFlowId(flowStatistics);
-            final FlowKey flowKey = new FlowKey(flowId);
-
-            final FlowStatisticsDataBuilder flowStatisticsDataBld = new FlowStatisticsDataBuilder()
-                    .setFlowStatistics(new FlowStatisticsBuilder(flowStatistics).build());
-
-            final FlowBuilder flowBuilder = new FlowBuilder(flowStatistics)
-                    .addAugmentation(FlowStatisticsData.class, flowStatisticsDataBld.build())
-                    .setKey(flowKey);
-
-            final InstanceIdentifier<Flow> flowStatisticsPath = nodePath
-                    .child(Table.class, new TableKey(flowStatistics.getTableId()))
-                    .child(Flow.class, flowKey);
-
-            getTxFacade().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, flowStatisticsPath, flowBuilder.build());
-        }
-    }
-
-    private FlowId generateFlowId(FlowAndStatisticsMapList flowStatistics) {
-        final FlowStatisticsDataBuilder flowStatisticsDataBld = new FlowStatisticsDataBuilder()
-                .setFlowStatistics(new FlowStatisticsBuilder(flowStatistics).build());
-
-        final FlowBuilder flowBuilder = new FlowBuilder(flowStatistics)
-                .addAugmentation(FlowStatisticsData.class, flowStatisticsDataBld.build());
-
-        final FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(getVersion(), flowBuilder.build());
-        return getDeviceRegistry().getDeviceFlowRegistry().storeIfNecessary(flowRegistryKey);
-    }
-}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/GroupDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/GroupDirectStatisticsService.java
deleted file mode 100644 (file)
index 9a4925c..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.openflowplugin.impl.statistics.services.direct;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatistics;
-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.GroupKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.MultipartReplyGroup;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestGroupCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.group._case.MultipartRequestGroupBuilder;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-/**
- * The Group direct statistics service.
- */
-public class GroupDirectStatisticsService extends AbstractDirectStatisticsService<GetGroupStatisticsInput, GetGroupStatisticsOutput> {
-    private final VersionConvertorData data;
-
-    /**
-     * Instantiates a new Group direct statistics service.
-     *  @param requestContextStack the request context stack
-     * @param deviceContext       the device context
-     * @param convertorExecutor
-     */
-    public GroupDirectStatisticsService(RequestContextStack requestContextStack, DeviceContext deviceContext, ConvertorExecutor convertorExecutor) {
-        super(MultipartType.OFPMPGROUP, requestContextStack, deviceContext, convertorExecutor);
-        data = new VersionConvertorData(getVersion());
-    }
-
-    @Override
-    protected MultipartRequestBody buildRequestBody(GetGroupStatisticsInput input) {
-        final MultipartRequestGroupBuilder mprGroupBuild = new MultipartRequestGroupBuilder();
-
-        if (input.getGroupId() != null) {
-            mprGroupBuild.setGroupId(new GroupId(input.getGroupId().getValue()));
-        } else {
-            mprGroupBuild.setGroupId(new GroupId(OFConstants.OFPG_ALL));
-        }
-
-        return new MultipartRequestGroupCaseBuilder()
-                .setMultipartRequestGroup(mprGroupBuild.build())
-                .build();
-    }
-
-    @Override
-    protected GetGroupStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
-        final List<GroupStats> groupStats = new ArrayList<>();
-
-        if (success) {
-            for (final MultipartReply mpReply : input) {
-                final MultipartReplyGroupCase caseBody = (MultipartReplyGroupCase) mpReply.getMultipartReplyBody();
-                final MultipartReplyGroup replyBody = caseBody.getMultipartReplyGroup();
-                final Optional<List<GroupStats>> groupStatsList = getConvertorExecutor().convert(
-                        replyBody.getGroupStats(), data);
-
-                if (groupStatsList.isPresent()) {
-                    groupStats.addAll(groupStatsList.get());
-                }
-            }
-        }
-
-        return new GetGroupStatisticsOutputBuilder()
-                .setGroupStats(groupStats)
-                .build();
-    }
-
-    @Override
-    protected void storeStatistics(GetGroupStatisticsOutput output) throws Exception {
-        final InstanceIdentifier<FlowCapableNode> nodePath = getDeviceInfo().getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
-
-        for (final GroupStats groupStatistics : output.getGroupStats()) {
-            final InstanceIdentifier<GroupStatistics> groupStatisticsPath = nodePath
-                    .child(Group.class, new GroupKey(groupStatistics.getGroupId()))
-                    .augmentation(NodeGroupStatistics.class)
-                    .child(GroupStatistics.class);
-
-            final GroupStatistics stats = new GroupStatisticsBuilder(groupStatistics).build();
-            getTxFacade().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, groupStatisticsPath, stats);
-        }
-    }
-}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/MeterDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/MeterDirectStatisticsService.java
deleted file mode 100644 (file)
index 1e1146d..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.openflowplugin.impl.statistics.services.direct;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatistics;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatisticsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter._case.MultipartReplyMeter;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeterCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.meter._case.MultipartRequestMeterBuilder;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-/**
- * The Meter direct statistics service.
- */
-public class MeterDirectStatisticsService extends AbstractDirectStatisticsService<GetMeterStatisticsInput, GetMeterStatisticsOutput> {
-    private final VersionConvertorData data;
-
-    /**
-     * Instantiates a new Meter direct statistics service.
-     *  @param requestContextStack the request context stack
-     * @param deviceContext       the device context
-     * @param convertorExecutor
-     */
-    public MeterDirectStatisticsService(RequestContextStack requestContextStack, DeviceContext deviceContext, ConvertorExecutor convertorExecutor) {
-        super(MultipartType.OFPMPMETER, requestContextStack, deviceContext, convertorExecutor);
-        data = new VersionConvertorData(getVersion());
-    }
-
-    @Override
-    protected MultipartRequestBody buildRequestBody(GetMeterStatisticsInput input) {
-        final MultipartRequestMeterBuilder mprMeterBuild = new MultipartRequestMeterBuilder();
-
-        if (input.getMeterId() != null) {
-            mprMeterBuild.setMeterId(new MeterId(input.getMeterId().getValue()));
-        } else {
-            mprMeterBuild.setMeterId(new MeterId(OFConstants.OFPM_ALL));
-        }
-
-        return new MultipartRequestMeterCaseBuilder()
-                .setMultipartRequestMeter(mprMeterBuild.build())
-                .build();
-    }
-
-    @Override
-    protected GetMeterStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
-        final List<MeterStats> meterStats = new ArrayList<>();
-
-        if (success) {
-            for (final MultipartReply mpReply : input) {
-                final MultipartReplyMeterCase caseBody = (MultipartReplyMeterCase) mpReply.getMultipartReplyBody();
-                final MultipartReplyMeter replyBody = caseBody.getMultipartReplyMeter();
-                final Optional<List<MeterStats>> meterStatsList = getConvertorExecutor().convert(replyBody.getMeterStats(), data);
-
-                if (meterStatsList.isPresent()) {
-                    meterStats.addAll(meterStatsList.get());
-                }
-            }
-        }
-
-        return new GetMeterStatisticsOutputBuilder()
-                .setMeterStats(meterStats)
-                .build();
-    }
-
-    @Override
-    protected void storeStatistics(GetMeterStatisticsOutput output) throws Exception {
-        final InstanceIdentifier<FlowCapableNode> nodePath = getDeviceInfo().getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
-
-        for (final MeterStats meterStatistics : output.getMeterStats()) {
-            final InstanceIdentifier<MeterStatistics> meterPath = nodePath
-                    .child(Meter.class, new MeterKey(meterStatistics.getMeterId()))
-                    .augmentation(NodeMeterStatistics.class)
-                    .child(MeterStatistics.class);
-
-            final MeterStatistics stats = new MeterStatisticsBuilder(meterStatistics).build();
-            getTxFacade().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, meterPath, stats);
-        }
-    }
-}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/NodeConnectorDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/NodeConnectorDirectStatisticsService.java
deleted file mode 100644 (file)
index 2efa1cf..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.openflowplugin.impl.statistics.services.direct;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
-import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsOutputBuilder;
-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.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.duration.DurationBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.BytesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.PacketsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortStatsCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.MultipartReplyPortStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.multipart.reply.port.stats.PortStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestPortStatsCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.port.stats._case.MultipartRequestPortStatsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatistics;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatisticsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-/**
- * The Node connector direct statistics service.
- */
-public class NodeConnectorDirectStatisticsService extends AbstractDirectStatisticsService<GetNodeConnectorStatisticsInput, GetNodeConnectorStatisticsOutput> {
-    /**
-     * Instantiates a new Node connector direct statistics service.
-     *  @param requestContextStack the request context stack
-     * @param deviceContext       the device context
-     * @param convertorExecutor
-     */
-    public NodeConnectorDirectStatisticsService(RequestContextStack requestContextStack, DeviceContext deviceContext, ConvertorExecutor convertorExecutor) {
-        super(MultipartType.OFPMPPORTSTATS, requestContextStack, deviceContext, convertorExecutor);
-    }
-
-    @Override
-    protected MultipartRequestBody buildRequestBody(GetNodeConnectorStatisticsInput input) {
-        final MultipartRequestPortStatsBuilder mprPortStatsBuilder = new MultipartRequestPortStatsBuilder();
-
-        if (input.getNodeConnectorId() != null) {
-            mprPortStatsBuilder.setPortNo(InventoryDataServiceUtil.portNumberfromNodeConnectorId(getOfVersion(), input.getNodeConnectorId()));
-        } else {
-            mprPortStatsBuilder.setPortNo(OFConstants.OFPP_ANY);
-        }
-
-        return new MultipartRequestPortStatsCaseBuilder()
-                .setMultipartRequestPortStats(mprPortStatsBuilder.build())
-                .build();
-    }
-
-    @Override
-    protected GetNodeConnectorStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
-        final List<NodeConnectorStatisticsAndPortNumberMap> nodeConnectorStatisticsAndPortNumberMap = new ArrayList<>();
-
-        if (success) {
-            for (final MultipartReply mpReply : input) {
-                final MultipartReplyPortStatsCase caseBody = (MultipartReplyPortStatsCase) mpReply.getMultipartReplyBody();
-                final MultipartReplyPortStats replyBody = caseBody.getMultipartReplyPortStats();
-
-                for (final PortStats portStats : replyBody.getPortStats()) {
-                    final NodeConnectorId nodeConnectorId = InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(
-                            getDatapathId(), portStats.getPortNo(), getOfVersion());
-
-                    final BytesBuilder bytesBuilder = new BytesBuilder()
-                            .setReceived(portStats.getRxBytes())
-                            .setTransmitted(portStats.getTxBytes());
-
-                    final PacketsBuilder packetsBuilder = new PacketsBuilder()
-                            .setReceived(portStats.getRxPackets())
-                            .setTransmitted(portStats.getTxPackets());
-
-                    final DurationBuilder durationBuilder = new DurationBuilder();
-
-                    if (portStats.getDurationSec() != null) {
-                        durationBuilder.setSecond(new Counter32(portStats.getDurationSec()));
-                    }
-
-                    if (portStats.getDurationNsec() != null) {
-                        durationBuilder.setNanosecond(new Counter32(portStats.getDurationNsec()));
-                    }
-
-                    final NodeConnectorStatisticsAndPortNumberMap stats = new NodeConnectorStatisticsAndPortNumberMapBuilder()
-                            .setBytes(bytesBuilder.build())
-                            .setPackets(packetsBuilder.build())
-                            .setNodeConnectorId(nodeConnectorId)
-                            .setDuration(durationBuilder.build())
-                            .setCollisionCount(portStats.getCollisions())
-                            .setKey(new NodeConnectorStatisticsAndPortNumberMapKey(nodeConnectorId))
-                            .setReceiveCrcError(portStats.getRxCrcErr()).setReceiveDrops(portStats.getRxDropped())
-                            .setReceiveErrors(portStats.getRxErrors())
-                            .setReceiveFrameError(portStats.getRxFrameErr())
-                            .setReceiveOverRunError(portStats.getRxOverErr())
-                            .setTransmitDrops(portStats.getTxDropped())
-                            .setTransmitErrors(portStats.getTxErrors())
-                            .build();
-
-                    nodeConnectorStatisticsAndPortNumberMap.add(stats);
-                }
-            }
-        }
-
-        return new GetNodeConnectorStatisticsOutputBuilder()
-                .setNodeConnectorStatisticsAndPortNumberMap(nodeConnectorStatisticsAndPortNumberMap)
-                .build();
-    }
-
-    @Override
-    protected void storeStatistics(GetNodeConnectorStatisticsOutput output) throws Exception {
-        final InstanceIdentifier<Node> nodePath = getDeviceInfo().getNodeInstanceIdentifier();
-
-        for (final NodeConnectorStatisticsAndPortNumberMap nodeConnectorStatistics : output.getNodeConnectorStatisticsAndPortNumberMap()) {
-            final InstanceIdentifier<FlowCapableNodeConnectorStatistics> nodeConnectorPath = nodePath
-                    .child(NodeConnector.class, new NodeConnectorKey(nodeConnectorStatistics.getNodeConnectorId()))
-                    .augmentation(FlowCapableNodeConnectorStatisticsData.class)
-                    .child(FlowCapableNodeConnectorStatistics.class);
-
-            final FlowCapableNodeConnectorStatistics stats = new FlowCapableNodeConnectorStatisticsBuilder(nodeConnectorStatistics).build();
-            getTxFacade().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, nodeConnectorPath, stats);
-        }
-    }
-}
index 3f5af2f8e6edf9ffd4bad53a2288a5c1ba2d2802..8e2cea384a479b0d107f17380952cd87c9efc911 100644 (file)
@@ -8,7 +8,6 @@
 
 package org.opendaylight.openflowplugin.impl.statistics.services.direct;
 
-import java.util.Optional;
 import java.util.concurrent.Future;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsOutput;
@@ -43,61 +42,46 @@ public class OpendaylightDirectStatisticsServiceImpl implements OpendaylightDire
     }
 
     @Override
+    @SuppressWarnings("unchecked")
     public Future<RpcResult<GetGroupStatisticsOutput>> getGroupStatistics(GetGroupStatisticsInput input) {
-        final Optional<GroupDirectStatisticsService> service = provider.lookup(GroupDirectStatisticsService.class);
-
-        if (!service.isPresent()) {
-            return missingImplementation(GroupDirectStatisticsService.class);
-        }
-
-        return service.get().handleAndReply(input);
+        return provider.lookup(AbstractGroupDirectStatisticsService.class)
+                .map(service -> service.handleAndReply(input))
+                .orElse(missingImplementation(AbstractGroupDirectStatisticsService.class));
     }
 
     @Override
+    @SuppressWarnings("unchecked")
     public Future<RpcResult<GetQueueStatisticsOutput>> getQueueStatistics(GetQueueStatisticsInput input) {
-        final Optional<QueueDirectStatisticsService> service = provider.lookup(QueueDirectStatisticsService.class);
-
-        if (!service.isPresent()) {
-            return missingImplementation(QueueDirectStatisticsService.class);
-        }
-
-        return service.get().handleAndReply(input);
+        return provider.lookup(AbstractQueueDirectStatisticsService.class)
+                .map(service -> service.handleAndReply(input))
+                .orElse(missingImplementation(AbstractQueueDirectStatisticsService.class));
     }
 
     @Override
+    @SuppressWarnings("unchecked")
     public Future<RpcResult<GetFlowStatisticsOutput>> getFlowStatistics(GetFlowStatisticsInput input) {
-        final Optional<FlowDirectStatisticsService> service = provider.lookup(FlowDirectStatisticsService.class);
-
-        if (!service.isPresent()) {
-            return missingImplementation(FlowDirectStatisticsService.class);
-        }
-
-        return service.get().handleAndReply(input);
+        return provider.lookup(AbstractFlowDirectStatisticsService.class)
+                .map(service -> service.handleAndReply(input))
+                .orElse(missingImplementation(AbstractFlowDirectStatisticsService.class));
     }
 
     @Override
+    @SuppressWarnings("unchecked")
     public Future<RpcResult<GetMeterStatisticsOutput>> getMeterStatistics(GetMeterStatisticsInput input) {
-        final Optional<MeterDirectStatisticsService> service = provider.lookup(MeterDirectStatisticsService.class);
-
-        if (!service.isPresent()) {
-            return missingImplementation(MeterDirectStatisticsService.class);
-        }
-
-        return service.get().handleAndReply(input);
+        return provider.lookup(AbstractMeterDirectStatisticsService.class)
+                .map(service -> service.handleAndReply(input))
+                .orElse(missingImplementation(AbstractMeterDirectStatisticsService.class));
     }
 
     @Override
+    @SuppressWarnings("unchecked")
     public Future<RpcResult<GetNodeConnectorStatisticsOutput>> getNodeConnectorStatistics(GetNodeConnectorStatisticsInput input) {
-        final Optional<NodeConnectorDirectStatisticsService> service = provider.lookup(NodeConnectorDirectStatisticsService.class);
-
-        if (!service.isPresent()) {
-            return missingImplementation(NodeConnectorDirectStatisticsService.class);
-        }
-
-        return service.get().handleAndReply(input);
+        return provider.lookup(AbstractPortDirectStatisticsService.class)
+                .map(service -> service.handleAndReply(input))
+                .orElse(missingImplementation(AbstractPortDirectStatisticsService.class));
     }
 
-    private <T extends DataObject> Future<RpcResult<T>> missingImplementation(Class service) {
+    private static <T extends DataObject> Future<RpcResult<T>> missingImplementation(Class service) {
         return RpcResultBuilder.<T>failed().withError(
                 RpcError.ErrorType.APPLICATION,
                 String.format("No implementation found for direct statistics service %s.", service.getCanonicalName()))
index daecefb2fa024666924f6615bbb1038837596653..96b9b03758e4f256e66a235dda7bbcc9e0de72b0 100644 (file)
@@ -25,21 +25,16 @@ public class OpendaylightDirectStatisticsServiceProvider {
      * @param service the service instance
      */
     public void register(Class<? extends AbstractDirectStatisticsService> type, AbstractDirectStatisticsService service) {
-        if (services.containsKey(type)) return;
-
         services.put(type, service);
     }
 
     /**
      * Lookup direct statistics service.
      *
-     * @param <T>  the type parameter
      * @param type the service type
      * @return the service instance
      */
-    public <T extends AbstractDirectStatisticsService> Optional<T> lookup(Class<T> type) {
-        if (!services.containsKey(type)) return Optional.empty();
-
-        return Optional.of(type.cast(services.get(type)));
+    public Optional<? extends AbstractDirectStatisticsService> lookup(Class<? extends AbstractDirectStatisticsService> type) {
+        return Optional.ofNullable(services.get(type)).map(type::cast);
     }
 }
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/QueueDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/QueueDirectStatisticsService.java
deleted file mode 100644 (file)
index 9ebbece..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.openflowplugin.impl.statistics.services.direct;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
-import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsOutputBuilder;
-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.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.model.statistics.types.rev130925.duration.DurationBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyQueueCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.MultipartReplyQueue;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.multipart.reply.queue.QueueStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestQueueCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.queue._case.MultipartRequestQueueBuilder;
-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.FlowCapableNodeConnectorQueueStatistics;
-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.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMapBuilder;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-/**
- * The Queue direct statistics service.
- */
-public class QueueDirectStatisticsService extends AbstractDirectStatisticsService<GetQueueStatisticsInput, GetQueueStatisticsOutput> {
-    /**
-     * Instantiates a new Queue direct statistics service.
-     *  @param requestContextStack the request context stack
-     * @param deviceContext       the device context
-     * @param convertorExecutor
-     */
-    public QueueDirectStatisticsService(RequestContextStack requestContextStack, DeviceContext deviceContext, ConvertorExecutor convertorExecutor) {
-        super(MultipartType.OFPMPQUEUE, requestContextStack, deviceContext, convertorExecutor);
-    }
-
-    @Override
-    protected MultipartRequestBody buildRequestBody(GetQueueStatisticsInput input) {
-        final MultipartRequestQueueBuilder mprQueueBuilder = new MultipartRequestQueueBuilder();
-
-        if (input.getQueueId() != null) {
-            mprQueueBuilder.setQueueId(input.getQueueId().getValue());
-        } else {
-            mprQueueBuilder.setQueueId(OFConstants.OFPQ_ALL);
-        }
-
-        if (input.getNodeConnectorId() != null) {
-            mprQueueBuilder.setPortNo(InventoryDataServiceUtil.portNumberfromNodeConnectorId(getOfVersion(), input.getNodeConnectorId()));
-        } else {
-            mprQueueBuilder.setPortNo(OFConstants.OFPP_ANY);
-        }
-
-        return new MultipartRequestQueueCaseBuilder()
-                .setMultipartRequestQueue(mprQueueBuilder.build())
-                .build();
-    }
-
-    @Override
-    protected GetQueueStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
-        final List<QueueIdAndStatisticsMap> queueIdAndStatisticsMap = new ArrayList<>();
-
-        if (success) {
-            for (final MultipartReply mpReply : input) {
-                final MultipartReplyQueueCase caseBody = (MultipartReplyQueueCase) mpReply.getMultipartReplyBody();
-                final MultipartReplyQueue replyBody = caseBody.getMultipartReplyQueue();
-
-                for (final QueueStats queueStats : replyBody.getQueueStats()) {
-                    final DurationBuilder durationBuilder = new DurationBuilder()
-                            .setSecond(new Counter32(queueStats.getDurationSec()))
-                            .setNanosecond(new Counter32(queueStats.getDurationNsec()));
-
-                    final QueueIdAndStatisticsMapBuilder statsBuilder = new QueueIdAndStatisticsMapBuilder()
-                            .setNodeConnectorId(InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(
-                                    getDatapathId(), queueStats.getPortNo(), getOfVersion()))
-                            .setTransmissionErrors(new Counter64(queueStats.getTxErrors()))
-                            .setTransmittedBytes(new Counter64(queueStats.getTxBytes()))
-                            .setTransmittedPackets(new Counter64(queueStats.getTxPackets()))
-                            .setQueueId(new QueueId(queueStats.getQueueId()))
-                            .setDuration(durationBuilder.build());
-
-                    queueIdAndStatisticsMap.add(statsBuilder.build());
-                }
-            }
-        }
-
-        return new GetQueueStatisticsOutputBuilder()
-                .setQueueIdAndStatisticsMap(queueIdAndStatisticsMap)
-                .build();
-    }
-
-    @Override
-    protected void storeStatistics(GetQueueStatisticsOutput output) throws Exception {
-        final InstanceIdentifier<Node> nodePath = getDeviceInfo().getNodeInstanceIdentifier();
-
-        for (final QueueIdAndStatisticsMap queueStatistics : output.getQueueIdAndStatisticsMap()) {
-            if (queueStatistics.getQueueId() != null) {
-                final QueueKey qKey = new QueueKey(queueStatistics.getQueueId());
-
-                final FlowCapableNodeConnectorQueueStatistics statChild =
-                        new FlowCapableNodeConnectorQueueStatisticsBuilder(queueStatistics).build();
-
-                final FlowCapableNodeConnectorQueueStatisticsDataBuilder statBuild =
-                        new FlowCapableNodeConnectorQueueStatisticsDataBuilder()
-                                .setFlowCapableNodeConnectorQueueStatistics(statChild);
-
-                final InstanceIdentifier<Queue> queueStatisticsPath = nodePath
-                        .child(NodeConnector.class, new NodeConnectorKey(queueStatistics.getNodeConnectorId()))
-                        .augmentation(FlowCapableNodeConnector.class)
-                        .child(Queue.class, qKey);
-
-                final Queue stats = new QueueBuilder()
-                        .setKey(qKey)
-                        .setQueueId(queueStatistics.getQueueId())
-                        .addAugmentation(FlowCapableNodeConnectorQueueStatisticsData.class, statBuild.build()).build();
-
-                getTxFacade().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, queueStatisticsPath, stats);
-            }
-        }
-    }
-}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/FlowDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/FlowDirectStatisticsService.java
new file mode 100644 (file)
index 0000000..54e8cc5
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics.services.direct.multilayer;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.extension.api.path.MatchPath;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractFlowDirectStatisticsService;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.FlowStatsResponseConvertorData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowId;
+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.and.statistics.map.list.FlowAndStatisticsMapListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyFlowCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.MultipartReplyFlow;
+
+public class FlowDirectStatisticsService extends AbstractFlowDirectStatisticsService<MultipartReply> {
+
+    private final FlowStatsResponseConvertorData data;
+
+    public FlowDirectStatisticsService(final RequestContextStack requestContextStack,
+                                       final DeviceContext deviceContext,
+                                       final ConvertorExecutor convertorExecutor,
+                                       final MultipartWriterProvider statisticsWriterProvider) {
+        super(requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider);
+        data = new FlowStatsResponseConvertorData(getVersion());
+        data.setDatapathId(getDatapathId());
+        data.setMatchPath(MatchPath.RPCFLOWSSTATISTICS_FLOWANDSTATISTICSMAPLIST_MATCH);
+    }
+
+    @Override
+    protected GetFlowStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
+        final List<FlowAndStatisticsMapList> statsList = new ArrayList<>();
+
+        if (success) {
+            for (final MultipartReply mpReply : input) {
+                final MultipartReplyFlowCase caseBody = (MultipartReplyFlowCase) mpReply.getMultipartReplyBody();
+                final MultipartReplyFlow replyBody = caseBody.getMultipartReplyFlow();
+                final Optional<List<FlowAndStatisticsMapList>> statsListPart = getConvertorExecutor().convert(
+                    replyBody.getFlowStats(), data);
+
+                if (statsListPart.isPresent()) {
+                    for (final FlowAndStatisticsMapList part : statsListPart.get()) {
+                        final FlowId flowId = new FlowId(generateFlowId(part).getValue());
+                        statsList.add(new FlowAndStatisticsMapListBuilder(part)
+                            .setKey(new FlowAndStatisticsMapListKey(flowId))
+                            .setFlowId(flowId)
+                            .build());
+                    }
+                }
+            }
+        }
+
+        return new GetFlowStatisticsOutputBuilder()
+            .setFlowAndStatisticsMapList(statsList)
+            .build();
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/GroupDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/GroupDirectStatisticsService.java
new file mode 100644 (file)
index 0000000..e1aeef6
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics.services.direct.multilayer;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractGroupDirectStatisticsService;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.MultipartReplyGroup;
+
+public class GroupDirectStatisticsService extends AbstractGroupDirectStatisticsService<MultipartReply> {
+
+    private final VersionConvertorData data;
+
+    public GroupDirectStatisticsService(final RequestContextStack requestContextStack,
+                                        final DeviceContext deviceContext,
+                                        final ConvertorExecutor convertorExecutor,
+                                        final MultipartWriterProvider statisticsWriterProvider) {
+        super(requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider);
+        data = new VersionConvertorData(getVersion());
+    }
+
+    @Override
+    protected GetGroupStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
+        final List<GroupStats> groupStats = new ArrayList<>();
+
+        if (success) {
+            for (final MultipartReply mpReply : input) {
+                final MultipartReplyGroupCase caseBody = (MultipartReplyGroupCase) mpReply.getMultipartReplyBody();
+                final MultipartReplyGroup replyBody = caseBody.getMultipartReplyGroup();
+                final Optional<List<GroupStats>> groupStatsList = getConvertorExecutor().convert(
+                        replyBody.getGroupStats(), data);
+
+                groupStatsList.ifPresent(groupStats::addAll);
+            }
+        }
+
+        return new GetGroupStatisticsOutputBuilder()
+                .setGroupStats(groupStats)
+                .build();
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/MeterDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/MeterDirectStatisticsService.java
new file mode 100644 (file)
index 0000000..6b8c70c
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics.services.direct.multilayer;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractMeterDirectStatisticsService;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter._case.MultipartReplyMeter;
+
+public class MeterDirectStatisticsService extends AbstractMeterDirectStatisticsService<MultipartReply> {
+
+    private final VersionConvertorData data;
+
+    public MeterDirectStatisticsService(final RequestContextStack requestContextStack,
+                                        final DeviceContext deviceContext,
+                                        final ConvertorExecutor convertorExecutor,
+                                        final MultipartWriterProvider statisticsWriterProvider) {
+        super(requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider);
+        data = new VersionConvertorData(getVersion());
+    }
+
+    @Override
+    protected GetMeterStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
+        final List<MeterStats> meterStats = new ArrayList<>();
+
+        if (success) {
+            for (final MultipartReply mpReply : input) {
+                final MultipartReplyMeterCase caseBody = (MultipartReplyMeterCase) mpReply.getMultipartReplyBody();
+                final MultipartReplyMeter replyBody = caseBody.getMultipartReplyMeter();
+                final Optional<List<MeterStats>> meterStatsList = getConvertorExecutor().convert(replyBody.getMeterStats(), data);
+                meterStatsList.ifPresent(meterStats::addAll);
+            }
+        }
+
+        return new GetMeterStatisticsOutputBuilder()
+            .setMeterStats(meterStats)
+            .build();
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/MultiLayerDirectStatisticsProviderInitializer.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/MultiLayerDirectStatisticsProviderInitializer.java
new file mode 100644 (file)
index 0000000..c82643f
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics.services.direct.multilayer;
+
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractFlowDirectStatisticsService;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractGroupDirectStatisticsService;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractMeterDirectStatisticsService;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractPortDirectStatisticsService;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractQueueDirectStatisticsService;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.OpendaylightDirectStatisticsServiceProvider;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+
+/**
+ * Utility class for instantiating #{@link org.opendaylight.openflowplugin.impl.statistics.services.direct.OpendaylightDirectStatisticsServiceProvider}
+ * with all multi-layer services already in
+ */
+public class MultiLayerDirectStatisticsProviderInitializer {
+
+    public static OpendaylightDirectStatisticsServiceProvider createProvider(
+        final RequestContextStack requestContextStack,
+        final DeviceContext deviceContext,
+        final ConvertorExecutor convertorExecutor,
+        final MultipartWriterProvider statisticsWriterProvider) {
+
+        final OpendaylightDirectStatisticsServiceProvider provider = new OpendaylightDirectStatisticsServiceProvider();
+
+        provider.register(AbstractFlowDirectStatisticsService.class, new FlowDirectStatisticsService(
+            requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider));
+        provider.register(AbstractGroupDirectStatisticsService.class, new FlowDirectStatisticsService(
+            requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider));
+        provider.register(AbstractMeterDirectStatisticsService.class, new MeterDirectStatisticsService(
+            requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider));
+        provider.register(AbstractPortDirectStatisticsService.class, new PortDirectStatisticsService(
+            requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider));
+        provider.register(AbstractQueueDirectStatisticsService.class, new QueueDirectStatisticsService(
+            requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider));
+
+        return provider;
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/PortDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/PortDirectStatisticsService.java
new file mode 100644 (file)
index 0000000..2d447e9
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics.services.direct.multilayer;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractPortDirectStatisticsService;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.duration.DurationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.BytesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.PacketsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortStatsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.MultipartReplyPortStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.multipart.reply.port.stats.PortStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapKey;
+
+public class PortDirectStatisticsService extends AbstractPortDirectStatisticsService<MultipartReply> {
+
+    public PortDirectStatisticsService(final RequestContextStack requestContextStack,
+                                       final DeviceContext deviceContext,
+                                       final ConvertorExecutor convertorExecutor,
+                                       final MultipartWriterProvider statisticsWriterProvider) {
+        super(requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider);
+    }
+
+    @Override
+    protected GetNodeConnectorStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
+        final List<NodeConnectorStatisticsAndPortNumberMap> nodeConnectorStatisticsAndPortNumberMap = new ArrayList<>();
+
+        if (success) {
+            for (final MultipartReply mpReply : input) {
+                final MultipartReplyPortStatsCase caseBody = (MultipartReplyPortStatsCase) mpReply.getMultipartReplyBody();
+                final MultipartReplyPortStats replyBody = caseBody.getMultipartReplyPortStats();
+
+                for (final PortStats portStats : replyBody.getPortStats()) {
+                    final NodeConnectorId nodeConnectorId = InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(
+                        getDatapathId(), portStats.getPortNo(), getOfVersion());
+
+                    final BytesBuilder bytesBuilder = new BytesBuilder()
+                        .setReceived(portStats.getRxBytes())
+                        .setTransmitted(portStats.getTxBytes());
+
+                    final PacketsBuilder packetsBuilder = new PacketsBuilder()
+                        .setReceived(portStats.getRxPackets())
+                        .setTransmitted(portStats.getTxPackets());
+
+                    final DurationBuilder durationBuilder = new DurationBuilder();
+
+                    if (portStats.getDurationSec() != null) {
+                        durationBuilder.setSecond(new Counter32(portStats.getDurationSec()));
+                    }
+
+                    if (portStats.getDurationNsec() != null) {
+                        durationBuilder.setNanosecond(new Counter32(portStats.getDurationNsec()));
+                    }
+
+                    final NodeConnectorStatisticsAndPortNumberMap stats = new NodeConnectorStatisticsAndPortNumberMapBuilder()
+                        .setBytes(bytesBuilder.build())
+                        .setPackets(packetsBuilder.build())
+                        .setNodeConnectorId(nodeConnectorId)
+                        .setDuration(durationBuilder.build())
+                        .setCollisionCount(portStats.getCollisions())
+                        .setKey(new NodeConnectorStatisticsAndPortNumberMapKey(nodeConnectorId))
+                        .setReceiveCrcError(portStats.getRxCrcErr()).setReceiveDrops(portStats.getRxDropped())
+                        .setReceiveErrors(portStats.getRxErrors())
+                        .setReceiveFrameError(portStats.getRxFrameErr())
+                        .setReceiveOverRunError(portStats.getRxOverErr())
+                        .setTransmitDrops(portStats.getTxDropped())
+                        .setTransmitErrors(portStats.getTxErrors())
+                        .build();
+
+                    nodeConnectorStatisticsAndPortNumberMap.add(stats);
+                }
+            }
+        }
+
+        return new GetNodeConnectorStatisticsOutputBuilder()
+            .setNodeConnectorStatisticsAndPortNumberMap(nodeConnectorStatisticsAndPortNumberMap)
+            .build();
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/QueueDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/multilayer/QueueDirectStatisticsService.java
new file mode 100644 (file)
index 0000000..3fd141f
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics.services.direct.multilayer;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractQueueDirectStatisticsService;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsOutputBuilder;
+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.model.statistics.types.rev130925.duration.DurationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyQueueCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.MultipartReplyQueue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.multipart.reply.queue.QueueStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMapKey;
+
+public class QueueDirectStatisticsService extends AbstractQueueDirectStatisticsService<MultipartReply> {
+
+    public QueueDirectStatisticsService(final RequestContextStack requestContextStack,
+                                        final DeviceContext deviceContext,
+                                        final ConvertorExecutor convertorExecutor,
+                                        final MultipartWriterProvider statisticsWriterProvider) {
+        super(requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider);
+    }
+
+    @Override
+    protected GetQueueStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
+        final List<QueueIdAndStatisticsMap> queueIdAndStatisticsMap = new ArrayList<>();
+
+        if (success) {
+            for (final MultipartReply mpReply : input) {
+                final MultipartReplyQueueCase caseBody = (MultipartReplyQueueCase) mpReply.getMultipartReplyBody();
+                final MultipartReplyQueue replyBody = caseBody.getMultipartReplyQueue();
+
+                for (final QueueStats queueStats : replyBody.getQueueStats()) {
+                    final DurationBuilder durationBuilder = new DurationBuilder()
+                        .setSecond(new Counter32(queueStats.getDurationSec()))
+                        .setNanosecond(new Counter32(queueStats.getDurationNsec()));
+
+                    final QueueId queueId = new QueueId(queueStats.getQueueId());
+                    final NodeConnectorId nodeConnectorId = InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(
+                        getDatapathId(), queueStats.getPortNo(), getOfVersion());
+
+                    final QueueIdAndStatisticsMapBuilder statsBuilder = new QueueIdAndStatisticsMapBuilder()
+                        .setKey(new QueueIdAndStatisticsMapKey(nodeConnectorId, queueId))
+                        .setNodeConnectorId(nodeConnectorId)
+                        .setTransmissionErrors(new Counter64(queueStats.getTxErrors()))
+                        .setTransmittedBytes(new Counter64(queueStats.getTxBytes()))
+                        .setTransmittedPackets(new Counter64(queueStats.getTxPackets()))
+                        .setQueueId(queueId)
+                        .setDuration(durationBuilder.build());
+
+                    queueIdAndStatisticsMap.add(statsBuilder.build());
+                }
+            }
+        }
+
+        return new GetQueueStatisticsOutputBuilder()
+            .setQueueIdAndStatisticsMap(queueIdAndStatisticsMap)
+            .build();
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/singlelayer/FlowDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/singlelayer/FlowDirectStatisticsService.java
new file mode 100644 (file)
index 0000000..e2e47be
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics.services.direct.singlelayer;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractFlowDirectStatisticsService;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowId;
+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.and.statistics.map.list.FlowAndStatisticsMapListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.multipart.reply.multipart.reply.body.MultipartReplyFlowStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply;
+
+public class FlowDirectStatisticsService extends AbstractFlowDirectStatisticsService<MultipartReply> {
+
+    public FlowDirectStatisticsService(final RequestContextStack requestContextStack,
+                                       final DeviceContext deviceContext,
+                                       final ConvertorExecutor convertorExecutor,
+                                       final MultipartWriterProvider statisticsWriterProvider) {
+        super(requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider);    }
+
+    @Override
+    protected GetFlowStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
+        return new GetFlowStatisticsOutputBuilder()
+            .setFlowAndStatisticsMapList(input
+                .stream()
+                .flatMap(multipartReply -> MultipartReplyFlowStats.class
+                    .cast(multipartReply.getMultipartReplyBody())
+                    .getFlowAndStatisticsMapList()
+                    .stream())
+                .map(flowAndStatisticsMapList -> {
+                    final FlowId flowId = new FlowId(generateFlowId(flowAndStatisticsMapList));
+                    return new FlowAndStatisticsMapListBuilder(flowAndStatisticsMapList)
+                        .setKey(new FlowAndStatisticsMapListKey(flowId))
+                        .setFlowId(flowId)
+                        .build();
+                })
+                .collect(Collectors.toList()))
+            .build();
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/singlelayer/GroupDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/singlelayer/GroupDirectStatisticsService.java
new file mode 100644 (file)
index 0000000..ec0a906
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics.services.direct.singlelayer;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractGroupDirectStatisticsService;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyGroupStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply;
+
+public class GroupDirectStatisticsService extends AbstractGroupDirectStatisticsService<MultipartReply> {
+
+    public GroupDirectStatisticsService(final RequestContextStack requestContextStack,
+                                        final DeviceContext deviceContext,
+                                        final ConvertorExecutor convertorExecutor,
+                                        final MultipartWriterProvider statisticsWriterProvider) {
+        super(requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider);
+    }
+
+    @Override
+    protected GetGroupStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
+        return new GetGroupStatisticsOutputBuilder()
+            .setGroupStats(input
+                .stream()
+                .flatMap(multipartReply -> MultipartReplyGroupStats.class
+                    .cast(multipartReply.getMultipartReplyBody())
+                    .getGroupStats()
+                    .stream())
+                .collect(Collectors.toList()))
+            .build();
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/singlelayer/MeterDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/singlelayer/MeterDirectStatisticsService.java
new file mode 100644 (file)
index 0000000..ba84cea
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics.services.direct.singlelayer;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractMeterDirectStatisticsService;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyMeterStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply;
+
+public class MeterDirectStatisticsService extends AbstractMeterDirectStatisticsService<MultipartReply> {
+
+    public MeterDirectStatisticsService(final RequestContextStack requestContextStack,
+                                        final DeviceContext deviceContext,
+                                        final ConvertorExecutor convertorExecutor,
+                                        final MultipartWriterProvider statisticsWriterProvider) {
+        super(requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider);
+    }
+
+    @Override
+    protected GetMeterStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
+        return  new GetMeterStatisticsOutputBuilder()
+            .setMeterStats(input
+                .stream()
+                .flatMap(multipartReply -> MultipartReplyMeterStats.class
+                    .cast(multipartReply.getMultipartReplyBody())
+                    .getMeterStats()
+                    .stream())
+                .collect(Collectors.toList()))
+            .build();
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/singlelayer/PortDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/singlelayer/PortDirectStatisticsService.java
new file mode 100644 (file)
index 0000000..a53a2ff
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics.services.direct.singlelayer;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractPortDirectStatisticsService;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.multipart.reply.multipart.reply.body.MultipartReplyPortStats;
+
+public class PortDirectStatisticsService extends AbstractPortDirectStatisticsService<MultipartReply> {
+
+    public PortDirectStatisticsService(final RequestContextStack requestContextStack,
+                                       final DeviceContext deviceContext,
+                                       final ConvertorExecutor convertorExecutor,
+                                       final MultipartWriterProvider statisticsWriterProvider) {
+        super(requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider);
+    }
+
+    @Override
+    protected GetNodeConnectorStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
+        return  new GetNodeConnectorStatisticsOutputBuilder()
+            .setNodeConnectorStatisticsAndPortNumberMap(input
+                .stream()
+                .flatMap(multipartReply -> MultipartReplyPortStats.class
+                    .cast(multipartReply.getMultipartReplyBody())
+                    .getNodeConnectorStatisticsAndPortNumberMap()
+                    .stream())
+                .collect(Collectors.toList()))
+            .build();
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/singlelayer/QueueDirectStatisticsService.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/singlelayer/QueueDirectStatisticsService.java
new file mode 100644 (file)
index 0000000..ed6438f
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics.services.direct.singlelayer;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractQueueDirectStatisticsService;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.multipart.reply.multipart.reply.body.MultipartReplyQueueStats;
+
+public class QueueDirectStatisticsService extends AbstractQueueDirectStatisticsService<MultipartReply> {
+
+    public QueueDirectStatisticsService(final RequestContextStack requestContextStack,
+                                        final DeviceContext deviceContext,
+                                        final ConvertorExecutor convertorExecutor,
+                                        final MultipartWriterProvider statisticsWriterProvider) {
+        super(requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider);
+    }
+
+    @Override
+    protected GetQueueStatisticsOutput buildReply(List<MultipartReply> input, boolean success) {
+        return  new GetQueueStatisticsOutputBuilder()
+            .setQueueIdAndStatisticsMap(input
+                .stream()
+                .flatMap(multipartReply -> MultipartReplyQueueStats.class
+                    .cast(multipartReply.getMultipartReplyBody())
+                    .getQueueIdAndStatisticsMap()
+                    .stream())
+                .collect(Collectors.toList()))
+            .build();
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/singlelayer/SingleLayerDirectStatisticsProviderInitializer.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/singlelayer/SingleLayerDirectStatisticsProviderInitializer.java
new file mode 100644 (file)
index 0000000..9749940
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics.services.direct.singlelayer;
+
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractFlowDirectStatisticsService;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractGroupDirectStatisticsService;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractMeterDirectStatisticsService;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractPortDirectStatisticsService;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractQueueDirectStatisticsService;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.OpendaylightDirectStatisticsServiceProvider;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+
+/**
+ * Utility class for instantiating #{@link org.opendaylight.openflowplugin.impl.statistics.services.direct.OpendaylightDirectStatisticsServiceProvider}
+ * with all multi-layer services already in
+ */
+public class SingleLayerDirectStatisticsProviderInitializer {
+
+    public static OpendaylightDirectStatisticsServiceProvider createProvider(
+        final RequestContextStack requestContextStack,
+        final DeviceContext deviceContext,
+        final ConvertorExecutor convertorExecutor,
+        final MultipartWriterProvider statisticsWriterProvider) {
+
+        final OpendaylightDirectStatisticsServiceProvider provider = new OpendaylightDirectStatisticsServiceProvider();
+
+        provider.register(AbstractFlowDirectStatisticsService.class, new FlowDirectStatisticsService(
+            requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider));
+        provider.register(AbstractGroupDirectStatisticsService.class, new FlowDirectStatisticsService(
+            requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider));
+        provider.register(AbstractMeterDirectStatisticsService.class, new MeterDirectStatisticsService(
+            requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider));
+        provider.register(AbstractPortDirectStatisticsService.class, new PortDirectStatisticsService(
+            requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider));
+        provider.register(AbstractQueueDirectStatisticsService.class, new QueueDirectStatisticsService(
+            requestContextStack, deviceContext, convertorExecutor, statisticsWriterProvider));
+
+        return provider;
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtil.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtil.java
new file mode 100644 (file)
index 0000000..c5f2f44
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2016 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.openflowplugin.impl.util;
+
+import java.net.InetSocketAddress;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.SwitchFeaturesUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.flow.node.SwitchFeatures;
+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.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutputBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DeviceInitializationUtil {
+
+    private static final Logger LOG = LoggerFactory.getLogger(DeviceInitializationUtil.class);
+
+    private DeviceInitializationUtil() {
+        // Hiding implicit constructor
+    }
+
+    /**
+     * Create specified number of empty tables on device
+     * FIXME: remove after ovs table features fix
+     * @param txFacade transaction facade
+     * @param deviceInfo device info
+     * @param nrOfTables number of tables
+     */
+    public static void makeEmptyTables(final TxFacade txFacade, final DeviceInfo deviceInfo, final Short nrOfTables) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("About to create {} empty tables for node {}.", nrOfTables, deviceInfo.getLOGValue());
+        }
+
+        for (int i = 0; i < nrOfTables; i++) {
+            try {
+                txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL,
+                    deviceInfo
+                        .getNodeInstanceIdentifier()
+                        .augmentation(FlowCapableNode.class)
+                        .child(Table.class, new TableKey((short) i)),
+                    new TableBuilder()
+                        .setId((short) i)
+                        .addAugmentation(
+                            FlowTableStatisticsData.class,
+                            new FlowTableStatisticsDataBuilder().build())
+                        .build());
+            } catch (final Exception e) {
+                LOG.debug("makeEmptyTables: Failed to write node {} to DS ", deviceInfo.getLOGValue(), e);
+            }
+        }
+    }
+
+    /**
+     * Retrieve ip address from connection
+     * @param connectionContext connection context
+     * @param instanceIdentifier instance identifier
+     * @return ip adress
+     */
+    public static IpAddress getIpAddress(final ConnectionContext connectionContext,
+                                         final InstanceIdentifier<Node> instanceIdentifier) {
+        final InetSocketAddress remoteAddress = connectionContext
+            .getConnectionAdapter()
+            .getRemoteAddress();
+
+        if (remoteAddress == null) {
+            LOG.warn("IP address of the node {} cannot be obtained. No connection with switch.", instanceIdentifier);
+            return null;
+        }
+
+        LOG.info("IP address of the node {} is: {}", instanceIdentifier, remoteAddress);
+        return IetfInetUtil.INSTANCE.ipAddressFor(remoteAddress.getAddress());
+    }
+
+    /**
+     * Retrieve switch features from connection
+     * @param connectionContext connection context
+     * @return switch features
+     */
+    public static SwitchFeatures getSwitchFeatures(final ConnectionContext connectionContext) {
+        return SwitchFeaturesUtil
+            .getInstance()
+            .buildSwitchFeatures(new GetFeaturesOutputBuilder(connectionContext
+                .getFeatures())
+                .build());
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtils.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtils.java
deleted file mode 100644 (file)
index 0bdbe08..0000000
+++ /dev/null
@@ -1,572 +0,0 @@
-/*
- * Copyright (c) 2016 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.openflowplugin.impl.util;
-
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.AsyncFunction;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
-import java.math.BigInteger;
-import java.net.InetSocketAddress;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.ExecutionException;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
-import org.opendaylight.openflowplugin.api.ConnectionException;
-import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
-import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
-import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
-import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
-import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
-import org.opendaylight.openflowplugin.impl.common.MultipartRequestInputFactory;
-import org.opendaylight.openflowplugin.impl.common.NodeStaticReplyTranslatorUtil;
-import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.SwitchFeaturesUtil;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
-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.group.statistics.rev131111.NodeGroupFeatures;
-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.NodeConnectorBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeatures;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.Capabilities;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.CapabilitiesV10;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortGrouping;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.MultipartReplyBody;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupFeaturesCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterFeaturesCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortDescCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyTableFeaturesCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDesc;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.features._case.MultipartReplyGroupFeatures;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter.features._case.MultipartReplyMeterFeatures;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.desc._case.MultipartReplyPortDesc;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table.features._case.MultipartReplyTableFeatures;
-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.table.types.rev131026.table.features.TableFeatures;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeaturesKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class DeviceInitializationUtils {
-
-    private static final Logger LOG = LoggerFactory.getLogger(DeviceInitializationUtils.class);
-
-    private DeviceInitializationUtils() {
-        // Hiding implicit constructor
-    }
-
-    /**
-     * InitializationNodeInformation is good to call only for MASTER otherwise we will have not empty transaction
-     * for every Cluster Node (SLAVE too) and we will get race-condition by closing Connection.
-     *
-     * @param deviceContext
-     * @param switchFeaturesMandatory
-     * @param convertorExecutor
-     */
-    public static void initializeNodeInformation(final DeviceContext deviceContext, final boolean switchFeaturesMandatory, final ConvertorExecutor convertorExecutor) throws ExecutionException, InterruptedException {
-        Preconditions.checkArgument(deviceContext != null);
-        final DeviceState deviceState = Preconditions.checkNotNull(deviceContext.getDeviceState());
-        final DeviceInfo deviceInfo = deviceContext.getDeviceInfo();
-        final ConnectionContext connectionContext = Preconditions.checkNotNull(deviceContext.getPrimaryConnectionContext());
-        final short version = deviceInfo.getVersion();
-        LOG.trace("initalizeNodeInformation for node {}", deviceInfo.getNodeId());
-        final SettableFuture<Void> returnFuture = SettableFuture.create();
-        addNodeToOperDS(deviceContext, returnFuture);
-        final ListenableFuture<List<RpcResult<List<MultipartReply>>>> deviceFeaturesFuture;
-        if (OFConstants.OFP_VERSION_1_0 == version) {
-            final CapabilitiesV10 capabilitiesV10 = connectionContext.getFeatures().getCapabilitiesV10();
-
-            DeviceStateUtil.setDeviceStateBasedOnV10Capabilities(deviceState, capabilitiesV10);
-
-            deviceFeaturesFuture = createDeviceFeaturesForOF10(deviceContext);
-            // create empty tables after device description is processed
-            chainTableTrunkWriteOF10(deviceContext, deviceFeaturesFuture);
-
-            final short ofVersion = deviceInfo.getVersion();
-            final TranslatorKey translatorKey = new TranslatorKey(ofVersion, PortGrouping.class.getName());
-            final MessageTranslator<PortGrouping, FlowCapableNodeConnector> translator = deviceContext.oook()
-                    .lookupTranslator(translatorKey);
-            final BigInteger dataPathId = deviceContext.getDeviceInfo().getDatapathId();
-
-            for (final PortGrouping port : connectionContext.getFeatures().getPhyPort()) {
-                final FlowCapableNodeConnector fcNodeConnector = translator.translate(port, deviceContext.getDeviceInfo(), null);
-
-                final NodeConnectorId nodeConnectorId = NodeStaticReplyTranslatorUtil.nodeConnectorId(
-                        dataPathId.toString(), port.getPortNo(), ofVersion);
-                final NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder().setId(nodeConnectorId);
-                ncBuilder.addAugmentation(FlowCapableNodeConnector.class, fcNodeConnector);
-                ncBuilder.addAugmentation(FlowCapableNodeConnectorStatisticsData.class,
-                        new FlowCapableNodeConnectorStatisticsDataBuilder().build());
-                final NodeConnector connector = ncBuilder.build();
-                final InstanceIdentifier<NodeConnector> connectorII = deviceInfo.getNodeInstanceIdentifier().child(
-                        NodeConnector.class, connector.getKey());
-                try {
-                    deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, connectorII, connector);
-                } catch (final Exception e) {
-                    LOG.debug("initializeNodeInformation: Failed to write node {} to DS ", deviceInfo.getNodeId().toString(),
-                            e);
-                }
-
-            }
-        } else if (OFConstants.OFP_VERSION_1_3 == version) {
-            final Capabilities capabilities = connectionContext.getFeatures().getCapabilities();
-            LOG.debug("Setting capabilities for device {}", deviceInfo.getNodeId());
-            DeviceStateUtil.setDeviceStateBasedOnV13Capabilities(deviceState, capabilities);
-            createDeviceFeaturesForOF13(deviceContext, switchFeaturesMandatory, convertorExecutor).get();
-        } else {
-            throw new ExecutionException(new ConnectionException("Unsupported version " + version));
-        }
-
-    }
-
-    private static void addNodeToOperDS(final DeviceContext deviceContext, final SettableFuture<Void> future) {
-        Preconditions.checkArgument(deviceContext != null);
-        final NodeBuilder nodeBuilder = new NodeBuilder().setId(deviceContext.getDeviceInfo().getNodeId()).setNodeConnector(
-                Collections.emptyList());
-        try {
-            deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, deviceContext.getDeviceInfo().getNodeInstanceIdentifier(),
-                    nodeBuilder.build());
-        } catch (final Exception e) {
-            LOG.warn("addNodeToOperDS: Failed to write node {} to DS ", deviceContext.getDeviceInfo().getNodeId(), e);
-            future.cancel(true);
-        }
-    }
-
-    private static ListenableFuture<List<RpcResult<List<MultipartReply>>>> createDeviceFeaturesForOF10(
-            final DeviceContext deviceContext) {
-        final ListenableFuture<RpcResult<List<MultipartReply>>> replyDesc = getNodeStaticInfo(MultipartType.OFPMPDESC,
-                deviceContext, deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), deviceContext.getDeviceInfo().getVersion());
-
-        return Futures.allAsList(Arrays.asList(replyDesc));
-    }
-
-    private static ListenableFuture<List<RpcResult<List<MultipartReply>>>> createDeviceFeaturesForOF13(
-            final DeviceContext deviceContext, final boolean switchFeaturesMandatory, final ConvertorExecutor convertorExecutor) {
-
-        final ListenableFuture<RpcResult<List<MultipartReply>>> replyDesc = getNodeStaticInfo(MultipartType.OFPMPDESC,
-                deviceContext, deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), deviceContext.getDeviceInfo().getVersion());
-
-        //first process description reply, write data to DS and write consequent data if successful
-        return Futures.transform(replyDesc,
-                new AsyncFunction<RpcResult<List<MultipartReply>>, List<RpcResult<List<MultipartReply>>>>() {
-                    @Override
-                    public ListenableFuture<List<RpcResult<List<MultipartReply>>>> apply(
-                            final RpcResult<List<MultipartReply>> rpcResult) throws Exception {
-
-                        translateAndWriteReply(MultipartType.OFPMPDESC, deviceContext,
-                                deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), rpcResult.getResult(), convertorExecutor);
-
-                        final ListenableFuture<RpcResult<List<MultipartReply>>> replyMeterFeature = getNodeStaticInfo(
-                                MultipartType.OFPMPMETERFEATURES, deviceContext,
-                                deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), deviceContext.getDeviceInfo().getVersion());
-
-                        createSuccessProcessingCallback(MultipartType.OFPMPMETERFEATURES, deviceContext,
-                                deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), replyMeterFeature, convertorExecutor);
-
-                        final ListenableFuture<RpcResult<List<MultipartReply>>> replyGroupFeatures = getNodeStaticInfo(
-                                MultipartType.OFPMPGROUPFEATURES, deviceContext,
-                                deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), deviceContext.getDeviceInfo().getVersion());
-                        createSuccessProcessingCallback(MultipartType.OFPMPGROUPFEATURES, deviceContext,
-                                deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), replyGroupFeatures, convertorExecutor);
-
-                        final ListenableFuture<RpcResult<List<MultipartReply>>> replyTableFeatures;
-
-                        if (deviceContext.isSkipTableFeatures()) {
-                            replyTableFeatures = RpcResultBuilder.<List<MultipartReply>>success().buildFuture();
-                        } else {
-                            replyTableFeatures = getNodeStaticInfo(
-                                    MultipartType.OFPMPTABLEFEATURES, deviceContext,
-                                    deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), deviceContext.getDeviceInfo().getVersion());
-                        }
-                        createSuccessProcessingCallback(MultipartType.OFPMPTABLEFEATURES, deviceContext,
-                                deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), replyTableFeatures, convertorExecutor);
-
-                        final ListenableFuture<RpcResult<List<MultipartReply>>> replyPortDescription = getNodeStaticInfo(
-                                MultipartType.OFPMPPORTDESC, deviceContext, deviceContext.getDeviceInfo().getNodeInstanceIdentifier(),
-                                deviceContext.getDeviceInfo().getVersion());
-                        createSuccessProcessingCallback(MultipartType.OFPMPPORTDESC, deviceContext,
-                                deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), replyPortDescription, convertorExecutor);
-                        if (switchFeaturesMandatory) {
-                            return Futures.allAsList(Arrays.asList(replyMeterFeature, replyGroupFeatures,
-                                    replyTableFeatures, replyPortDescription));
-                        } else {
-                            return Futures.successfulAsList(Arrays.asList(replyMeterFeature, replyGroupFeatures,
-                                    replyTableFeatures, replyPortDescription));
-                        }
-                    }
-                });
-
-    }
-
-    static void translateAndWriteReply(final MultipartType type, final DeviceContext dContext,
-                                       final InstanceIdentifier<Node> nodeII, final Collection<MultipartReply> result,
-                                       final ConvertorExecutor convertorExecutor) {
-        if (Objects.nonNull(result)) {
-            try {
-                result.stream()
-                        .map(MultipartReply::getMultipartReplyBody)
-                        .forEach(multipartReplyBody -> {
-                            if (!(writeDesc(type, multipartReplyBody, dContext, nodeII)
-                                    || writeTableFeatures(type, multipartReplyBody, dContext, nodeII, convertorExecutor)
-                                    || writeMeterFeatures(type, multipartReplyBody, dContext, nodeII)
-                                    || writeGroupFeatures(type, multipartReplyBody, dContext, nodeII)
-                                    || writePortDesc(type, multipartReplyBody, dContext, nodeII))) {
-                                throw new IllegalArgumentException("Unexpected MultipartType " + type);
-                            }
-                        });
-            } catch (final Exception e) {
-                LOG.debug("translateAndWriteReply: Failed to write node {} to DS ", dContext.getDeviceInfo().getNodeId().toString(), e);
-            }
-        } else {
-            LOG.debug("translateAndWriteReply: Failed to write node {} to DS because we failed to gather device" +
-                            "info.",
-                    dContext.getDeviceInfo().getNodeId().toString());
-        }
-    }
-
-    private static boolean writeDesc(final MultipartType type,
-                                     final MultipartReplyBody body,
-                                     final DeviceContext dContext,
-                                     final InstanceIdentifier<Node> nodeII) {
-        if (!MultipartType.OFPMPDESC.equals(type)) {
-            return false;
-        }
-
-        Preconditions.checkArgument(body instanceof MultipartReplyDescCase);
-        final MultipartReplyDesc replyDesc = ((MultipartReplyDescCase) body).getMultipartReplyDesc();
-        final FlowCapableNode fcNode = NodeStaticReplyTranslatorUtil
-                .nodeDescTranslator(replyDesc, getIpAddressOf(dContext))
-                .setSwitchFeatures(SwitchFeaturesUtil.getInstance().buildSwitchFeatures(
-                        new GetFeaturesOutputBuilder(dContext.getPrimaryConnectionContext().getFeatures()).build()))
-                .build();
-
-        final InstanceIdentifier<FlowCapableNode> fNodeII = nodeII.augmentation(FlowCapableNode.class);
-        dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, fNodeII, fcNode);
-        return true;
-    }
-
-    private static boolean writeTableFeatures(final MultipartType type,
-                                              final MultipartReplyBody body,
-                                              final DeviceContext dContext,
-                                              final InstanceIdentifier<Node> nodeII,
-                                              final ConvertorExecutor convertorExecutor) {
-        if (!MultipartType.OFPMPTABLEFEATURES.equals(type)) {
-            return false;
-        }
-
-        Preconditions.checkArgument(body instanceof MultipartReplyTableFeaturesCase);
-        final MultipartReplyTableFeatures tableFeaturesMP = ((MultipartReplyTableFeaturesCase) body)
-                .getMultipartReplyTableFeatures();
-        final List<TableFeatures> tableFeatures = NodeStaticReplyTranslatorUtil
-                .nodeTableFeatureTranslator(tableFeaturesMP, dContext.getDeviceInfo().getVersion(), convertorExecutor);
-        for (final TableFeatures tableFeature : tableFeatures) {
-            final Short tableId = tableFeature.getTableId();
-            final KeyedInstanceIdentifier<TableFeatures, TableFeaturesKey> tableFeaturesII =
-                    nodeII.augmentation(FlowCapableNode.class)
-                            .child(TableFeatures.class, new TableFeaturesKey(tableId));
-            dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, tableFeaturesII, tableFeature);
-
-            // write parent for table statistics
-            final KeyedInstanceIdentifier<Table, TableKey> tableII =
-                    nodeII.augmentation(FlowCapableNode.class)
-                            .child(Table.class, new TableKey(tableId));
-            final TableBuilder tableBld = new TableBuilder().setId(tableId)
-                    .addAugmentation(FlowTableStatisticsData.class,
-                            new FlowTableStatisticsDataBuilder().build());
-
-            dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, tableII, tableBld.build());
-        }
-
-        return true;
-    }
-
-    private static boolean writeMeterFeatures(final MultipartType type,
-                                              final MultipartReplyBody body,
-                                              final DeviceContext dContext,
-                                              final InstanceIdentifier<Node> nodeII) {
-        if (!MultipartType.OFPMPMETERFEATURES.equals(type)) {
-            return false;
-        }
-
-        Preconditions.checkArgument(body instanceof MultipartReplyMeterFeaturesCase);
-        final MultipartReplyMeterFeatures meterFeatures = ((MultipartReplyMeterFeaturesCase) body)
-                .getMultipartReplyMeterFeatures();
-        final NodeMeterFeatures mFeature = NodeStaticReplyTranslatorUtil
-                .nodeMeterFeatureTranslator(meterFeatures);
-        final InstanceIdentifier<NodeMeterFeatures> mFeatureII = nodeII
-                .augmentation(NodeMeterFeatures.class);
-        dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, mFeatureII, mFeature);
-        if (0L < mFeature.getMeterFeatures().getMaxMeter().getValue()) {
-            dContext.getDeviceState().setMeterAvailable(true);
-        }
-
-        return true;
-    }
-
-    private static boolean writeGroupFeatures(final MultipartType type,
-                                              final MultipartReplyBody body,
-                                              final DeviceContext dContext,
-                                              final InstanceIdentifier<Node> nodeII) {
-        if (!MultipartType.OFPMPGROUPFEATURES.equals(type)) {
-            return false;
-        }
-
-        Preconditions.checkArgument(body instanceof MultipartReplyGroupFeaturesCase);
-        final MultipartReplyGroupFeatures groupFeatures = ((MultipartReplyGroupFeaturesCase) body)
-                .getMultipartReplyGroupFeatures();
-        final NodeGroupFeatures gFeature = NodeStaticReplyTranslatorUtil
-                .nodeGroupFeatureTranslator(groupFeatures);
-        final InstanceIdentifier<NodeGroupFeatures> gFeatureII = nodeII
-                .augmentation(NodeGroupFeatures.class);
-        dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, gFeatureII, gFeature);
-
-        return true;
-    }
-
-    private static boolean writePortDesc(final MultipartType type,
-                                         final MultipartReplyBody body,
-                                         final DeviceContext dContext,
-                                         final InstanceIdentifier<Node> nodeII) {
-        if (!MultipartType.OFPMPPORTDESC.equals(type)) {
-            return false;
-        }
-
-        Preconditions.checkArgument(body instanceof MultipartReplyPortDescCase);
-        final MultipartReplyPortDesc portDesc = ((MultipartReplyPortDescCase) body)
-                .getMultipartReplyPortDesc();
-        for (final PortGrouping port : portDesc.getPorts()) {
-            final short ofVersion = dContext.getDeviceInfo().getVersion();
-            final TranslatorKey translatorKey = new TranslatorKey(ofVersion, PortGrouping.class.getName());
-            final MessageTranslator<PortGrouping, FlowCapableNodeConnector> translator = dContext.oook()
-                    .lookupTranslator(translatorKey);
-            final FlowCapableNodeConnector fcNodeConnector = translator.translate(port, dContext.getDeviceInfo(), null);
-
-            final BigInteger dataPathId = dContext.getPrimaryConnectionContext().getFeatures()
-                    .getDatapathId();
-            final NodeConnectorId nodeConnectorId = NodeStaticReplyTranslatorUtil.nodeConnectorId(
-                    dataPathId.toString(), port.getPortNo(), ofVersion);
-            final NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder().setId(nodeConnectorId);
-            ncBuilder.addAugmentation(FlowCapableNodeConnector.class, fcNodeConnector);
-
-            ncBuilder.addAugmentation(FlowCapableNodeConnectorStatisticsData.class,
-                    new FlowCapableNodeConnectorStatisticsDataBuilder().build());
-            final NodeConnector connector = ncBuilder.build();
-
-            final InstanceIdentifier<NodeConnector> connectorII = nodeII.child(NodeConnector.class,
-                    connector.getKey());
-            dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, connectorII, connector);
-        }
-
-        return true;
-    }
-
-    private static void createEmptyFlowCapableNodeInDs(final DeviceContext deviceContext) {
-        final FlowCapableNodeBuilder flowCapableNodeBuilder = new FlowCapableNodeBuilder();
-        final InstanceIdentifier<FlowCapableNode> fNodeII = deviceContext.getDeviceInfo().getNodeInstanceIdentifier()
-                .augmentation(FlowCapableNode.class);
-        try {
-            deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, fNodeII, flowCapableNodeBuilder.build());
-        } catch (final Exception e) {
-            LOG.debug("createEmptyFlowCapableNodeInDs: Failed to write node {} to DS ", deviceContext.getDeviceInfo().getNodeId().toString(), e);
-        }
-    }
-
-    private static IpAddress getIpAddressOf(final DeviceContext deviceContext) {
-
-        final InetSocketAddress remoteAddress = deviceContext.getPrimaryConnectionContext().getConnectionAdapter()
-                .getRemoteAddress();
-
-        if (remoteAddress == null) {
-            LOG.warn("IP address of the node {} cannot be obtained. No connection with switch.", deviceContext
-                    .getDeviceInfo().getNodeId());
-            return null;
-        }
-        LOG.info("IP address of switch is: {}", remoteAddress);
-
-        return IetfInetUtil.INSTANCE.ipAddressFor(remoteAddress.getAddress());
-    }
-
-    // FIXME : remove after ovs tableFeatures fix
-    private static void makeEmptyTables(final DeviceContext dContext, final InstanceIdentifier<Node> nodeII,
-                                        final Short nrOfTables) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("About to create {} empty tables.", nrOfTables);
-        }
-        for (int i = 0; i < nrOfTables; i++) {
-            final short tId = (short) i;
-            final InstanceIdentifier<Table> tableII = nodeII.augmentation(FlowCapableNode.class).child(Table.class,
-                    new TableKey(tId));
-            final TableBuilder tableBuilder = new TableBuilder().setId(tId).addAugmentation(
-                    FlowTableStatisticsData.class, new FlowTableStatisticsDataBuilder().build());
-
-            try {
-                dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, tableII, tableBuilder.build());
-            } catch (final Exception e) {
-                LOG.debug("makeEmptyTables: Failed to write node {} to DS ", dContext.getDeviceInfo().getNodeId().toString(), e);
-            }
-
-        }
-    }
-
-    static void createSuccessProcessingCallback(final MultipartType type, final DeviceContext deviceContext,
-                                                final InstanceIdentifier<Node> nodeII,
-                                                final ListenableFuture<RpcResult<List<MultipartReply>>> requestContextFuture,
-                                                final ConvertorExecutor convertorExecutor) {
-        Futures.addCallback(requestContextFuture, new FutureCallback<RpcResult<List<MultipartReply>>>() {
-            @Override
-            public void onSuccess(final RpcResult<List<MultipartReply>> rpcResult) {
-                final List<MultipartReply> result = rpcResult.getResult();
-                if (result != null) {
-                    LOG.info("Static node {} info: {} collected", deviceContext.getDeviceInfo().getNodeId(), type);
-                    translateAndWriteReply(type, deviceContext, nodeII, result, convertorExecutor);
-                } else {
-                    for (RpcError rpcError : rpcResult.getErrors()) {
-                        LOG.info("Failed to retrieve static node {} info: {}", type, rpcError.getMessage());
-                        if (LOG.isTraceEnabled() && Objects.nonNull(rpcError.getCause())) {
-                            LOG.trace("Detailed error:", rpcError.getCause());
-                        }
-                    }
-                    if (MultipartType.OFPMPTABLEFEATURES.equals(type)) {
-                        makeEmptyTables(deviceContext, nodeII, deviceContext.getPrimaryConnectionContext()
-                                .getFeatures().getTables());
-                    }
-                }
-            }
-
-            @Override
-            public void onFailure(final Throwable throwable) {
-                LOG.info("Request of type {} for static info of node {} failed.", type, nodeII);
-            }
-        });
-    }
-
-    private static ListenableFuture<RpcResult<List<MultipartReply>>> getNodeStaticInfo(final MultipartType type,
-                                                                                       final DeviceContext deviceContext,
-                                                                                       final InstanceIdentifier<Node> nodeII,
-                                                                                       final short version) {
-
-        final OutboundQueue queue = deviceContext.getPrimaryConnectionContext().getOutboundQueueProvider();
-
-        final Long reserved = deviceContext.getDeviceInfo().reserveXidForDeviceMessage();
-        final RequestContext<List<MultipartReply>> requestContext = new AbstractRequestContext<List<MultipartReply>>(
-                reserved) {
-            @Override
-            public void close() {
-                //NOOP
-            }
-        };
-
-        final Xid xid = requestContext.getXid();
-
-        if (Objects.isNull(xid)) {
-            LOG.debug("Xid is not present, so cancelling node static info gathering.");
-            return Futures.immediateCancelledFuture();
-        }
-
-        LOG.trace("Hooking xid {} to device context - precaution.", reserved);
-
-        final MultiMsgCollector multiMsgCollector = deviceContext.getMultiMsgCollector(requestContext);
-        queue.commitEntry(xid.getValue(),
-                MultipartRequestInputFactory.makeMultipartRequestInput(xid.getValue(), version, type),
-                new FutureCallback<OfHeader>() {
-                    @Override
-                    public void onSuccess(final OfHeader ofHeader) {
-                        if (ofHeader instanceof MultipartReply) {
-                            final MultipartReply multipartReply = (MultipartReply) ofHeader;
-                            multiMsgCollector.addMultipartMsg(multipartReply);
-                        } else if (null != ofHeader) {
-                            LOG.info("Unexpected response type received {}.", ofHeader.getClass());
-                        } else {
-                            multiMsgCollector.endCollecting();
-                            LOG.info("Response received is null.");
-                        }
-                    }
-
-                    @Override
-                    public void onFailure(final Throwable t) {
-                        LOG.info("Fail response from OutboundQueue for multipart type {}.", type);
-                        final RpcResult<List<MultipartReply>> rpcResult = RpcResultBuilder
-                                .<List<MultipartReply>>failed().build();
-                        requestContext.setResult(rpcResult);
-                        if (MultipartType.OFPMPTABLEFEATURES.equals(type)) {
-                            makeEmptyTables(deviceContext, nodeII, deviceContext.getPrimaryConnectionContext()
-                                    .getFeatures().getTables());
-                        }
-                        requestContext.close();
-                    }
-                });
-
-        return requestContext.getFuture();
-    }
-
-    static void chainTableTrunkWriteOF10(final DeviceContext deviceContext,
-                                         final ListenableFuture<List<RpcResult<List<MultipartReply>>>> deviceFeaturesFuture) {
-
-        try {
-            if (LOG.isTraceEnabled()) {
-                LOG.trace("Waiting for protocol version 1.0");
-            }
-            List<RpcResult<List<MultipartReply>>> results = deviceFeaturesFuture.get();
-            boolean allSucceeded = true;
-            for (final RpcResult<List<MultipartReply>> rpcResult : results) {
-                allSucceeded &= rpcResult.isSuccessful();
-            }
-            if (allSucceeded) {
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("Creating empty flow capable node: {}", deviceContext.getDeviceInfo().getLOGValue());
-                }
-                createEmptyFlowCapableNodeInDs(deviceContext);
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("Creating empty tables for {}", deviceContext.getDeviceInfo().getLOGValue());
-                }
-                makeEmptyTables(deviceContext, deviceContext.getDeviceInfo().getNodeInstanceIdentifier(),
-                        deviceContext.getPrimaryConnectionContext().getFeatures().getTables());
-            }
-        } catch (InterruptedException | ExecutionException e) {
-            LOG.warn("Error occurred in preparation node {} for protocol 1.0", deviceContext.getDeviceInfo().getLOGValue());
-            if (LOG.isTraceEnabled()) {
-                LOG.trace("Error for node {} : ", deviceContext.getDeviceInfo().getLOGValue(), e);
-            }
-        }
-    }
-}
index 781776ad70eed29cc02fbe3d5369600ecac3b761..aa11506cb3be7c4426183927627a183e8c3f3557 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -16,21 +16,23 @@ import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
 import org.opendaylight.openflowplugin.api.openflow.statistics.compatibility.Delegator;
 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
-import org.opendaylight.openflowplugin.impl.services.FlowCapableTransactionServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.NodeConfigServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.PacketProcessingServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.SalEchoServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.SalExperimenterMessageServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.SalExperimenterMpMessageServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.SalFlatBatchServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.SalFlowServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.SalFlowsBatchServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.SalGroupServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.SalGroupsBatchServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.SalMeterServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.SalMetersBatchServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.SalPortServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.SalTableServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.FlowCapableTransactionServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.NodeConfigServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.PacketProcessingServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.SalEchoServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.SalExperimenterMessageServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.SalExperimenterMpMessageServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.SalFlatBatchServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.SalFlowServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.SalFlowsBatchServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.SalGroupServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.SalGroupsBatchServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.SalMeterServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.SalMetersBatchServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.SalPortServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.SalTableServiceImpl;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProviderFactory;
 import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightFlowStatisticsServiceImpl;
 import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightFlowTableStatisticsServiceImpl;
 import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightGroupStatisticsServiceImpl;
@@ -38,13 +40,9 @@ import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightMete
 import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightPortStatisticsServiceImpl;
 import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightQueueStatisticsServiceImpl;
 import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.OpendaylightFlowStatisticsServiceDelegateImpl;
-import org.opendaylight.openflowplugin.impl.statistics.services.direct.FlowDirectStatisticsService;
-import org.opendaylight.openflowplugin.impl.statistics.services.direct.GroupDirectStatisticsService;
-import org.opendaylight.openflowplugin.impl.statistics.services.direct.MeterDirectStatisticsService;
-import org.opendaylight.openflowplugin.impl.statistics.services.direct.NodeConnectorDirectStatisticsService;
 import org.opendaylight.openflowplugin.impl.statistics.services.direct.OpendaylightDirectStatisticsServiceImpl;
-import org.opendaylight.openflowplugin.impl.statistics.services.direct.OpendaylightDirectStatisticsServiceProvider;
-import org.opendaylight.openflowplugin.impl.statistics.services.direct.QueueDirectStatisticsService;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.multilayer.MultiLayerDirectStatisticsProviderInitializer;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.singlelayer.SingleLayerDirectStatisticsProviderInitializer;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.OpendaylightDirectStatisticsService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.echo.service.rev150305.SalEchoService;
@@ -84,7 +82,7 @@ public class MdSalRegistrationUtils {
      * Method registers all OF services for role {@link OfpRole#BECOMEMASTER}
      *  @param rpcContext    - registration processing is implemented in {@link org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext}
      * @param deviceContext - every service needs {@link org.opendaylight.openflowplugin.api.openflow.device.DeviceContext} as input parameter
-     * @param convertorExecutor
+     * @param convertorExecutor convertor executor
      */
     public static void registerServices(@CheckForNull final RpcContext rpcContext,
                                         @CheckForNull final DeviceContext deviceContext,
@@ -93,6 +91,10 @@ public class MdSalRegistrationUtils {
         Preconditions.checkArgument(rpcContext != null);
         Preconditions.checkArgument(deviceContext != null);
 
+        // TODO: Use multipart writer provider from device context
+        final MultipartWriterProvider multipartWriterProvider = MultipartWriterProviderFactory
+            .createDefaultProvider(deviceContext);
+
         // create service instances
         final SalFlowServiceImpl salFlowService = new SalFlowServiceImpl(rpcContext, deviceContext, convertorExecutor);
         final FlowCapableTransactionServiceImpl flowCapableTransactionService = new FlowCapableTransactionServiceImpl(rpcContext, deviceContext);
@@ -105,20 +107,19 @@ public class MdSalRegistrationUtils {
         rpcContext.registerRpcServiceImplementation(FlowCapableTransactionService.class, flowCapableTransactionService);
         rpcContext.registerRpcServiceImplementation(SalMeterService.class, salMeterService);
         rpcContext.registerRpcServiceImplementation(SalGroupService.class, salGroupService);
-        rpcContext.registerRpcServiceImplementation(SalTableService.class, new SalTableServiceImpl(rpcContext, deviceContext, convertorExecutor));
+        rpcContext.registerRpcServiceImplementation(SalTableService.class, new SalTableServiceImpl(rpcContext, deviceContext, convertorExecutor, multipartWriterProvider));
         rpcContext.registerRpcServiceImplementation(SalPortService.class, new SalPortServiceImpl(rpcContext, deviceContext, convertorExecutor));
         rpcContext.registerRpcServiceImplementation(PacketProcessingService.class, new PacketProcessingServiceImpl(rpcContext, deviceContext, convertorExecutor));
         rpcContext.registerRpcServiceImplementation(NodeConfigService.class, new NodeConfigServiceImpl(rpcContext, deviceContext));
         rpcContext.registerRpcServiceImplementation(OpendaylightFlowStatisticsService.class, OpendaylightFlowStatisticsServiceImpl.createWithOook(rpcContext, deviceContext, convertorExecutor));
 
         // register direct statistics gathering services
-        final OpendaylightDirectStatisticsServiceProvider statisticsProvider = new OpendaylightDirectStatisticsServiceProvider();
-        statisticsProvider.register(FlowDirectStatisticsService.class, new FlowDirectStatisticsService(rpcContext, deviceContext, convertorExecutor));
-        statisticsProvider.register(GroupDirectStatisticsService.class, new GroupDirectStatisticsService(rpcContext, deviceContext, convertorExecutor));
-        statisticsProvider.register(MeterDirectStatisticsService.class, new MeterDirectStatisticsService(rpcContext, deviceContext, convertorExecutor));
-        statisticsProvider.register(NodeConnectorDirectStatisticsService.class, new NodeConnectorDirectStatisticsService(rpcContext, deviceContext, convertorExecutor));
-        statisticsProvider.register(QueueDirectStatisticsService.class, new QueueDirectStatisticsService(rpcContext, deviceContext, convertorExecutor));
-        rpcContext.registerRpcServiceImplementation(OpendaylightDirectStatisticsService.class, new OpendaylightDirectStatisticsServiceImpl(statisticsProvider));
+        rpcContext.registerRpcServiceImplementation(OpendaylightDirectStatisticsService.class,
+            new OpendaylightDirectStatisticsServiceImpl(deviceContext.canUseSingleLayerSerialization()
+                ? SingleLayerDirectStatisticsProviderInitializer
+                    .createProvider(rpcContext, deviceContext, convertorExecutor, multipartWriterProvider)
+                : MultiLayerDirectStatisticsProviderInitializer
+                    .createProvider(rpcContext, deviceContext, convertorExecutor, multipartWriterProvider)));
 
         // register flat batch services
         rpcContext.registerRpcServiceImplementation(SalFlatBatchService.class, new SalFlatBatchServiceImpl(
@@ -137,7 +138,7 @@ public class MdSalRegistrationUtils {
     /**
      * Support deprecated statistic related services for backward compatibility. The only exception from deprecation is
      * the aggregated flow statistic with match criteria input.
-     *  @param rpcContext
+     * @param rpcContext
      * @param deviceContext
      * @param notificationPublishService
      * @param convertorExecutor
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/common/NodeConnectorTranslatorUtilTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/common/NodeConnectorTranslatorUtilTest.java
deleted file mode 100644 (file)
index 6fe1d30..0000000
+++ /dev/null
@@ -1,323 +0,0 @@
-/**
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.openflowplugin.impl.common;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.math.BigInteger;
-import java.util.Arrays;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
-import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-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.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortConfig;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortConfigV10;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeatures;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeaturesV10;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortState;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortStateV10;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.features.reply.PhyPort;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * openflowplugin-impl
- * org.opendaylight.openflowplugin.impl.common
- *
- * Test class for testing {@link org.opendaylight.openflowplugin.impl.common.NodeConnectorTranslatorUtil}
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- * Created: Mar 31, 2015
- */
-public class NodeConnectorTranslatorUtilTest {
-
-    private static final Logger LOG = LoggerFactory.getLogger(NodeConnectorTranslatorUtilTest.class);
-
-    private static final String MAC_ADDRESS = "00:01:02:03:04:05";
-    private static final String NAME = "PortTranslatorTest";
-    private final Boolean[] pfBls = {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false};
-    private final boolean[] pfV10Bls = {false, false, false, false, false, false, false, false, false, false, false, false};
-    private final boolean[] portCfgBools = {false, false, false, false};
-    private final boolean[] portCfgV10bools = {false, false, false, false, false, false, false};
-    private final boolean[] portStateBools = {false, false, false, false};
-    private final Long currentSpeed = Long.decode("4294967295");
-    private static final Long maxSpeed = Long.decode("4294967295");
-
-    /**
-     * Test method for {@link NodeConnectorTranslatorUtil#translateNodeConnectorFromFeaturesReply(FeaturesReply)}.
-     */
-    @Test
-    public void testTranslateNodeConnectorFromFeaturesReply(){
-        final FeaturesReply reply = mock(FeaturesReply.class);
-        final BigInteger dataPathId = BigInteger.valueOf(25L);
-        final List<PhyPort> listPorts = Arrays.asList(mockPhyPortPort());
-        when(reply.getPhyPort()).thenReturn(listPorts);
-        when(reply.getDatapathId()).thenReturn(dataPathId);
-        when(reply.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
-        final List<NodeConnector> nodeConnector = NodeConnectorTranslatorUtil.translateNodeConnectorFromFeaturesReply(reply);
-        Assert.assertNotNull(nodeConnector);
-        Assert.assertEquals(1, nodeConnector.size());
-    }
-
-    /**
-     * Test method for {@link NodeConnectorTranslatorUtil#translateNodeConnectorFromFeaturesReply(FeaturesReply)}.
-     * {@link IllegalArgumentException}
-     */
-    @Test(expected=IllegalArgumentException.class)
-    public void testTranslateNodeConnectorFromFeaturesReplyNullPorts(){
-        final FeaturesReply reply = mock(FeaturesReply.class);
-        when(reply.getPhyPort()).thenReturn(null);
-        NodeConnectorTranslatorUtil.translateNodeConnectorFromFeaturesReply(reply);
-    }
-
-    /**
-     * Test method for {@link NodeConnectorTranslatorUtil#translateNodeConnectorFromFeaturesReply(FeaturesReply)}.
-     * {@link IllegalArgumentException}
-     */
-    @Test(expected=IllegalArgumentException.class)
-    public void testTranslateNodeConnectorFromFeaturesReplyNullReplay(){
-        NodeConnectorTranslatorUtil.translateNodeConnectorFromFeaturesReply(null);
-    }
-
-    /**
-     * Test method for {@link NodeConnectorTranslatorUtil#translateFlowCapableNodeFromPhyPort(PhyPort, short)}.
-     */
-    @Test
-    public void testTranslateFlowCapableNodeFromPhyPortOF10(){
-        final PhyPort port = mockPhyPortPort();
-        final FlowCapableNodeConnector flowCapableNodeConnector = NodeConnectorTranslatorUtil
-                .translateFlowCapableNodeFromPhyPort(port, OFConstants.OFP_VERSION_1_0);
-        Assert.assertNotNull(flowCapableNodeConnector);
-        Assert.assertEquals(port.getName(), flowCapableNodeConnector.getName());
-        Assert.assertEquals(port.getPortNo(), flowCapableNodeConnector.getPortNumber().getUint32());
-        Assert.assertEquals(port.getHwAddr().getValue(), flowCapableNodeConnector.getHardwareAddress().getValue());
-        Assert.assertEquals(port.getCurrSpeed(), flowCapableNodeConnector.getCurrentSpeed());
-        Assert.assertEquals(port.getMaxSpeed(), flowCapableNodeConnector.getMaximumSpeed());
-        assertEqualsStateV10(port.getStateV10(), flowCapableNodeConnector.getState());
-        assertEqualsPortFeaturesV10(port.getAdvertisedFeaturesV10(), flowCapableNodeConnector.getAdvertisedFeatures());
-        assertEqualsPortFeaturesV10(port.getCurrentFeaturesV10(), flowCapableNodeConnector.getCurrentFeature());
-        assertEqualsPortFeaturesV10(port.getPeerFeaturesV10(), flowCapableNodeConnector.getPeerFeatures());
-        assertEqualsPortFeaturesV10(port.getSupportedFeaturesV10(), flowCapableNodeConnector.getSupported());
-
-    }
-
-    /**
-     * Test method for {@link NodeConnectorTranslatorUtil#translateFlowCapableNodeFromPhyPort(PhyPort, short)}.
-     */
-    @Test
-    public void testTranslateFlowCapableNodeFromPhyPortOF13(){
-        final PhyPort port = mockPhyPortPort();
-        final FlowCapableNodeConnector flowCapableNodeConnector = NodeConnectorTranslatorUtil
-                .translateFlowCapableNodeFromPhyPort(port, OFConstants.OFP_VERSION_1_3);
-        Assert.assertNotNull(flowCapableNodeConnector);
-        Assert.assertEquals(port.getName(), flowCapableNodeConnector.getName());
-        Assert.assertEquals(port.getPortNo(), flowCapableNodeConnector.getPortNumber().getUint32());
-        Assert.assertEquals(port.getHwAddr().getValue(), flowCapableNodeConnector.getHardwareAddress().getValue());
-        Assert.assertEquals(port.getCurrSpeed(), flowCapableNodeConnector.getCurrentSpeed());
-        Assert.assertEquals(port.getMaxSpeed(), flowCapableNodeConnector.getMaximumSpeed());
-        assertEqualsState(port.getState(), flowCapableNodeConnector.getState());
-        assertEqualsPortFeatures(port.getAdvertisedFeatures(), flowCapableNodeConnector.getAdvertisedFeatures());
-        assertEqualsPortFeatures(port.getCurrentFeatures(), flowCapableNodeConnector.getCurrentFeature());
-        assertEqualsPortFeatures(port.getPeerFeatures(), flowCapableNodeConnector.getPeerFeatures());
-        assertEqualsPortFeatures(port.getSupportedFeatures(), flowCapableNodeConnector.getSupported());
-    }
-
-    /**
-     * Here unsupported version is used
-     * Test method for {@link NodeConnectorTranslatorUtil#translateFlowCapableNodeFromPhyPort(PhyPort, short)}.
-     */
-    @Test
-    public void testTranslateFlowCapableNodeFromPhyPortOF12() {
-        final PhyPort port = mockPhyPortPort();
-        try {
-            final FlowCapableNodeConnector flowCapableNodeConnector = NodeConnectorTranslatorUtil
-                    .translateFlowCapableNodeFromPhyPort(port, (short) 0x03);
-            Assert.fail("port of version 0x03 (OF-1.2) should not be translated");
-        } catch (Exception e) {
-            LOG.debug("expected exception: {}", e.getMessage());
-            Assert.assertTrue(e instanceof IllegalArgumentException);
-        }
-
-    }
-
-    /**
-     * Test method for {@link NodeConnectorTranslatorUtil#makeNodeConnectorId(BigInteger, String, long)}.
-     */
-    @Test
-    public void testMakeNodeConnectorId(){
-        final BigInteger dataPathId = BigInteger.valueOf(25L);
-        final String logicalName = "testPort";
-        final long portNo = 45L;
-        final NodeConnectorId nodeConnectorId = NodeConnectorTranslatorUtil.makeNodeConnectorId(dataPathId, logicalName, portNo);
-        Assert.assertNotNull(nodeConnectorId);
-        Assert.assertNotNull(nodeConnectorId.getValue());
-        Assert.assertTrue(nodeConnectorId.getValue().contains(logicalName));
-        Assert.assertTrue(nodeConnectorId.getValue().contains(dataPathId.toString()));
-        Assert.assertFalse(nodeConnectorId.getValue().contains(":" + portNo));
-    }
-
-    /**
-     * Test method for {@link NodeConnectorTranslatorUtil#makeNodeConnectorId(BigInteger, String, long)}.
-     */
-    @Test
-    public void testMakeNodeConnectorIdNullLogicalName(){
-        final BigInteger dataPathId = BigInteger.valueOf(25L);
-        final long portNo = 45L;
-        final NodeConnectorId nodeConnectorId = NodeConnectorTranslatorUtil.makeNodeConnectorId(dataPathId, null, portNo);
-        Assert.assertNotNull(nodeConnectorId);
-        Assert.assertNotNull(nodeConnectorId.getValue());
-        Assert.assertTrue(nodeConnectorId.getValue().contains(dataPathId.toString()));
-        Assert.assertTrue(nodeConnectorId.getValue().contains(":" + portNo));
-    }
-
-    /**
-     * Test method for {@link NodeConnectorTranslatorUtil#makeNodeConnectorId(BigInteger, String, long)}.
-     * expect {@link IllegalArgumentException}
-     */
-    @Test(expected=IllegalArgumentException.class)
-    public void testMakeNodeConnectorIdNullDataPath(){
-        final long portNo = 45L;
-        NodeConnectorTranslatorUtil.makeNodeConnectorId(null, null, portNo);
-    }
-
-    private PhyPort mockPhyPortPort() {
-        final PhyPort phyport = mock(PhyPort.class);
-        when(phyport.getAdvertisedFeatures()).thenReturn(getPortFeatures());
-        when(phyport.getAdvertisedFeaturesV10()).thenReturn(getPortFeaturesV10());
-        when(phyport.getConfig()).thenReturn(getPortConfig());
-        when(phyport.getConfigV10()).thenReturn(getPortConfigV10());
-        when(phyport.getCurrentFeatures()).thenReturn(getPortFeatures());
-        when(phyport.getCurrentFeaturesV10()).thenReturn(getPortFeaturesV10());
-        when(phyport.getCurrSpeed()).thenReturn(currentSpeed);
-        when(phyport.getHwAddr()).thenReturn(getMacAddress());
-        when(phyport.getName()).thenReturn(NAME);
-        when(phyport.getMaxSpeed()).thenReturn(maxSpeed);
-        when(phyport.getPeerFeatures()).thenReturn(getPortFeatures());
-        when(phyport.getPeerFeaturesV10()).thenReturn(getPortFeaturesV10());
-        when(phyport.getPortNo()).thenReturn(Long.MAX_VALUE);
-        when(phyport.getState()).thenReturn(getPortState());
-        when(phyport.getStateV10()).thenReturn(getPortStateV10());
-        when(phyport.getSupportedFeatures()).thenReturn(getPortFeatures());
-        when(phyport.getSupportedFeaturesV10()).thenReturn(getPortFeaturesV10());
-        return phyport;
-    }
-
-    private static PortStateV10 getPortStateV10() {
-        final PortStateV10 portState = new PortStateV10(Boolean.TRUE, Boolean.TRUE, Boolean.TRUE, Boolean.TRUE, Boolean.TRUE, Boolean.TRUE, Boolean.TRUE, Boolean.TRUE);
-        return portState;
-    }
-
-    private PortState getPortState() {
-        final PortState portState = new PortState(portStateBools[0], portStateBools[1], portStateBools[2]);
-        return portState;
-    }
-
-    private PortFeatures getPortFeatures() {
-        return new PortFeatures(pfBls[0], pfBls[1], pfBls[2], pfBls[3], pfBls[4], pfBls[5], pfBls[6], pfBls[7], pfBls[8],
-                pfBls[9], pfBls[10], pfBls[11], pfBls[12], pfBls[13], pfBls[14], pfBls[15]);
-    }
-
-    private PortFeaturesV10 getPortFeaturesV10() {
-        return new PortFeaturesV10(pfV10Bls[0], pfV10Bls[1], pfV10Bls[2], pfV10Bls[3], pfV10Bls[4], pfV10Bls[5], pfV10Bls[6],
-                pfV10Bls[7], pfV10Bls[8], pfV10Bls[9], pfV10Bls[10], pfV10Bls[11]);
-    }
-
-    private static MacAddress getMacAddress() {
-        return new MacAddress(MAC_ADDRESS);
-    }
-
-    private PortConfigV10 getPortConfigV10() {
-        return new PortConfigV10(portCfgV10bools[0], portCfgV10bools[1], portCfgV10bools[2], portCfgV10bools[3], portCfgV10bools[4], portCfgV10bools[5], portCfgV10bools[6]);
-    }
-
-    private PortConfig getPortConfig() {
-        return new PortConfig(portCfgBools[0], portCfgBools[1], portCfgBools[2], portCfgBools[3]);
-    }
-
-    private static void assertEqualsStateV10(final PortStateV10 psV10, final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortState state) {
-        assertEquals(psV10.isBlocked(), state.isBlocked());
-        assertEquals(psV10.isLinkDown(), state.isLinkDown());
-        assertEquals(psV10.isLive(), state.isLive());
-    }
-
-    private static void assertEqualsState(final PortState ps, final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortState state) {
-        assertEquals(ps.isBlocked(), state.isBlocked());
-        assertEquals(ps.isLinkDown(), state.isLinkDown());
-        assertEquals(ps.isLive(), state.isLive());
-    }
-
-    private static void assertEqualsPortFeaturesV10(final PortFeaturesV10 apfV10, final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures npf) {
-        assertEquals(apfV10.is_100mbFd(), npf.isHundredMbFd());
-        assertEquals(apfV10.is_100mbHd(), npf.isHundredMbHd());
-
-        assertEquals(apfV10.is_10gbFd(), npf.isTenGbFd());
-        assertEquals(apfV10.is_10mbFd(), npf.isTenMbFd());
-        assertEquals(apfV10.is_10mbHd(), npf.isTenMbHd());
-
-        assertEquals(apfV10.is_1gbFd(), npf.isOneGbFd());
-        assertEquals(apfV10.is_1gbHd(), npf.isOneGbHd());
-
-        assertEquals(apfV10.isAutoneg(), npf.isAutoeng());
-        assertEquals(apfV10.isCopper(), npf.isCopper());
-        assertEquals(apfV10.isFiber(), npf.isFiber());
-        assertEquals(apfV10.isPause(), npf.isPause());
-        assertEquals(apfV10.isPauseAsym(), npf.isPauseAsym());
-    }
-
-    private static void assertEqualsPortFeatures(final PortFeatures apf, final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures npf) {
-        assertEquals(apf.is_100gbFd(), npf.isHundredGbFd());
-        assertEquals(apf.is_100mbFd(), npf.isHundredMbFd());
-        assertEquals(apf.is_100mbHd(), npf.isHundredMbHd());
-
-        assertEquals(apf.is_10gbFd(), npf.isTenGbFd());
-        assertEquals(apf.is_10mbFd(), npf.isTenMbFd());
-        assertEquals(apf.is_10mbHd(), npf.isTenMbHd());
-
-        assertEquals(apf.is_1gbFd(), npf.isOneGbFd());
-        assertEquals(apf.is_1gbHd(), npf.isOneGbHd());
-        assertEquals(apf.is_1tbFd(), npf.isOneTbFd());
-
-        assertEquals(apf.is_40gbFd(), npf.isFortyGbFd());
-
-        assertEquals(apf.isAutoneg(), npf.isAutoeng());
-        assertEquals(apf.isCopper(), npf.isCopper());
-        assertEquals(apf.isFiber(), npf.isFiber());
-        assertEquals(apf.isOther(), npf.isOther());
-        assertEquals(apf.isPause(), npf.isPause());
-        assertEquals(apf.isPauseAsym(), npf.isPauseAsym());
-    }
-
-    static InstanceIdentifier<NodeConnector> createNodeConnectorId(String nodeKey, String nodeConnectorKey) {
-        return InstanceIdentifier.builder(Nodes.class)
-                .child(Node.class, new NodeKey(new NodeId(nodeKey)))
-                .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId(nodeConnectorKey)))
-                .build();
-    }
-
-    @Test
-    public void testDummy() {
-        InstanceIdentifier<NodeConnector> id = createNodeConnectorId("openflow:1", "openflow:1:1");
-        InstanceIdentifier<Node> nodeId = id.firstIdentifierOf(Node.class);
-        System.out.println(nodeId);
-    }
-}
index ffba264ed470f4417bc61f729a3eef5f6b65627e..c0657da1991e914d3e8e8d1ca01414911eebd2ad 100644 (file)
@@ -71,6 +71,7 @@ import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleLi
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
 import org.opendaylight.openflowplugin.extension.api.ConvertorMessageFromOFJava;
 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
+import org.opendaylight.openflowplugin.impl.device.initialization.DeviceInitializerProviderFactory;
 import org.opendaylight.openflowplugin.impl.registry.flow.FlowDescriptorFactory;
 import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
 import org.opendaylight.openflowplugin.impl.util.DeviceStateUtil;
@@ -230,7 +231,8 @@ public class DeviceContextImplTest {
                 translatorLibrary,
                 deviceManager,
                 convertorExecutor,
-                false, timer, deviceManager, false);
+                false, timer, deviceManager, false,
+            DeviceInitializerProviderFactory.createDefaultProvider());
         deviceContextSpy = Mockito.spy(deviceContext);
 
         xid = new Xid(atomicLong.incrementAndGet());
@@ -241,16 +243,6 @@ public class DeviceContextImplTest {
 
     }
 
-    @Test(expected = NullPointerException.class)
-    public void testDeviceContextImplConstructorNullDataBroker() throws Exception {
-        new DeviceContextImpl(connectionContext, null, null, translatorLibrary, deviceManager, convertorExecutor,false, timer, deviceManager, false).close();
-    }
-
-    @Test(expected = NullPointerException.class)
-    public void testDeviceContextImplConstructorNullTimer() throws Exception {
-        new DeviceContextImpl(null, dataBroker, null, translatorLibrary, deviceManager,convertorExecutor,false, timer, deviceManager, false).close();
-    }
-
     @Test
     public void testGetReadTransaction() {
         final ReadTransaction readTx = deviceContext.getReadTransaction();
@@ -362,10 +354,15 @@ public class DeviceContextImplTest {
 
     @Test
     public void testProcessReply2() {
-        final MultipartReply mockedMultipartReply = mock(MultipartReply.class);
         final Xid dummyXid = new Xid(DUMMY_XID);
-        deviceContext.processReply(dummyXid, Lists.newArrayList(mockedMultipartReply));
+
+        final Error mockedError = mock(Error.class);
+        deviceContext.processReply(dummyXid, Lists.newArrayList(mockedError));
         verify(messageSpy).spyMessage(any(Class.class), eq(MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_FAILURE));
+
+        final MultipartReply mockedMultipartReply = mock(MultipartReply.class);
+        deviceContext.processReply(dummyXid, Lists.newArrayList(mockedMultipartReply));
+        verify(messageSpy).spyMessage(any(Class.class), eq(MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_SUCCESS));
     }
 
     @Test
index 237839ad3d941f5b7dfdac467b55fe0bac7642e8..c742b2cc91efeeb1c987fb2d64fee1abfce7cbca 100644 (file)
@@ -58,6 +58,7 @@ import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTermin
 import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
 import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
+import org.opendaylight.openflowplugin.impl.device.initialization.DeviceInitializerProviderFactory;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
@@ -145,19 +146,20 @@ public class DeviceManagerImplTest {
         when(mockedWriteTransaction.submit()).thenReturn(mockedFuture);
 
         final DeviceManagerImpl deviceManager = new DeviceManagerImpl(
-                mockedDataBroker,
-                TEST_VALUE_GLOBAL_NOTIFICATION_QUOTA,
-                false,
-                barrierIntervalNanos,
-                barrierCountLimit,
-                messageIntelligenceAgency,
-                true,
-                clusterSingletonServiceProvider,
-                null,
-                new HashedWheelTimer(),
-                convertorExecutor,
-                false,
-                false);
+            mockedDataBroker,
+            TEST_VALUE_GLOBAL_NOTIFICATION_QUOTA,
+            false,
+            barrierIntervalNanos,
+            barrierCountLimit,
+            messageIntelligenceAgency,
+            true,
+            clusterSingletonServiceProvider,
+            null,
+            new HashedWheelTimer(),
+            convertorExecutor,
+            false,
+            false,
+            DeviceInitializerProviderFactory.createDefaultProvider());
 
         deviceManager.setDeviceInitializationPhaseHandler(deviceInitPhaseHandler);
         deviceManager.setDeviceTerminationPhaseHandler(deviceTerminationPhaseHandler);
index f517c818f1d368f82c0510cf6cd1efc4f542f6cc..5e59a828d37c268b0266e800ab412bfb45b7d82e 100644 (file)
@@ -45,7 +45,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 @RunWith(MockitoJUnitRunner.class)
 public class MultiMsgCollectorImplTest {
 
-    private MultiMsgCollectorImpl collector;
+    private MultiMsgCollectorImpl<MultipartReply> collector;
     private Runnable cleanUpCheck;
 
     @Mock
@@ -68,7 +68,7 @@ public class MultiMsgCollectorImplTest {
 
     @Before
     public void setUp() {
-        collector = new MultiMsgCollectorImpl(deviceProcessor, requestContext);
+        collector = new MultiMsgCollectorImpl<>(deviceProcessor, requestContext);
         cleanUpCheck = Runnables.doNothing();
         Mockito.when(requestContext.getXid()).thenReturn(new Xid(xid));
     }
@@ -88,7 +88,7 @@ public class MultiMsgCollectorImplTest {
      */
     @Test
     public void testAddMultipartMsgOne() {
-        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, false).build());
+        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, false).build(), false, null);
 
         Mockito.verify(deviceProcessor).processReply(xidCaptor.capture(), mmCaptor.capture());
         Assert.assertEquals(xid, xidCaptor.getValue().getValue());
@@ -104,8 +104,8 @@ public class MultiMsgCollectorImplTest {
      */
     @Test
     public void testAddMultipartMsgTwo() {
-        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, true).build());
-        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, false).build());
+        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, true).build(), true, null);
+        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, false).build(), false, null);
 
         Mockito.verify(deviceProcessor).processReply(xidCaptor.capture(), mmCaptor.capture());
         Assert.assertEquals(xid, xidCaptor.getValue().getValue());
@@ -124,7 +124,7 @@ public class MultiMsgCollectorImplTest {
     public void testAddMultipartMsgNotExpectedXid() {
         final Long dif_xid = 5L;
         final MultipartReplyMessage mrMsg = MsgGeneratorTestUtils.makeMultipartDescReply(dif_xid, hwTestValue, true).build();
-        collector.addMultipartMsg(mrMsg);
+        collector.addMultipartMsg(mrMsg, true, null);
     }
 
     /**
@@ -133,9 +133,9 @@ public class MultiMsgCollectorImplTest {
      */
     @Test
     public void testAddMultipartMsgWrongType1() {
-        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, true).build());
+        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, true).build(), true, null);
         collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, false)
-                .setType(MultipartType.OFPMPPORTDESC).build());
+                .setType(MultipartType.OFPMPPORTDESC).build(), false, null);
 
         Mockito.verify(deviceProcessor).processReply(xidCaptor.capture(), mmCaptor.capture());
         Assert.assertEquals(xid, xidCaptor.getValue().getValue());
@@ -158,10 +158,10 @@ public class MultiMsgCollectorImplTest {
      */
     @Test
     public void testAddMultipartMsgWrongType2() {
-        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, true).build());
+        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, true).build(), true, null);
         collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, true)
-                .setType(MultipartType.OFPMPPORTDESC).build());
-        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, false).build());
+                .setType(MultipartType.OFPMPPORTDESC).build(), true, null);
+        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, false).build(), false, null);
 
         Mockito.verify(deviceProcessor).processReply(xidCaptor.capture(), mmCaptor.capture());
         Mockito.verify(deviceProcessor).processReply(xidCaptor.capture(), mmCaptor.capture());
@@ -185,10 +185,10 @@ public class MultiMsgCollectorImplTest {
      */
     @Test
     public void testAddMultipartMsgWrongType3() {
-        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, true).build());
+        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, true).build(), true, null);
         collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, true)
-                .setType(MultipartType.OFPMPPORTDESC).build());
-        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, false).build());
+                .setType(MultipartType.OFPMPPORTDESC).build(), true, null);
+        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, false).build(), false, null);
 
         Mockito.verify(deviceProcessor).processReply(xidCaptor.capture(), mmCaptor.capture());
         Assert.assertEquals(xid, xidCaptor.getValue().getValue());
index 342d2218b41d24a8e7479af58f578b4e1c120a54..41d48b200891ac9b835b95b352b7f2bc1d9f025d 100644 (file)
@@ -40,6 +40,7 @@ public abstract class AbstractDeserializerTest {
         factory.setRegistry(registry);
         provider = new DeserializerExtensionProviderImpl(registry, factory);
         DeserializerInjector.injectDeserializers(provider);
+        MessageDeserializerInjector.injectDeserializers(provider);
         init();
     }
 
index 12f5de2af3d296d1cd7730cade2ccc24b66e2d7a..e7b2488f15ea1593c7938bbd1bf4c2965522f215 100644 (file)
@@ -19,11 +19,13 @@ import org.mockito.Matchers;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.stubbing.OngoingStubbing;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
+import org.opendaylight.openflowplugin.impl.services.multilayer.MultiLayerMultipartRequestCallback;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
@@ -32,7 +34,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yangtools.yang.common.RpcResult;
 
 /**
- * Test for {@link MultipartRequestCallback}.
+ * Test for {@link org.opendaylight.openflowplugin.impl.services.AbstractMultipartRequestCallback}.
  */
 @RunWith(MockitoJUnitRunner.class)
 public class MultipartRequestCallbackTest {
@@ -44,18 +46,21 @@ public class MultipartRequestCallbackTest {
     @Mock
     private MessageSpy spy;
     @Mock
-    private MultiMsgCollector multiMsgCollector;
+    private MultiMsgCollector<MultipartReply> multiMsgCollector;
     @Captor
     private ArgumentCaptor<RpcResult<List<MultipartReply>>> rpcResultCapt;
 
-    private MultipartRequestCallback multipartRequestCallback;
+    private AbstractMultipartRequestCallback<MultipartReply> multipartRequestCallback;
 
     @Before
     public void setUp() throws Exception {
         Mockito.doNothing().when(requestContext).setResult(rpcResultCapt.capture());
         Mockito.when(deviceContext.getMessageSpy()).thenReturn(spy);
-        Mockito.when(deviceContext.getMultiMsgCollector(Matchers.<RequestContext>any())).thenReturn(multiMsgCollector);
-        multipartRequestCallback = new MultipartRequestCallback(requestContext, MultipartRequestInput.class, deviceContext);
+
+        final OngoingStubbing<MultiMsgCollector<MultipartReply>> when =
+            Mockito.when(deviceContext.getMultiMsgCollector(Matchers.any()));
+        when.thenReturn(multiMsgCollector);
+        multipartRequestCallback = new MultiLayerMultipartRequestCallback<>(requestContext, MultipartRequestInput.class, deviceContext, null);
     }
 
     /**
@@ -91,6 +96,6 @@ public class MultipartRequestCallbackTest {
     public void testOnSuccess3() throws Exception {
         final MultipartReplyMessage replyMessage = new MultipartReplyMessageBuilder().build();
         multipartRequestCallback.onSuccess(replyMessage);
-        Mockito.verify(multiMsgCollector).addMultipartMsg(Matchers.eq(replyMessage), Matchers.<EventIdentifier>any());
+        Mockito.verify(multiMsgCollector).addMultipartMsg(Matchers.eq(replyMessage), Matchers.eq(false), Matchers.any());
     }
-}
\ No newline at end of file
+}
index 098ef4dd866e6061fae6f2ad3590a0f16a78dfa5..637c3b6023f24faa0e0953bd9acba39dfb34bd3f 100644 (file)
@@ -8,8 +8,8 @@
 package org.opendaylight.openflowplugin.impl.services;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
@@ -43,7 +43,9 @@ import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegi
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProviderFactory;
 import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext;
+import org.opendaylight.openflowplugin.impl.services.multilayer.MultiLayerFlowMultipartRequestOnTheFlyCallback;
 import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.MessageIntelligenceAgencyImpl;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
@@ -112,7 +114,7 @@ public class MultipartRequestOnTheFlyCallbackTest {
 
     private AbstractRequestContext<List<MultipartReply>> dummyRequestContext;
     private final EventIdentifier dummyEventIdentifier = new EventIdentifier(DUMMY_EVENT_NAME, DUMMY_DEVICE_ID);
-    private MultipartRequestOnTheFlyCallback multipartRequestOnTheFlyCallback;
+    private AbstractMultipartRequestOnTheFlyCallback<MultipartReply> multipartRequestOnTheFlyCallback;
     private final short tableId = 0;
 
     @Before
@@ -156,9 +158,13 @@ public class MultipartRequestOnTheFlyCallbackTest {
         };
 
         final ConvertorManager convertorManager = ConvertorManagerFactory.createDefaultManager();
-        multipartRequestOnTheFlyCallback = new MultipartRequestOnTheFlyCallback(dummyRequestContext, String.class,
-                mockedDeviceContext.getMessageSpy(),dummyEventIdentifier, mockedDeviceInfo,
-                mockedDeviceContext.getDeviceFlowRegistry(), mockedDeviceContext, convertorManager);
+        multipartRequestOnTheFlyCallback = new MultiLayerFlowMultipartRequestOnTheFlyCallback<>(
+            dummyRequestContext,
+            String.class,
+            mockedDeviceContext,
+            dummyEventIdentifier,
+            MultipartWriterProviderFactory.createDefaultProvider(mockedDeviceContext),
+            convertorManager);
     }
 
 
@@ -267,11 +273,10 @@ public class MultipartRequestOnTheFlyCallbackTest {
         multipartRequestOnTheFlyCallback.onSuccess(mpReplyMessage.build());
 
         final RpcResult<List<MultipartReply>> actualResult = dummyRequestContext.getFuture().get();
-        assertNotNull(actualResult.getErrors());
-        assertTrue(actualResult.getErrors().isEmpty());
-        assertNotNull(actualResult.getResult());
-        assertTrue(actualResult.getResult().isEmpty());
 
+        // Nothing else than flow is supported by on the fly callback
+        assertNotNull(actualResult.getErrors());
+        assertFalse(actualResult.getErrors().isEmpty());
         Mockito.verify(mockedFlowRegistry, Mockito.never()).storeIfNecessary(Matchers.any());
         Mockito.verify(mockedDeviceContext, Mockito.never()).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL),
                 Matchers.<InstanceIdentifier>any(), Matchers.<DataObject>any());
index cf1d4601ffde8b7b90ee2639a5a98335cc22c277..d2717523dc3972a24f4b3cba8f206d44a18eb9f7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Pantheon Technologies s.r.o. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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,
@@ -19,6 +19,8 @@ import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.extension.api.ConvertorMessageToOFJava;
 import org.opendaylight.openflowplugin.extension.api.TypeVersionKey;
 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
+import org.opendaylight.openflowplugin.impl.services.multilayer.MultiLayerExperimenterMultipartService;
+import org.opendaylight.openflowplugin.impl.services.sal.SalExperimenterMpMessageServiceImpl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
@@ -75,7 +77,8 @@ public class SalExperimenterMpMessageServiceImplTest extends ServiceMocking {
                 .setNode(new NodeRef(mockedDeviceInfo.getNodeInstanceIdentifier()))
                 .build();
 
-        final OfHeader ofHeader = salExperimenterMpMessageService.buildRequest(new Xid(DUMMY_ID), data);
+        final OfHeader ofHeader = new MultiLayerExperimenterMultipartService(mockedDeviceContext, mockedDeviceContext, mockedExtensionConverterProvider)
+            .buildRequest(new Xid(DUMMY_ID), data);
         verify(mockedExtensionConverter).convert(data.getExperimenterMessageOfChoice());
         assertEquals(DUMMY_ID, (long) ofHeader.getXid());
         assertEquals(mockedDeviceInfo.getVersion(), (short) ofHeader.getVersion());
@@ -98,4 +101,4 @@ public class SalExperimenterMpMessageServiceImplTest extends ServiceMocking {
             return DummyExperimenter.class;
         }
     }
-}
\ No newline at end of file
+}
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -14,6 +14,8 @@ import static org.mockito.Mockito.verify;
 
 import org.junit.Test;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.impl.services.ServiceMocking;
+import org.opendaylight.openflowplugin.impl.services.sal.FlowCapableTransactionServiceImpl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.SendBarrierInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.SendBarrierInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
@@ -21,7 +23,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 
 /**
- * Test for {@link FlowCapableTransactionServiceImpl}.
+ * Test for {@link org.opendaylight.openflowplugin.impl.services.sal.FlowCapableTransactionServiceImpl}.
  */
 public class FlowCapableTransactionServiceImplTest extends ServiceMocking {
 
@@ -53,4 +55,4 @@ public class FlowCapableTransactionServiceImplTest extends ServiceMocking {
         return new SendBarrierInputBuilder()
                 .setNode(new NodeRef(mockedDeviceInfo.getNodeInstanceIdentifier())).build();
     }
-}
\ No newline at end of file
+}
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -14,12 +14,14 @@ import static org.mockito.Mockito.verify;
 
 import org.junit.Test;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.impl.services.ServiceMocking;
+import org.opendaylight.openflowplugin.impl.services.sal.NodeConfigServiceImpl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.module.config.rev141015.SetConfigInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.module.config.rev141015.SetConfigInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.SwitchConfigFlag;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 
-public class NodeConfigServiceImplTest extends ServiceMocking{
+public class NodeConfigServiceImplTest extends ServiceMocking {
 
     private static final Long DUMMY_XID_VALUE = 150L;
     private static final SwitchConfigFlag DUMMY_FLAG = SwitchConfigFlag.FRAGNORMAL;
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -15,6 +15,7 @@ import static org.mockito.Mockito.verify;
 import org.junit.Test;
 import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.impl.services.ServiceMocking;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
@@ -34,7 +35,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.Tr
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 
 /**
- * Test for {@link PacketProcessingServiceImpl}.
+ * Test for {@link org.opendaylight.openflowplugin.impl.services.sal.PacketProcessingServiceImpl}.
  */
 public class PacketProcessingServiceImplTest extends ServiceMocking {
 
@@ -85,4 +86,4 @@ public class PacketProcessingServiceImplTest extends ServiceMocking {
                 .setEgress(new NodeConnectorRef(pathToNodeconnector));
         return transmitPacketInputBld.build();
     }
-}
\ No newline at end of file
+}
similarity index 90%
rename from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalEchoServiceImplTest.java
rename to openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalEchoServiceImplTest.java
index 3564d2836a4544f66a09a508e8f3a31f294057b4..17197e74337f892c303f4ca7948f3e4aafa04e2d 100644 (file)
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import static org.mockito.Mockito.verify;
 
@@ -18,6 +18,8 @@ import org.junit.Assert;
 import org.junit.Test;
 import org.mockito.Matchers;
 import org.mockito.Mockito;
+import org.opendaylight.openflowplugin.impl.services.ServiceMocking;
+import org.opendaylight.openflowplugin.impl.services.sal.SalEchoServiceImpl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.echo.service.rev150305.SendEchoInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.echo.service.rev150305.SendEchoInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.echo.service.rev150305.SendEchoOutput;
@@ -57,4 +59,4 @@ public class SalEchoServiceImplTest extends ServiceMocking {
         verify(mockedRequestContextStack).createRequestContext();
         verify(mockedOutboundQueue).commitEntry(Matchers.eq(2121L), Matchers.<OfHeader>any(), Matchers.<FutureCallback<OfHeader>>any());
     }
-}
\ No newline at end of file
+}
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -20,6 +20,7 @@ import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.extension.api.ConvertorMessageToOFJava;
 import org.opendaylight.openflowplugin.extension.api.TypeVersionKey;
 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
+import org.opendaylight.openflowplugin.impl.services.ServiceMocking;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.message.service.rev151020.SendExperimenterInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.message.service.rev151020.SendExperimenterInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
@@ -30,7 +31,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.experimenter
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 
 /**
- * Test for {@link SalExperimenterMessageServiceImpl}.
+ * Test for {@link org.opendaylight.openflowplugin.impl.services.sal.SalExperimenterMessageServiceImpl}.
  */
 public class SalExperimenterMessageServiceImplTest extends ServiceMocking {
 
@@ -85,4 +86,4 @@ public class SalExperimenterMessageServiceImplTest extends ServiceMocking {
         }
     }
 
-}
\ No newline at end of file
+}
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.AsyncFunction;
@@ -102,7 +102,7 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
 /**
- * Test for {@link SalFlatBatchServiceImpl}.
+ * Test for {@link org.opendaylight.openflowplugin.impl.services.sal.SalFlatBatchServiceImpl}.
  */
 @RunWith(MockitoJUnitRunner.class)
 public class SalFlatBatchServiceImplTest {
@@ -555,4 +555,4 @@ public class SalFlatBatchServiceImplTest {
         Mockito.verify(salFlowsBatchService, Mockito.times(2)).addFlowsBatch(addFlowsBatchInputCpt.capture());
         Assert.assertEquals(2, addFlowsBatchInputCpt.getValue().getBatchAddFlows().size());
     }
-}
\ No newline at end of file
+}
similarity index 98%
rename from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalFlowServiceImplTest.java
rename to openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalFlowServiceImplTest.java
index 46af7563d9db6a8348419718f671a65fff722247..9918d9b953459f1a95622c03f91a32f796aeb7a7 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 
 import static org.mockito.Mockito.mock;
@@ -39,6 +39,7 @@ import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
 import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
+import org.opendaylight.openflowplugin.impl.services.sal.SalFlowServiceImpl;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
@@ -144,7 +145,7 @@ public class SalFlowServiceImplTest extends TestCase {
         when(mockedDeviceInfo.getVersion()).thenReturn(version);
 
         if (OFConstants.OFP_VERSION_1_3 >= version) {
-            when(mockedDeviceContext.isUseSingleLayerSerialization()).thenReturn(true);
+            when(mockedDeviceContext.canUseSingleLayerSerialization()).thenReturn(true);
         }
 
         final ConvertorManager convertorManager = ConvertorManagerFactory.createDefaultManager();
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import com.google.common.collect.Lists;
 import java.util.List;
@@ -67,7 +67,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Test for {@link SalFlowsBatchServiceImpl}.
+ * Test for {@link org.opendaylight.openflowplugin.impl.services.sal.SalFlowsBatchServiceImpl}.
  */
 @RunWith(MockitoJUnitRunner.class)
 public class SalFlowsBatchServiceImplTest {
@@ -336,4 +336,4 @@ public class SalFlowsBatchServiceImplTest {
 
         inOrder.verify(transactionService).sendBarrier(Matchers.<SendBarrierInput>any());
     }
-}
\ No newline at end of file
+}
similarity index 96%
rename from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalGroupServiceImplTest.java
rename to openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalGroupServiceImplTest.java
index f0814d8962320ef7bf1e89ecf42033030a9fcebe..3581bf81aae58b429bcab6d59d12e461e3fa452a 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
@@ -17,6 +17,7 @@ import org.mockito.Matchers;
 import org.mockito.Mock;
 import org.opendaylight.openflowplugin.api.openflow.registry.group.DeviceGroupRegistry;
 import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
+import org.opendaylight.openflowplugin.impl.services.ServiceMocking;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import com.google.common.collect.Lists;
 import java.util.List;
@@ -23,6 +23,7 @@ import org.mockito.Matchers;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.openflowplugin.impl.services.sal.SalGroupsBatchServiceImpl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.FlowCapableTransactionService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.SendBarrierInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
@@ -64,7 +65,7 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
 /**
- * Test for {@link SalGroupsBatchServiceImpl}.
+ * Test for {@link org.opendaylight.openflowplugin.impl.services.sal.SalGroupsBatchServiceImpl}.
  */
 @RunWith(MockitoJUnitRunner.class)
 public class SalGroupsBatchServiceImplTest {
@@ -311,4 +312,4 @@ public class SalGroupsBatchServiceImplTest {
                 .setUpdatedBatchedGroup(new UpdatedBatchedGroupBuilder(createEmptyBatchAddGroup(groupIdValue+1)).build())
                 .build();
     }
-}
\ No newline at end of file
+}
similarity index 96%
rename from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalMeterServiceImplTest.java
rename to openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalMeterServiceImplTest.java
index ea20a88647c778e0c1aeb0cdf39a7ba47a050353..75debf6b4634f1e0e7061753e1c686e9f7d2bac0 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
@@ -17,6 +17,7 @@ import org.mockito.Matchers;
 import org.mockito.Mock;
 import org.opendaylight.openflowplugin.api.openflow.registry.meter.DeviceMeterRegistry;
 import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
+import org.opendaylight.openflowplugin.impl.services.ServiceMocking;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import com.google.common.collect.Lists;
 import java.util.List;
@@ -23,6 +23,7 @@ import org.mockito.Matchers;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.openflowplugin.impl.services.sal.SalMetersBatchServiceImpl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.FlowCapableTransactionService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.SendBarrierInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
@@ -64,7 +65,7 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
 /**
- * Test for {@link SalMetersBatchServiceImpl}.
+ * Test for {@link org.opendaylight.openflowplugin.impl.services.sal.SalMetersBatchServiceImpl}.
  */
 @RunWith(MockitoJUnitRunner.class)
 public class SalMetersBatchServiceImplTest {
@@ -310,4 +311,4 @@ public class SalMetersBatchServiceImplTest {
                 .setUpdatedBatchedMeter(new UpdatedBatchedMeterBuilder(createEmptyBatchAddMeter(groupIdValue + 1)).build())
                 .build();
     }
-}
\ No newline at end of file
+}
similarity index 93%
rename from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalPortServiceImplTest.java
rename to openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalPortServiceImplTest.java
index c0d55986fcd49a23ae3b2c7b6394603dd9eb4a43..dd8ae67e421b816686881ec75e1d7d555e0244af 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import static org.mockito.Mockito.verify;
 
@@ -15,6 +15,8 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.runners.MockitoJUnitRunner;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.impl.services.ServiceMocking;
+import org.opendaylight.openflowplugin.impl.services.sal.SalPortServiceImpl;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
similarity index 97%
rename from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalRoleServiceImplTest.java
rename to openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalRoleServiceImplTest.java
index 0c7d7586e438f3dc5aa2519009e778c3e368b30c..74ec78da7640b71506f683eecfeced328db5f587 100644 (file)
@@ -1,11 +1,11 @@
-/**
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -30,6 +30,7 @@ import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
+import org.opendaylight.openflowplugin.impl.services.sal.SalRoleServiceImpl;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
similarity index 95%
rename from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/SalTableServiceImplTest.java
rename to openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalTableServiceImplTest.java
index 3bf020e83e3f22050f70596fc319375d4d37b06f..1810e8b429f91833b4a8d8cfc0c04aefb5165cdb 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.services;
+package org.opendaylight.openflowplugin.impl.services.sal;
 
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -27,6 +27,8 @@ import org.mockito.stubbing.Answer;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProviderFactory;
+import org.opendaylight.openflowplugin.impl.services.ServiceMocking;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
@@ -74,7 +76,7 @@ public class SalTableServiceImplTest extends ServiceMocking {
 
         final ConvertorManager convertorManager = ConvertorManagerFactory.createDefaultManager();
         salTableService = new SalTableServiceImpl(mockedRequestContextStack, mockedDeviceContext,
-                convertorManager);
+                convertorManager, MultipartWriterProviderFactory.createDefaultProvider(mockedDeviceContext));
     }
 
     @Test
@@ -21,16 +21,16 @@ import org.junit.Test;
 import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
+import org.opendaylight.openflowplugin.impl.common.MultipartReplyTranslatorUtil;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsUpdate;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdate;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionAware;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupDescStatsUpdated;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowAndStatisticsMapList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupDescStatsReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupStatisticsReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.AggregateFlowStatistics;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
@@ -54,15 +54,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.desc._case.multipart.reply.group.desc.GroupDescBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.MultipartReplyPortStatsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.multipart.reply.port.stats.PortStatsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdate;
 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.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
 
-public class SinglePurposeMultipartReplyTranslatorTest {
+public class MultipartReplyTranslatorTest {
 
     private static final BigInteger DUMMY_DATAPATH_ID = new BigInteger("21");
     private static final Long DUMMY_XID = 1L;
-    private SinglePurposeMultipartReplyTranslator singlePurposeMultipartReplyTranslator;
     private static final BigInteger DUMMY_BYTE_COUNT = new BigInteger("31");
     private static final BigInteger DUMMY_PACKET_COUNT = new BigInteger("41");
     private static final Long DUMMY_FLOW_COUNT = 51L;
@@ -85,11 +83,10 @@ public class SinglePurposeMultipartReplyTranslatorTest {
     private static final Long DUMMY_REF_COUNT = 1234L;
     private static final GroupTypes DUMMY_GROUPS_TYPE = GroupTypes.GroupAll;
     private static final GroupType DUMMY_GROUP_TYPE = GroupType.OFPGTALL;
+    private static final ConvertorManager convertorManager = ConvertorManagerFactory.createDefaultManager();
 
     @Before
     public void setUp() {
-        final ConvertorManager convertorManager = ConvertorManagerFactory.createDefaultManager();
-        singlePurposeMultipartReplyTranslator = new SinglePurposeMultipartReplyTranslator(convertorManager);
     }
 
     @Test
@@ -98,13 +95,14 @@ public class SinglePurposeMultipartReplyTranslatorTest {
 
         MultipartReplyMessage multipartReplyMessage = prepareMocks(mockedDeviceContext, prepareMultipartReplyFlow(), MultipartType.OFPMPFLOW);
 
-        List<DataObject> result = singlePurposeMultipartReplyTranslator.translate(
-                mockedDeviceContext.getPrimaryConnectionContext().getFeatures().getDatapathId(),
-                mockedDeviceContext.getPrimaryConnectionContext().getFeatures().getVersion(),
-                multipartReplyMessage);
+        DataContainer result = MultipartReplyTranslatorUtil.translate(
+            multipartReplyMessage,
+            mockedDeviceContext.getDeviceInfo(),
+            convertorManager,
+            mockedDeviceContext.oook()).get();
 
-        DataObject dataObject = validateOutput(result);
-        assertTrue(dataObject instanceof FlowsStatisticsUpdate);
+        DataContainer dataObject = validateOutput(result);
+        assertTrue(dataObject instanceof FlowAndStatisticsMapList);
     }
 
     @Test
@@ -113,14 +111,15 @@ public class SinglePurposeMultipartReplyTranslatorTest {
 
         MultipartReplyMessage multipartReplyMessage = prepareMocks(mockedDeviceContext, prepareMultipartReplyAggregate(), MultipartType.OFPMPAGGREGATE);
 
-        List<DataObject> result = singlePurposeMultipartReplyTranslator.translate(
-                mockedDeviceContext.getPrimaryConnectionContext().getFeatures().getDatapathId(),
-                mockedDeviceContext.getPrimaryConnectionContext().getFeatures().getVersion(),
-                multipartReplyMessage);
+        DataContainer result = MultipartReplyTranslatorUtil.translate(
+            multipartReplyMessage,
+            mockedDeviceContext.getDeviceInfo(),
+            convertorManager,
+            mockedDeviceContext.oook()).get();
 
-        DataObject dataObject = validateOutput(result);
-        assertTrue(dataObject instanceof AggregateFlowStatisticsUpdate);
-        AggregateFlowStatisticsUpdate message = (AggregateFlowStatisticsUpdate)dataObject;
+        DataContainer dataObject = validateOutput(result);
+        assertTrue(dataObject instanceof AggregateFlowStatistics);
+        AggregateFlowStatistics message = (AggregateFlowStatistics)dataObject;
         assertEquals(DUMMY_BYTE_COUNT, message.getByteCount().getValue());
         assertEquals(DUMMY_PACKET_COUNT, message.getPacketCount().getValue());
         assertEquals(DUMMY_FLOW_COUNT, message.getFlowCount().getValue());
@@ -132,14 +131,15 @@ public class SinglePurposeMultipartReplyTranslatorTest {
 
         MultipartReplyMessage multipartReplyMessage = prepareMocks(mockedDeviceContext, prepareMultipartReplyPortStats(), MultipartType.OFPMPPORTSTATS);
 
-        List<DataObject> result = singlePurposeMultipartReplyTranslator.translate(
-                mockedDeviceContext.getPrimaryConnectionContext().getFeatures().getDatapathId(),
-                mockedDeviceContext.getPrimaryConnectionContext().getFeatures().getVersion(),
-                multipartReplyMessage);
+        DataContainer result = MultipartReplyTranslatorUtil.translate(
+            multipartReplyMessage,
+            mockedDeviceContext.getDeviceInfo(),
+            convertorManager,
+            mockedDeviceContext.oook()).get();
 
-        DataObject dataObject = validateOutput(result);
-        assertTrue(dataObject instanceof NodeConnectorStatisticsUpdate);
-        NodeConnectorStatisticsUpdate nodeConnectorStatisticsUpdate = (NodeConnectorStatisticsUpdate)dataObject;
+        DataContainer dataObject = validateOutput(result);
+        assertTrue(dataObject instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsAndPortNumberMap);
+        org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsAndPortNumberMap nodeConnectorStatisticsUpdate = (org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsAndPortNumberMap)dataObject;
         List<NodeConnectorStatisticsAndPortNumberMap> nodeConnectorStatisticsAndPortNumberMaps = nodeConnectorStatisticsUpdate.getNodeConnectorStatisticsAndPortNumberMap();
         assertEquals(1, nodeConnectorStatisticsAndPortNumberMaps.size());
         NodeConnectorStatisticsAndPortNumberMap nodeConnectorStatisticsAndPortNumberMap = nodeConnectorStatisticsAndPortNumberMaps.get(0);
@@ -164,14 +164,15 @@ public class SinglePurposeMultipartReplyTranslatorTest {
 
         MultipartReplyMessage multipartReplyMessage = prepareMocks(mockedDeviceContext, prepareMultipartReplyGroup(), MultipartType.OFPMPGROUP);
 
-        List<DataObject> result = singlePurposeMultipartReplyTranslator.translate(
-                mockedDeviceContext.getPrimaryConnectionContext().getFeatures().getDatapathId(),
-                mockedDeviceContext.getPrimaryConnectionContext().getFeatures().getVersion(),
-                multipartReplyMessage);
+        DataContainer result = MultipartReplyTranslatorUtil.translate(
+            multipartReplyMessage,
+            mockedDeviceContext.getDeviceInfo(),
+            convertorManager,
+            mockedDeviceContext.oook()).get();
 
-        DataObject dataObject = validateOutput(result);
-        assertTrue(dataObject instanceof GroupStatisticsUpdated);
-        GroupStatisticsUpdated groupStatisticsUpdate = (GroupStatisticsUpdated)dataObject;
+        DataContainer dataObject = validateOutput(result);
+        assertTrue(dataObject instanceof GroupStatisticsReply);
+        GroupStatisticsReply groupStatisticsUpdate = (GroupStatisticsReply)dataObject;
         List<org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats> groupStats = groupStatisticsUpdate.getGroupStats();
         assertEquals(1, groupStats.size());
         org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats groupStat = groupStats.get(0);
@@ -190,14 +191,15 @@ public class SinglePurposeMultipartReplyTranslatorTest {
 
         MultipartReplyMessage multipartReplyMessage = prepareMocks(mockedDeviceContext, prepareMultipartReplyGroupDesc(), MultipartType.OFPMPGROUPDESC);
 
-        List<DataObject> result = singlePurposeMultipartReplyTranslator.translate(
-                mockedDeviceContext.getPrimaryConnectionContext().getFeatures().getDatapathId(),
-                mockedDeviceContext.getPrimaryConnectionContext().getFeatures().getVersion(),
-                multipartReplyMessage);
+        DataContainer result = MultipartReplyTranslatorUtil.translate(
+            multipartReplyMessage,
+            mockedDeviceContext.getDeviceInfo(),
+            convertorManager,
+            mockedDeviceContext.oook()).get();
 
-        DataObject dataObject = validateOutput(result);
-        assertTrue(dataObject instanceof GroupDescStatsUpdated);
-        GroupDescStatsUpdated groupStatistics = (GroupDescStatsUpdated) dataObject;
+        DataContainer dataObject = validateOutput(result);
+        assertTrue(dataObject instanceof GroupDescStatsReply);
+        GroupDescStatsReply groupStatistics = (GroupDescStatsReply) dataObject;
         List<GroupDescStats> groupDescStats = groupStatistics.getGroupDescStats();
         assertEquals(1, groupDescStats.size());
         GroupDescStats groupDescStat = groupDescStats.get(0);
@@ -283,6 +285,12 @@ public class SinglePurposeMultipartReplyTranslatorTest {
         when(mockedFeaturesReply.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
         when(mockedFeaturesReply.getDatapathId()).thenReturn(DUMMY_DATAPATH_ID);
 
+        DeviceInfo deviceInfo = mock(DeviceInfo.class);
+        when(deviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
+        when(deviceInfo.getDatapathId()).thenReturn(DUMMY_DATAPATH_ID);
+        when(deviceInfo.getLOGValue()).thenReturn(DUMMY_DATAPATH_ID.toString());
+        when(mockedDeviceContext.getDeviceInfo()).thenReturn(deviceInfo);
+
         when(mockedConnectionContext.getFeatures()).thenReturn(mockedFeaturesReply);
         when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedConnectionContext);
 
@@ -295,13 +303,7 @@ public class SinglePurposeMultipartReplyTranslatorTest {
     }
 
 
-    private DataObject validateOutput(List<DataObject> input) {
-        assertEquals(input.size(), 1);
-        DataObject dataObject = input.get(0);
-        assertTrue(dataObject instanceof Node);
-        assertEquals("openflow:" + DUMMY_DATAPATH_ID, ((Node) dataObject).getId().getValue());
-        assertTrue(dataObject instanceof TransactionAware);
-        assertEquals(new BigInteger(DUMMY_XID.toString()), ((TransactionAware) dataObject).getTransactionId().getValue());
+    private DataContainer validateOutput(DataContainer dataObject) {
         return dataObject;
     }
 }
index 55b18f5600f7d8cbd508bfd3a132ea0ac7331f58..f45f98d022dcc655dd99cc08ab6871326ff5a441 100644 (file)
@@ -29,6 +29,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 
@@ -44,8 +45,8 @@ class StatisticsContextImpMockInitiation {
     protected DeviceContext mockedDeviceContext;
     protected DeviceState mockedDeviceState;
 
-    StatisticsGatheringService mockedStatisticsGatheringService;
-    StatisticsGatheringOnTheFlyService mockedStatisticsOnFlyGatheringService;
+    StatisticsGatheringService<MultipartReply> mockedStatisticsGatheringService;
+    StatisticsGatheringOnTheFlyService<MultipartReply> mockedStatisticsOnFlyGatheringService;
     ConnectionContext mockedConnectionContext;
     DeviceInfo mockedDeviceInfo;
     StatisticsManager mockedStatisticsManager;
index 3df476ab35a580a346b4a330e814ad43e746670c..7cc74efbd19bf7ecf8310f34e7b922a58b608f8a 100644 (file)
@@ -23,6 +23,7 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProviderFactory;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
@@ -67,7 +68,8 @@ public class StatisticsContextImplParamTest extends StatisticsContextImpMockInit
         when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
 
         final ConvertorManager convertorManager = ConvertorManagerFactory.createDefaultManager();
-        final StatisticsContextImpl statisticsContext = new StatisticsContextImpl(mockedDeviceInfo, true, lifecycleService ,convertorManager, mockedStatisticsManager);
+        final StatisticsContextImpl<MultipartReply> statisticsContext = new StatisticsContextImpl<>(mockedDeviceInfo, true, lifecycleService ,convertorManager, mockedStatisticsManager,
+            MultipartWriterProviderFactory.createDefaultProvider(mockedDeviceContext));
 
         final ListenableFuture<RpcResult<List<MultipartReply>>> rpcResult = immediateFuture(RpcResultBuilder.success(Collections.<MultipartReply>emptyList()).build());
         when(mockedStatisticsGatheringService.getStatisticsOfType(any(EventIdentifier.class), any(MultipartType
index c31e57286b0dd3743236c58ce07d496612c9bb3f..11e0371032833652e79bf2057e9f52eaf7ada6cc 100644 (file)
@@ -28,6 +28,7 @@ import org.mockito.runners.MockitoJUnitRunner;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProviderFactory;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
@@ -43,7 +44,7 @@ public class StatisticsContextImplTest extends StatisticsContextImpMockInitiatio
     private static final Logger LOG = LoggerFactory.getLogger(StatisticsContextImplTest.class);
 
     private static final Long TEST_XID = 55L;
-    private StatisticsContextImpl statisticsContext;
+    private StatisticsContextImpl<MultipartReply> statisticsContext;
     private ConvertorManager convertorManager;
 
     @Before
@@ -56,7 +57,9 @@ public class StatisticsContextImplTest extends StatisticsContextImpMockInitiatio
     }
 
     private void initStatisticsContext() {
-        statisticsContext = new StatisticsContextImpl(mockedDeviceInfo, true, lifecycleService, convertorManager, mockedStatisticsManager);
+        statisticsContext = new StatisticsContextImpl<>(mockedDeviceInfo, true, lifecycleService, convertorManager, mockedStatisticsManager,
+            MultipartWriterProviderFactory.createDefaultProvider(mockedDeviceContext));
+
         statisticsContext.setStatisticsGatheringService(mockedStatisticsGatheringService);
         statisticsContext.setStatisticsGatheringOnTheFlyService(mockedStatisticsOnFlyGatheringService);
     }
@@ -74,7 +77,9 @@ public class StatisticsContextImplTest extends StatisticsContextImpMockInitiatio
      */
     @Test
     public void testClose() throws Exception {
-        final StatisticsContextImpl statisticsContext = new StatisticsContextImpl(mockedDeviceInfo, true, lifecycleService, convertorManager, mockedStatisticsManager);
+        final StatisticsContextImpl<MultipartReply> statisticsContext = new StatisticsContextImpl<>(mockedDeviceInfo, true, lifecycleService, convertorManager, mockedStatisticsManager,
+            MultipartWriterProviderFactory.createDefaultProvider(mockedDeviceContext));
+
         final RequestContext<Object> requestContext = statisticsContext.createRequestContext();
         statisticsContext.close();
         try {
index e6d11dae1126f73fd7bc725ea531ee72e6451fbc..9635fc23ed8f6481d5c15315d8d18c878c4329f3 100644 (file)
@@ -40,7 +40,6 @@ import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
-import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
@@ -48,8 +47,8 @@ import org.opendaylight.openflowplugin.api.openflow.registry.group.DeviceGroupRe
 import org.opendaylight.openflowplugin.api.openflow.registry.meter.DeviceMeterRegistry;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.StatisticsGatherer;
-import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProviderFactory;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
@@ -164,18 +163,14 @@ public class StatisticsGatheringUtilsTest {
     @Mock
     private ConnectionContext connectionAdapter;
     @Mock
-    private StatisticsGatherer statisticsService;
+    private StatisticsGatherer<MultipartReply> statisticsService;
     @Mock
     private DeviceInfo deviceInfo;
-    @Mock
-    private TxFacade txFacade;
 
-    private SinglePurposeMultipartReplyTranslator singlePurposeMultipartReplyTranslator;
+    private MultipartWriterProvider provider;
 
     @Before
     public void setUp() throws Exception {
-        final ConvertorManager convertorManager = ConvertorManagerFactory.createDefaultManager();
-        singlePurposeMultipartReplyTranslator = new SinglePurposeMultipartReplyTranslator(convertorManager);
         when(deviceContext.getDeviceState()).thenReturn(deviceState);
         when(deviceContext.getDeviceInfo()).thenReturn(deviceInfo);
         when(deviceContext.getDeviceFlowRegistry()).thenReturn(deviceFlowRegistry);
@@ -183,17 +178,17 @@ public class StatisticsGatheringUtilsTest {
         when(deviceContext.getDeviceMeterRegistry()).thenReturn(deviceMeterRegistry);
         when(deviceFlowRegistry.retrieveIdForFlow(Matchers.any(FlowRegistryKey.class))).thenReturn(flowDescriptor);
         when(deviceContext.getReadTransaction()).thenReturn(readTx);
-        when(txFacade.getReadTransaction()).thenReturn(readTx);
+        when(deviceContext.getReadTransaction()).thenReturn(readTx);
         when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionAdapter);
         when(connectionAdapter.getNodeId()).thenReturn(DUMMY_NODE_ID);
         when(connectionAdapter.getFeatures()).thenReturn(features);
         when(features.getDatapathId()).thenReturn(BigInteger.ONE);
         when(features.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
-
         when(deviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
         when(deviceInfo.getDatapathId()).thenReturn(BigInteger.ONE);
         when(deviceInfo.getNodeInstanceIdentifier()).thenReturn(dummyNodePath);
         when(deviceInfo.getNodeId()).thenReturn(DUMMY_NODE_ID);
+        provider = MultipartWriterProviderFactory.createDefaultProvider(deviceContext);
     }
 
     @Test
@@ -202,8 +197,7 @@ public class StatisticsGatheringUtilsTest {
         final ArgumentCaptor<InstanceIdentifier> flowPath = ArgumentCaptor.forClass(InstanceIdentifier.class);
         final ArgumentCaptor<Flow> flow = ArgumentCaptor.forClass(Flow.class);
 
-        StatisticsGatheringUtils.writeFlowStatistics(prepareFlowStatisticsData(),
-                deviceInfo, deviceContext.getDeviceFlowRegistry(), deviceContext);
+        provider.lookup(MultipartType.OFPMPFLOW).get().write(prepareFlowStatisticsData().iterator().next(), false);
 
         Mockito.verify(deviceContext).writeToTransaction(
                 dataStoreType.capture(), flowPath.capture(), flow.capture());
@@ -252,7 +246,7 @@ public class StatisticsGatheringUtilsTest {
                 .child(Group.class, new GroupKey(new org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId(groupIdValue)))
                 .augmentation(NodeGroupStatistics.class)
                 .child(GroupStatistics.class);
-        verify(txFacade).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL),
+        verify(deviceContext).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL),
                 Matchers.eq(groupPath), Matchers.any(GroupStatistics.class));
     }
 
@@ -283,7 +277,7 @@ public class StatisticsGatheringUtilsTest {
         verify(deviceContext, Mockito.never()).addDeleteToTxChain(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.<InstanceIdentifier<?>> any());
         verify(deviceGroupRegistry).removeMarked();
         verify(deviceGroupRegistry).store(storedGroupId);
-        verify(txFacade).writeToTransaction(
+        verify(deviceContext).writeToTransaction(
                 Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.eq(groupPath), Matchers.any(Group.class));
     }
 
@@ -317,7 +311,7 @@ public class StatisticsGatheringUtilsTest {
                 .child(Meter.class, new MeterKey(new org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId(meterIdValue)))
                 .augmentation(NodeMeterStatistics.class)
                 .child(MeterStatistics.class);
-        verify(txFacade).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL),
+        verify(deviceContext).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL),
                 Matchers.eq(meterPath), Matchers.any(MeterStatistics.class));
     }
 
@@ -341,7 +335,7 @@ public class StatisticsGatheringUtilsTest {
                 .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:" + DUMMY_NODE_ID_VALUE + ":11")))
                 .augmentation(FlowCapableNodeConnectorStatisticsData.class)
                 .child(FlowCapableNodeConnectorStatistics.class);
-        verify(txFacade).writeToTransaction(
+        verify(deviceContext).writeToTransaction(
                 Matchers.eq(LogicalDatastoreType.OPERATIONAL),
                 Matchers.eq(portPath),
                 Matchers.any(FlowCapableNodeConnectorStatistics.class));
@@ -371,7 +365,7 @@ public class StatisticsGatheringUtilsTest {
                 .child(Table.class, new TableKey((short) 0))
                 .augmentation(FlowTableStatisticsData.class)
                 .child(FlowTableStatistics.class);
-        verify(txFacade).writeToTransaction(
+        verify(deviceContext).writeToTransaction(
                 Matchers.eq(LogicalDatastoreType.OPERATIONAL),
                 Matchers.eq(tablePath),
                 Matchers.any(FlowTableStatistics.class));
@@ -405,7 +399,7 @@ public class StatisticsGatheringUtilsTest {
                 .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:" + DUMMY_NODE_ID_VALUE + ":11")))
                 .augmentation(FlowCapableNodeConnector.class)
                 .child(Queue.class, new QueueKey(new QueueId(queueIdValue)));
-        verify(txFacade).writeToTransaction(
+        verify(deviceContext).writeToTransaction(
                 Matchers.eq(LogicalDatastoreType.OPERATIONAL),
                 Matchers.eq(queuePath),
                 Matchers.any(Queue.class));
@@ -456,8 +450,8 @@ public class StatisticsGatheringUtilsTest {
 
         verify(deviceContext, Mockito.never()).addDeleteToTxChain(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.<InstanceIdentifier<?>>any());
 
-        final InOrder inOrder = Mockito.inOrder(txFacade);
-        inOrder.verify(txFacade).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.eq(tablePath), Matchers.any(Table.class));
+        final InOrder inOrder = Mockito.inOrder(deviceContext);
+        inOrder.verify(deviceContext).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.eq(tablePath), Matchers.any(Table.class));
     }
 
     @Test
@@ -486,7 +480,7 @@ public class StatisticsGatheringUtilsTest {
                 .child(Meter.class, new MeterKey(meterId));
         verify(deviceContext, Mockito.never()).addDeleteToTxChain(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.<InstanceIdentifier<?>>any());
         verify(deviceMeterRegistry).store(meterId);
-        verify(txFacade).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.eq(meterPath), Matchers.any(Meter.class));
+        verify(deviceContext).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.eq(meterPath), Matchers.any(Meter.class));
     }
 
     private void fireAndCheck(final MultipartType type, final List<MultipartReply> statsData) throws InterruptedException, ExecutionException, TimeoutException {
@@ -494,15 +488,17 @@ public class StatisticsGatheringUtilsTest {
                 .thenReturn(Futures.immediateFuture(RpcResultBuilder.success(statsData).build()));
 
         final ListenableFuture<Boolean> gatherStatisticsResult = StatisticsGatheringUtils.gatherStatistics(
-                statisticsService,
-                deviceInfo,
-                type,
-                txFacade,
-                deviceContext,
-                false,
-                singlePurposeMultipartReplyTranslator);
-        Assert.assertTrue(gatherStatisticsResult.get(1, TimeUnit.SECONDS).booleanValue());
-        verify(txFacade).submitTransaction();
+            statisticsService,
+            deviceInfo,
+            type,
+            deviceContext,
+            deviceContext,
+            false,
+            ConvertorManagerFactory.createDefaultManager(),
+            provider);
+
+        Assert.assertTrue(gatherStatisticsResult.get(1, TimeUnit.SECONDS));
+        verify(deviceContext).submitTransaction();
     }
 
     private static MultipartReplyMessage assembleMPReplyMessage(final MultipartType type, final MultipartReplyBody mpReplyGroupCaseBld) {
@@ -532,10 +528,10 @@ public class StatisticsGatheringUtilsTest {
         final KeyedInstanceIdentifier<Table, TableKey> tablePath = deviceInfo.getNodeInstanceIdentifier()
                 .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId));
 
-        StatisticsGatheringUtils.deleteAllKnownFlows(deviceInfo,
-                deviceContext.getDeviceFlowRegistry(), txFacade);
+        StatisticsGatheringUtils.deleteAllKnownFlows(deviceContext, deviceInfo.getNodeInstanceIdentifier()
+            .augmentation(FlowCapableNode.class), false);
 
-        verify(txFacade).writeToTransaction(
+        verify(deviceContext).writeToTransaction(
                 LogicalDatastoreType.OPERATIONAL,
                 tablePath,
                 tableDataBld.setFlow(Collections.<Flow>emptyList()).build());
index 8140e84d59cfb956ad26dedb01cc81edb0e9575f..7cb1ab1a15558224b233eb514c93b9c0e8c27a1e 100644 (file)
@@ -50,7 +50,7 @@ public abstract class AbstractSingleStatsServiceTest extends AbstractStatsServic
         };
 
         Mockito.when(rqContextStack.<Object>createRequestContext()).thenReturn(rqContext);
-        Mockito.doAnswer(closeRequestFutureAnswer).when(multiMsgCollector).endCollecting();
+        Mockito.doAnswer(closeRequestFutureAnswer).when(multiMsgCollector).endCollecting(null);
         Mockito.doAnswer(closeRequestFutureAnswer).when(multiMsgCollector).endCollecting(Matchers.any(EventIdentifier.class));
     }
 }
index fa05edea0edcb6447631c9aca9e9531e076daaf7..b208416adff64f95d83fd9e4a44f96710703f7e7 100644 (file)
@@ -101,7 +101,7 @@ public class AbstractCompatibleStatServiceTest extends AbstractStatsServiceTest
         Mockito.when(deviceContext.getDeviceInfo()).thenReturn(deviceInfo);
         Mockito.when(deviceInfo.getNodeId()).thenReturn(NODE_ID);
         Mockito.when(deviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
-        Mockito.doAnswer(closeRequestFutureAnswer).when(multiMsgCollector).endCollecting();
+        Mockito.doAnswer(closeRequestFutureAnswer).when(multiMsgCollector).endCollecting(null);
         Mockito.doAnswer(closeRequestFutureAnswer).when(multiMsgCollector).endCollecting(Matchers.any(EventIdentifier.class));
 
         Mockito.doAnswer(answerVoidToCallback).when(outboundQueueProvider)
index dd292d112d65d46665ae90d4d7ad4049c3335234..905f8a2c88a0ad515aeff48b51c32b586ba63778 100644 (file)
@@ -13,11 +13,13 @@ import org.junit.Test;
 import org.mockito.Mockito;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProviderFactory;
 import org.opendaylight.openflowplugin.impl.services.ServiceMocking;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 
@@ -27,12 +29,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 public class StatisticsGatheringOnTheFlyServiceTest extends ServiceMocking {
 
     public static final NodeId NODE_ID = new NodeId(DUMMY_NODE_ID);
-    private StatisticsGatheringOnTheFlyService statisticsGatheringService;
+    private StatisticsGatheringOnTheFlyService<MultipartReply> statisticsGatheringService;
 
     @Override
     protected void setup() {
         final ConvertorManager convertorManager = ConvertorManagerFactory.createDefaultManager();
-        statisticsGatheringService = new StatisticsGatheringOnTheFlyService(mockedRequestContextStack, mockedDeviceContext, convertorManager);
+        statisticsGatheringService = new StatisticsGatheringOnTheFlyService<>(mockedRequestContextStack, mockedDeviceContext, convertorManager, MultipartWriterProviderFactory.createDefaultProvider(mockedDeviceContext));
         Mockito.doReturn(NODE_ID).when(mockedPrimConnectionContext).getNodeId();
         Mockito.when(mockedDeviceInfo.getNodeId()).thenReturn(NODE_ID);
         Mockito.when(mockedDeviceContext.getDeviceInfo().getNodeId()).thenReturn(NODE_ID);
@@ -54,4 +56,4 @@ public class StatisticsGatheringOnTheFlyServiceTest extends ServiceMocking {
         Assert.assertEquals(xidValue, request.getXid().longValue());
         Assert.assertNotNull(request);
     }
-}
\ No newline at end of file
+}
index 16929cacb75a60c1866bbdfb04c2bfb48280420a..f9f367bebe94a5ca8796fcda3c17a6cdb2031599 100644 (file)
@@ -28,6 +28,8 @@ import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
+import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProviderFactory;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
 import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
@@ -75,7 +77,7 @@ public abstract class AbstractDirectStatisticsServiceTest {
     protected NodeConnectorId nodeConnectorId;
     protected KeyedInstanceIdentifier<Node, NodeKey> nodeInstanceIdentifier;
     protected ConvertorManager convertorManager;
-
+    protected MultipartWriterProvider multipartWriterProvider;
     protected static NodeRef createNodeRef(String nodeIdValue) {
         InstanceIdentifier<Node> nodePath = InstanceIdentifier.create(Nodes.class)
                 .child(Node.class, new NodeKey(new NodeId(nodeIdValue)));
@@ -93,7 +95,6 @@ public abstract class AbstractDirectStatisticsServiceTest {
                 .child(Node.class, new NodeKey(new NodeId(NODE_ID)));
 
         convertorManager = ConvertorManagerFactory.createDefaultManager();
-
         when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
         when(deviceContext.getMessageSpy()).thenReturn(messageSpy);
         when(deviceContext.getMultiMsgCollector(any())).thenReturn(multiMsgCollector);
@@ -110,6 +111,7 @@ public abstract class AbstractDirectStatisticsServiceTest {
         when(connectionContext.getOutboundQueueProvider()).thenReturn(outboundQueueProvider);
         when(features.getVersion()).thenReturn(OF_VERSION);
         when(features.getDatapathId()).thenReturn(DATAPATH_ID);
+        multipartWriterProvider = MultipartWriterProviderFactory.createDefaultProvider(deviceContext);
         setUp();
     }
 
@@ -123,4 +125,4 @@ public abstract class AbstractDirectStatisticsServiceTest {
 
     @Test
     public abstract void testStoreStatistics() throws Exception;
-}
\ No newline at end of file
+}
index 33b0746aa9635cb325a976aa2853d2d4bd4ea930..73ef8601bde63dfc1b766169d366e7de74749717 100644 (file)
@@ -35,15 +35,15 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 @RunWith(MockitoJUnitRunner.class)
 public class OpendaylightDirectStatisticsServiceImplTest {
     @Mock
-    FlowDirectStatisticsService flowDirectStatisticsService;
+    AbstractFlowDirectStatisticsService flowDirectStatisticsService;
     @Mock
-    GroupDirectStatisticsService groupDirectStatisticsService;
+    AbstractGroupDirectStatisticsService groupDirectStatisticsService;
     @Mock
-    MeterDirectStatisticsService meterDirectStatisticsService;
+    AbstractMeterDirectStatisticsService meterDirectStatisticsService;
     @Mock
-    NodeConnectorDirectStatisticsService nodeConnectorDirectStatisticsService;
+    AbstractPortDirectStatisticsService nodeConnectorDirectStatisticsService;
     @Mock
-    QueueDirectStatisticsService queueDirectStatisticsService;
+    AbstractQueueDirectStatisticsService queueDirectStatisticsService;
 
     @Mock
     GetGroupStatisticsInput getGroupStatisticsInput;
@@ -55,18 +55,18 @@ public class OpendaylightDirectStatisticsServiceImplTest {
     GetMeterStatisticsInput getMeterStatisticsInput;
     @Mock
     GetNodeConnectorStatisticsInput getNodeConnectorStatisticsInput;
-    
+
     private OpendaylightDirectStatisticsService service;
     private OpendaylightDirectStatisticsService emptyService;
 
     @Before
     public void setUp() throws Exception {
         final OpendaylightDirectStatisticsServiceProvider provider = new OpendaylightDirectStatisticsServiceProvider();
-        provider.register(FlowDirectStatisticsService.class, flowDirectStatisticsService);
-        provider.register(GroupDirectStatisticsService.class, groupDirectStatisticsService);
-        provider.register(MeterDirectStatisticsService.class, meterDirectStatisticsService);
-        provider.register(NodeConnectorDirectStatisticsService.class, nodeConnectorDirectStatisticsService);
-        provider.register(QueueDirectStatisticsService.class, queueDirectStatisticsService);
+        provider.register(AbstractFlowDirectStatisticsService.class, flowDirectStatisticsService);
+        provider.register(AbstractGroupDirectStatisticsService.class, groupDirectStatisticsService);
+        provider.register(AbstractMeterDirectStatisticsService.class, meterDirectStatisticsService);
+        provider.register(AbstractPortDirectStatisticsService.class, nodeConnectorDirectStatisticsService);
+        provider.register(AbstractQueueDirectStatisticsService.class, queueDirectStatisticsService);
 
         service = new OpendaylightDirectStatisticsServiceImpl(provider);
         emptyService = new OpendaylightDirectStatisticsServiceImpl(new OpendaylightDirectStatisticsServiceProvider());
@@ -87,7 +87,7 @@ public class OpendaylightDirectStatisticsServiceImplTest {
         assertFalse(result.isSuccessful());
 
         for (RpcError error : result.getErrors()) {
-            assertTrue(error.getMessage().contains(GroupDirectStatisticsService.class.getSimpleName()));
+            assertTrue(error.getMessage().contains(AbstractGroupDirectStatisticsService.class.getSimpleName()));
         }
 
         verify(groupDirectStatisticsService, times(0)).handleAndReply(getGroupStatisticsInput);
@@ -108,7 +108,7 @@ public class OpendaylightDirectStatisticsServiceImplTest {
         assertFalse(result.isSuccessful());
 
         for (RpcError error : result.getErrors()) {
-            assertTrue(error.getMessage().contains(QueueDirectStatisticsService.class.getSimpleName()));
+            assertTrue(error.getMessage().contains(AbstractQueueDirectStatisticsService.class.getSimpleName()));
         }
 
         verify(queueDirectStatisticsService, times(0)).handleAndReply(getQueueStatisticsInput);
@@ -129,7 +129,7 @@ public class OpendaylightDirectStatisticsServiceImplTest {
         assertFalse(result.isSuccessful());
 
         for (RpcError error : result.getErrors()) {
-            assertTrue(error.getMessage().contains(FlowDirectStatisticsService.class.getSimpleName()));
+            assertTrue(error.getMessage().contains(AbstractFlowDirectStatisticsService.class.getSimpleName()));
         }
 
         verify(flowDirectStatisticsService, times(0)).handleAndReply(getFlowStatisticsInput);
@@ -150,7 +150,7 @@ public class OpendaylightDirectStatisticsServiceImplTest {
         assertFalse(result.isSuccessful());
 
         for (RpcError error : result.getErrors()) {
-            assertTrue(error.getMessage().contains(MeterDirectStatisticsService.class.getSimpleName()));
+            assertTrue(error.getMessage().contains(AbstractMeterDirectStatisticsService.class.getSimpleName()));
         }
 
         verify(meterDirectStatisticsService, times(0)).handleAndReply(getMeterStatisticsInput);
@@ -171,9 +171,9 @@ public class OpendaylightDirectStatisticsServiceImplTest {
         assertFalse(result.isSuccessful());
 
         for (RpcError error : result.getErrors()) {
-            assertTrue(error.getMessage().contains(NodeConnectorDirectStatisticsService.class.getSimpleName()));
+            assertTrue(error.getMessage().contains(AbstractPortDirectStatisticsService.class.getSimpleName()));
         }
 
         verify(nodeConnectorDirectStatisticsService, times(0)).handleAndReply(getNodeConnectorStatisticsInput);
     }
-}
\ No newline at end of file
+}
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics.services.direct;
+package org.opendaylight.openflowplugin.impl.statistics.services.direct.multilayer;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -22,6 +22,7 @@ import java.util.Collections;
 import java.util.List;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractDirectStatisticsServiceTest;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
@@ -29,6 +30,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.F
 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.types.rev131026.flow.MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyFlowCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.MultipartReplyFlow;
@@ -43,7 +45,7 @@ public class FlowDirectStatisticsServiceTest extends AbstractDirectStatisticsSer
 
     @Override
     public void setUp() throws Exception {
-        service = new FlowDirectStatisticsService(requestContextStack, deviceContext, convertorManager);
+        service = new FlowDirectStatisticsService(requestContextStack, deviceContext, convertorManager, multipartWriterProvider);
         final DeviceFlowRegistry registry = mock(DeviceFlowRegistry.class);
         when(registry.storeIfNecessary(any())).thenReturn(new FlowId("1"));
         when(deviceContext.getDeviceFlowRegistry()).thenReturn(registry);
@@ -104,7 +106,7 @@ public class FlowDirectStatisticsServiceTest extends AbstractDirectStatisticsSer
         final GetFlowStatisticsOutput output = mock(GetFlowStatisticsOutput.class);
         when(output.getFlowAndStatisticsMapList()).thenReturn(stats);
 
-        service.storeStatistics(output);
+        multipartWriterProvider.lookup(MultipartType.OFPMPFLOW).get().write(output, true);
         verify(deviceContext).writeToTransactionWithParentsSlow(eq(LogicalDatastoreType.OPERATIONAL), any(), any());
     }
-}
\ No newline at end of file
+}
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics.services.direct;
+package org.opendaylight.openflowplugin.impl.statistics.services.direct.multilayer;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -21,9 +21,11 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractDirectStatisticsServiceTest;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.MultipartReplyGroup;
@@ -38,7 +40,7 @@ public class GroupDirectStatisticsServiceTest extends AbstractDirectStatisticsSe
 
     @Override
     public void setUp() throws Exception {
-        service = new GroupDirectStatisticsService(requestContextStack, deviceContext, convertorManager);
+        service = new GroupDirectStatisticsService(requestContextStack, deviceContext, convertorManager, multipartWriterProvider);
     }
 
     @Override
@@ -94,7 +96,7 @@ public class GroupDirectStatisticsServiceTest extends AbstractDirectStatisticsSe
         final GetGroupStatisticsOutput output = mock(GetGroupStatisticsOutput.class);
         when(output.getGroupStats()).thenReturn(stats);
 
-        service.storeStatistics(output);
+        multipartWriterProvider.lookup(MultipartType.OFPMPGROUP).get().write(output, true);
         verify(deviceContext).writeToTransactionWithParentsSlow(eq(LogicalDatastoreType.OPERATIONAL), any(), any());
     }
-}
\ No newline at end of file
+}
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics.services.direct;
+package org.opendaylight.openflowplugin.impl.statistics.services.direct.multilayer;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -21,9 +21,11 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractDirectStatisticsServiceTest;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter._case.MultipartReplyMeter;
@@ -38,7 +40,7 @@ public class MeterDirectStatisticsServiceTest extends AbstractDirectStatisticsSe
 
     @Override
     public void setUp() throws Exception {
-        service = new MeterDirectStatisticsService(requestContextStack, deviceContext, convertorManager);
+        service = new MeterDirectStatisticsService(requestContextStack, deviceContext, convertorManager, multipartWriterProvider);
     }
 
     @Override
@@ -94,7 +96,7 @@ public class MeterDirectStatisticsServiceTest extends AbstractDirectStatisticsSe
         final GetMeterStatisticsOutput output = mock(GetMeterStatisticsOutput.class);
         when(output.getMeterStats()).thenReturn(stats);
 
-        service.storeStatistics(output);
+        multipartWriterProvider.lookup(MultipartType.OFPMPMETER).get().write(output, true);
         verify(deviceContext).writeToTransactionWithParentsSlow(eq(LogicalDatastoreType.OPERATIONAL), any(), any());
     }
-}
\ No newline at end of file
+}
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics.services.direct;
+package org.opendaylight.openflowplugin.impl.statistics.services.direct.multilayer;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -20,8 +20,10 @@ import java.math.BigInteger;
 import java.util.Arrays;
 import java.util.List;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractDirectStatisticsServiceTest;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortStatsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.MultipartReplyPortStats;
@@ -31,11 +33,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
 
 public class NodeConnectorDirectStatisticsServiceTest extends AbstractDirectStatisticsServiceTest {
-    private NodeConnectorDirectStatisticsService service;
+    private PortDirectStatisticsService service;
 
     @Override
     public void setUp() throws Exception {
-        service = new NodeConnectorDirectStatisticsService(requestContextStack, deviceContext, convertorManager);
+        service = new PortDirectStatisticsService(requestContextStack, deviceContext, convertorManager, multipartWriterProvider);
     }
 
     @Override
@@ -95,7 +97,7 @@ public class NodeConnectorDirectStatisticsServiceTest extends AbstractDirectStat
         final GetNodeConnectorStatisticsOutput output = mock(GetNodeConnectorStatisticsOutput.class);
         when(output.getNodeConnectorStatisticsAndPortNumberMap()).thenReturn(stats);
 
-        service.storeStatistics(output);
+        multipartWriterProvider.lookup(MultipartType.OFPMPPORTSTATS).get().write(output, true);
         verify(deviceContext).writeToTransactionWithParentsSlow(eq(LogicalDatastoreType.OPERATIONAL), any(), any());
     }
-}
\ No newline at end of file
+}
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.statistics.services.direct;
+package org.opendaylight.openflowplugin.impl.statistics.services.direct.multilayer;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -20,10 +20,12 @@ import java.math.BigInteger;
 import java.util.Arrays;
 import java.util.List;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.AbstractDirectStatisticsServiceTest;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsOutput;
 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.openflow.common.types.rev130731.MultipartType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyQueueCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.MultipartReplyQueue;
@@ -38,7 +40,7 @@ public class QueueDirectStatisticsServiceTest extends AbstractDirectStatisticsSe
 
     @Override
     public void setUp() throws Exception {
-        service = new QueueDirectStatisticsService(requestContextStack, deviceContext, convertorManager);
+        service = new QueueDirectStatisticsService(requestContextStack, deviceContext, convertorManager, multipartWriterProvider);
     }
 
     @Override
@@ -92,7 +94,7 @@ public class QueueDirectStatisticsServiceTest extends AbstractDirectStatisticsSe
         final GetQueueStatisticsOutput output = mock(GetQueueStatisticsOutput.class);
         when(output.getQueueIdAndStatisticsMap()).thenReturn(maps);
 
-        service.storeStatistics(output);
+        multipartWriterProvider.lookup(MultipartType.OFPMPQUEUE).get().write(output, true);
         verify(deviceContext).writeToTransactionWithParentsSlow(eq(LogicalDatastoreType.OPERATIONAL), any(), any());
     }
-}
\ No newline at end of file
+}
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtilsTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtilsTest.java
deleted file mode 100644 (file)
index cc6e509..0000000
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (c) 2016 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.openflowplugin.impl.util;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Matchers;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.mockito.stubbing.Answer;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
-import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
-import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandler;
-import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandlerRegistration;
-import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
-import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
-import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
-import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
-import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
-import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
-import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
-import org.opendaylight.openflowplugin.impl.device.DeviceContextImpl;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeatures;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.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.NodeMeterFeatures;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ActionType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.Capabilities;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.CapabilitiesV10;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupCapabilities;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupTypes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterBandTypeBitmap;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterFlags;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupFeaturesCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterFeaturesCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortDescCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyTableFeaturesCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDesc;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDescBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.features._case.MultipartReplyGroupFeatures;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.features._case.MultipartReplyGroupFeaturesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter.features._case.MultipartReplyMeterFeaturesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.desc._case.MultipartReplyPortDescBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.desc._case.multipart.reply.port.desc.PortsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table.features._case.MultipartReplyTableFeatures;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table.features._case.MultipartReplyTableFeaturesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table.features._case.multipart.reply.table.features.TableFeatures;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table.features._case.multipart.reply.table.features.TableFeaturesBuilder;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-
-@RunWith(MockitoJUnitRunner.class)
-public class DeviceInitializationUtilsTest {
-
-    public static final String DUMMY_NODE_ID = "dummyNodeId";
-    public static final NodeId NODE_ID = new NodeId(DUMMY_NODE_ID);
-    private static final KeyedInstanceIdentifier<Node, NodeKey> DUMMY_NODE_II = InstanceIdentifier.create(Nodes.class)
-            .child(Node.class, new NodeKey(new NodeId(DUMMY_NODE_ID)));
-    private static final Short DUMMY_TABLE_ID = 1;
-    private static final Long DUMMY_MAX_METER = 544L;
-    private static final String DUMMY_DATAPATH_ID = "44";
-    private static final Long DUMMY_PORT_NUMBER = 21L;
-
-    @Mock
-    CheckedFuture<Void, TransactionCommitFailedException> mockedFuture;
-    @Mock
-    private FeaturesReply mockFeatures;
-    @Mock
-    private OutboundQueue outboundQueueProvider;
-    @Mock
-    private DeviceInitializationPhaseHandler deviceInitPhaseHandler;
-    @Mock
-    private TranslatorLibrary translatorLibrary;
-    @Mock
-    private ConnectionContext mockConnectionContext;
-    @Mock
-    private ConnectionAdapter mockedConnectionAdapter;
-    @Mock
-    private DeviceContextImpl mockedDeviceContext;
-    @Mock
-    private DeviceInfo mockedDeviceInfo;
-    @Mock
-    private DeviceInitializationUtils deviceInitializationUtils;
-    @Mock
-    private DeviceInfo deviceInfo;
-
-    private ConvertorManager convertorManager;
-
-    @Before
-    public void setUp() throws Exception {
-        convertorManager = ConvertorManagerFactory.createDefaultManager();
-
-        when(mockConnectionContext.getNodeId()).thenReturn(NODE_ID);
-        when(mockConnectionContext.getFeatures()).thenReturn(mockFeatures);
-        when(mockConnectionContext.getConnectionAdapter()).thenReturn(mockedConnectionAdapter);
-        when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockConnectionContext);
-        when(mockedDeviceContext.getDeviceInfo()).thenReturn(mockedDeviceInfo);
-        when(mockedDeviceInfo.getNodeId()).thenReturn(NODE_ID);
-
-        final Capabilities capabilitiesV13 = mock(Capabilities.class);
-        final CapabilitiesV10 capabilitiesV10 = mock(CapabilitiesV10.class);
-        when(mockFeatures.getCapabilities()).thenReturn(capabilitiesV13);
-        when(mockFeatures.getCapabilitiesV10()).thenReturn(capabilitiesV10);
-        when(mockFeatures.getDatapathId()).thenReturn(BigInteger.valueOf(21L));
-    }
-
-    //TODO: need to be rewritten with power mock to properly test statis class
-    @Test
-    public void initializeNodeInformationTest() throws Exception {
-        DeviceState mockedDeviceState = mock(DeviceState.class);
-        MultiMsgCollector msgCollector = mock(MultiMsgCollector.class);
-        TranslatorLibrary tLibrary = mock(TranslatorLibrary.class);
-
-        GetFeaturesOutput mockedFeatures = mock(GetFeaturesOutput.class);
-        when(mockedFeatures.getTables()).thenReturn((short) 2);
-        when(mockedDeviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_0);
-
-        when(mockedDeviceInfo.getNodeInstanceIdentifier()).thenReturn(DUMMY_NODE_II);
-        when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
-        when(mockedDeviceContext.getMultiMsgCollector(Mockito.any(RequestContext.class))).thenReturn(msgCollector);
-        when(mockedDeviceContext.oook()).thenReturn(tLibrary);
-
-        final ConnectionContext connectionContext = buildMockConnectionContext(OFConstants.OFP_VERSION_1_0);
-        when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
-    }
-
-    @Test
-    public void chainTableTrunkWriteOF10Test() throws Exception {
-        DeviceState mockedDeviceState = mock(DeviceState.class);
-
-        final GetFeaturesOutput mockedFeatures = mock(GetFeaturesOutput.class);
-        when(mockedFeatures.getTables()).thenReturn((short) 2);
-        when(mockConnectionContext.getFeatures()).thenReturn(mockedFeatures);
-
-        when(mockedDeviceInfo.getNodeInstanceIdentifier()).thenReturn(DUMMY_NODE_II);
-        when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
-
-        final RpcResult<List<MultipartReply>> mockedRpcResult = mock(RpcResult.class);
-        when(mockedRpcResult.isSuccessful()).thenReturn(true);
-        final List<RpcResult<List<MultipartReply>>> data = new ArrayList<RpcResult<List<MultipartReply>>>();
-        data.add(mockedRpcResult);
-        data.add(mockedRpcResult);
-
-        DeviceInitializationUtils.chainTableTrunkWriteOF10(mockedDeviceContext, Futures.immediateFuture(data));
-        verify(mockedDeviceContext, times(3)).writeToTransaction(any(LogicalDatastoreType.class),
-                Matchers.<InstanceIdentifier<FlowCapableNode>> any(), any(FlowCapableNode.class));
-    }
-
-    @Test
-    public void testTranslateAndWriteReplyTypeDesc() throws Exception {
-        final ConnectionContext connectionContext = buildMockConnectionContext(OFConstants.OFP_VERSION_1_3);
-        when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
-        final DeviceState deviceState = mock(DeviceState.class);
-        when(mockedDeviceContext.getDeviceState()).thenReturn(deviceState);
-
-        final Collection<MultipartReply> multipartReplyMessages = prepareDataforTypeDesc(mockedDeviceContext);
-
-        DeviceInitializationUtils.translateAndWriteReply(MultipartType.OFPMPDESC, mockedDeviceContext, DUMMY_NODE_II, multipartReplyMessages, convertorManager);
-        verify(mockedDeviceContext)
-                .writeToTransaction(eq(LogicalDatastoreType.OPERATIONAL), eq(DUMMY_NODE_II.augmentation(FlowCapableNode.class)), any(FlowCapableNode.class));
-    }
-
-    @Test
-    public void translateAndWriteReplyTypeTableFeatures() throws Exception {
-        when(mockedDeviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
-        TableFeaturesBuilder tableFeature = new TableFeaturesBuilder();
-        tableFeature.setTableId(DUMMY_TABLE_ID);
-        final List<TableFeatures> tableFeatures = new ArrayList<>();
-        tableFeatures.add(tableFeature.build());
-
-        final MultipartReplyTableFeatures multipartReplyTableFeatures = new MultipartReplyTableFeaturesBuilder().setTableFeatures(tableFeatures).build();
-        final MultipartReplyTableFeaturesCaseBuilder multipartReplyTableFeaturesCaseBuilder = new MultipartReplyTableFeaturesCaseBuilder();
-        multipartReplyTableFeaturesCaseBuilder.setMultipartReplyTableFeatures(multipartReplyTableFeatures);
-
-        final MultipartReplyMessage multipartReplyMessage = new MultipartReplyMessageBuilder().setMultipartReplyBody(multipartReplyTableFeaturesCaseBuilder.build()).build();
-        final Set<MultipartReply> multipartReplyMessages = Collections.<MultipartReply>singleton(multipartReplyMessage);
-        DeviceInitializationUtils.translateAndWriteReply(MultipartType.OFPMPTABLEFEATURES, mockedDeviceContext, DUMMY_NODE_II, multipartReplyMessages, convertorManager);
-        verify(mockedDeviceContext)
-                .writeToTransaction(eq(LogicalDatastoreType.OPERATIONAL),
-                        eq(DUMMY_NODE_II.augmentation(FlowCapableNode.class).child(Table.class, new TableKey(DUMMY_TABLE_ID))), any(Table.class));
-
-    }
-
-    @Test
-    public void translateAndWriteReplyTypeMeterFeatures() throws Exception {
-        DeviceState mockedDeviceState = mock(DeviceState.class);
-        when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
-
-        final MultipartReplyMeterFeaturesBuilder multipartReplyMeterFeaturesBuilder = new MultipartReplyMeterFeaturesBuilder();
-        multipartReplyMeterFeaturesBuilder.setBandTypes(new MeterBandTypeBitmap(true, true));
-        multipartReplyMeterFeaturesBuilder.setCapabilities(new MeterFlags(true, true, true, true));
-        multipartReplyMeterFeaturesBuilder.setMaxMeter(DUMMY_MAX_METER);
-
-        final MultipartReplyMeterFeaturesCaseBuilder multipartReplyMeterFeaturesCaseBuilder = new MultipartReplyMeterFeaturesCaseBuilder();
-        multipartReplyMeterFeaturesCaseBuilder.setMultipartReplyMeterFeatures(multipartReplyMeterFeaturesBuilder.build());
-
-        final MultipartReplyMessage multipartReplyMessage = new MultipartReplyMessageBuilder().setMultipartReplyBody(multipartReplyMeterFeaturesCaseBuilder.build()).build();
-        final Set<MultipartReply> multipartReplyMessages = Collections.<MultipartReply>singleton(multipartReplyMessage);
-        DeviceInitializationUtils.translateAndWriteReply(MultipartType.OFPMPMETERFEATURES, mockedDeviceContext, DUMMY_NODE_II, multipartReplyMessages, convertorManager);
-        verify(mockedDeviceContext)
-                .writeToTransaction(eq(LogicalDatastoreType.OPERATIONAL), eq(DUMMY_NODE_II.augmentation(NodeMeterFeatures.class)), any(NodeMeterFeatures.class));
-        verify(mockedDeviceState).setMeterAvailable(eq(true));
-    }
-
-    @Test
-    public void translateAndWriteReplyTypeGroupFeatures() throws Exception {
-        MultipartReplyGroupFeaturesBuilder multipartReplyGroupFeaturesBuilder = new MultipartReplyGroupFeaturesBuilder();
-        multipartReplyGroupFeaturesBuilder.setTypes(new GroupTypes(true, true, true, true));
-        multipartReplyGroupFeaturesBuilder.setCapabilities(new GroupCapabilities(true, true, true, true));
-        final ActionType actionType = new ActionType(true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true);
-        multipartReplyGroupFeaturesBuilder.setActionsBitmap(Lists.newArrayList(actionType));
-
-        final MultipartReplyGroupFeatures multipartReplyGroupFeatures = multipartReplyGroupFeaturesBuilder.build();
-
-        final MultipartReplyGroupFeaturesCaseBuilder multipartReplyGroupFeaturesCaseBuilder = new MultipartReplyGroupFeaturesCaseBuilder();
-        multipartReplyGroupFeaturesCaseBuilder.setMultipartReplyGroupFeatures(multipartReplyGroupFeatures);
-
-        final MultipartReplyMessage multipartReplyMessage = new MultipartReplyMessageBuilder().setMultipartReplyBody(multipartReplyGroupFeaturesCaseBuilder.build()).build();
-        final Set<MultipartReply> multipartReplyMessages = Collections.<MultipartReply>singleton(multipartReplyMessage);
-
-        DeviceInitializationUtils.translateAndWriteReply(MultipartType.OFPMPGROUPFEATURES, mockedDeviceContext, DUMMY_NODE_II, multipartReplyMessages, convertorManager);
-        verify(mockedDeviceContext)
-                .writeToTransaction(eq(LogicalDatastoreType.OPERATIONAL), eq(DUMMY_NODE_II.augmentation(NodeGroupFeatures.class)), any(NodeGroupFeatures.class));
-    }
-
-
-    @Test
-    public void translateAndWriteReplyTypePortDesc() throws Exception {
-        ConnectionContext mockedPrimaryConnectionContext = mock(ConnectionContext.class);
-        FeaturesReply mockedFeatures = mock(FeaturesReply.class);
-        when(mockedFeatures.getDatapathId()).thenReturn(new BigInteger(DUMMY_DATAPATH_ID));
-        when(mockedPrimaryConnectionContext.getFeatures()).thenReturn(mockedFeatures);
-        when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedPrimaryConnectionContext);
-        final DeviceState mockedDeviceState = mock(DeviceState.class);
-        when(mockedDeviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_0);
-        when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
-        final MessageTranslator mockedTranslator = mock(MessageTranslator.class);
-        when(translatorLibrary.lookupTranslator(any(TranslatorKey.class))).thenReturn(mockedTranslator);
-        when(mockedDeviceContext.oook()).thenReturn(translatorLibrary);
-
-        final MultipartReplyPortDescBuilder multipartReplyPortDescBuilder = new MultipartReplyPortDescBuilder();
-
-        final PortsBuilder portsBuilder = new PortsBuilder();
-        portsBuilder.setPortNo(DUMMY_PORT_NUMBER);
-
-        multipartReplyPortDescBuilder.setPorts(Lists.newArrayList(portsBuilder.build()));
-
-        final MultipartReplyPortDescCaseBuilder multipartReplyPortDescCaseBuilder = new MultipartReplyPortDescCaseBuilder();
-        multipartReplyPortDescCaseBuilder.setMultipartReplyPortDesc(multipartReplyPortDescBuilder.build());
-
-        final MultipartReplyMessage multipartReplyMessage = new MultipartReplyMessageBuilder().setMultipartReplyBody(multipartReplyPortDescCaseBuilder.build()).build();
-        final Set<MultipartReply> multipartReplyMessages = Collections.<MultipartReply>singleton(multipartReplyMessage);
-
-        DeviceInitializationUtils.translateAndWriteReply(MultipartType.OFPMPPORTDESC, mockedDeviceContext, DUMMY_NODE_II, multipartReplyMessages, convertorManager);
-        verify(mockedDeviceContext).writeToTransaction(eq(LogicalDatastoreType.OPERATIONAL),
-                Matchers.<InstanceIdentifier<NodeConnector>> any(), any(NodeConnector.class));
-    }
-
-    @Test
-    public void createSuccessProcessingCallbackTest() throws Exception {
-        DeviceState mockedDeviceState = mock(DeviceState.class);
-        when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
-
-        final ConnectionContext connectionContext = buildMockConnectionContext(OFConstants.OFP_VERSION_1_3);
-
-        final List<MultipartReply> multipartReplies = new ArrayList<>(prepareDataforTypeDesc(mockedDeviceContext));
-        final RpcResult<List<MultipartReply>> result = RpcResultBuilder.<List<MultipartReply>>success(multipartReplies).build();
-        ListenableFuture<RpcResult<List<MultipartReply>>> mockedRequestContextFuture = Futures.immediateFuture(result);
-
-        DeviceInitializationUtils.createSuccessProcessingCallback(MultipartType.OFPMPDESC, mockedDeviceContext, DUMMY_NODE_II, mockedRequestContextFuture, convertorManager);
-        verify(mockedDeviceContext).writeToTransaction(eq(LogicalDatastoreType.OPERATIONAL), eq(DUMMY_NODE_II.augmentation(FlowCapableNode.class)), any(FlowCapableNode.class));
-
-        final RpcResult<List<MultipartReply>> rpcResult = RpcResultBuilder.<List<MultipartReply>>failed().withError(RpcError.ErrorType.PROTOCOL, "dummy error").build();
-        mockedRequestContextFuture = Futures.immediateFuture(rpcResult);
-        DeviceInitializationUtils.createSuccessProcessingCallback(MultipartType.OFPMPDESC, mockedDeviceContext, DUMMY_NODE_II, mockedRequestContextFuture, convertorManager);
-        verify(mockedDeviceContext).writeToTransaction(eq(LogicalDatastoreType.OPERATIONAL), eq(DUMMY_NODE_II.augmentation(FlowCapableNode.class)), any(FlowCapableNode.class));
-    }
-
-    private Collection<MultipartReply> prepareDataforTypeDesc(final DeviceContext mockedDeviceContext) {
-        final MultipartReplyDesc multipartReplyDesc = new MultipartReplyDescBuilder().build();
-
-        final MultipartReplyDescCaseBuilder multipartReplyDescCaseBuilder = new MultipartReplyDescCaseBuilder();
-        multipartReplyDescCaseBuilder.setMultipartReplyDesc(multipartReplyDesc);
-
-        final MultipartReplyMessage multipartReplyMessage = new MultipartReplyMessageBuilder().setMultipartReplyBody(multipartReplyDescCaseBuilder.build()).build();
-        return Collections.<MultipartReply>singleton(multipartReplyMessage);
-
-    }
-
-    protected ConnectionContext buildMockConnectionContext(final short ofpVersion) {
-        when(mockFeatures.getVersion()).thenReturn(ofpVersion);
-        when(outboundQueueProvider.reserveEntry()).thenReturn(43L);
-        Mockito.doAnswer(new Answer<Void>() {
-            @Override
-            public Void answer(final InvocationOnMock invocation) throws Throwable {
-                final FutureCallback<OfHeader> callBack = (FutureCallback<OfHeader>) invocation.getArguments()[2];
-                callBack.onSuccess(null);
-                return null;
-            }
-        })
-                .when(outboundQueueProvider)
-                .commitEntry(Matchers.anyLong(), Matchers.<MultipartRequestInput>any(), Matchers.<FutureCallback<OfHeader>>any());
-
-        when(mockedConnectionAdapter.registerOutboundQueueHandler(Matchers.<OutboundQueueHandler>any(), Matchers.anyInt(), Matchers.anyLong()))
-                .thenAnswer(new Answer<OutboundQueueHandlerRegistration<OutboundQueueHandler>>() {
-                    @Override
-                    public OutboundQueueHandlerRegistration<OutboundQueueHandler> answer(final InvocationOnMock invocation) throws Throwable {
-                        final OutboundQueueHandler handler = (OutboundQueueHandler) invocation.getArguments()[0];
-                        handler.onConnectionQueueChanged(outboundQueueProvider);
-                        return null;
-                    }
-                });
-
-        when(mockConnectionContext.getOutboundQueueProvider()).thenReturn(outboundQueueProvider);
-        return mockConnectionContext;
-    }
-}