X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=openflowplugin-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fopenflowplugin%2Fimpl%2Fstatistics%2FStatisticsContextImpl.java;h=301d0061fbd97c226ea5ce413489da571eca6589;hb=c65275bb09353d58610a644d1dfb70299143742c;hp=be3e1e7b3e2a9361b658412549396dd063f5aee0;hpb=c6a071abdc80250fb771531e226c201bed94ebac;p=openflowplugin.git diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsContextImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsContextImpl.java index be3e1e7b3e..301d0061fb 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsContextImpl.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsContextImpl.java @@ -8,122 +8,251 @@ package org.opendaylight.openflowplugin.impl.statistics; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; 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 io.netty.util.Timeout; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; import java.util.List; -import java.util.concurrent.Future; +import javax.annotation.CheckForNull; +import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext; import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext; +import org.opendaylight.openflowplugin.api.openflow.device.DeviceState; import org.opendaylight.openflowplugin.api.openflow.device.RequestContext; +import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener; import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext; -import org.opendaylight.openflowplugin.impl.rpc.RequestContextImpl; -import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightFlowStatisticsServiceImpl; -import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightFlowTableStatisticsServiceImpl; -import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightGroupStatisticsServiceImpl; -import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightMeterStatisticsServiceImpl; -import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightPortStatisticsServiceImpl; -import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightQueueStatisticsServiceImpl; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesOutput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsService; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; -import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.FlowStatisticsService; -import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.FlowTableStatisticsService; -import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.GroupStatisticsService; -import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.MeterStatisticsService; -import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.PortStatisticsService; -import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.QueueStatisticsService; -import org.opendaylight.yangtools.yang.common.RpcResult; -import java.util.Arrays; +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.statistics.services.dedicated.StatisticsGatheringOnTheFlyService; +import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.StatisticsGatheringService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Created by Martin Bobak <mbobak@cisco.com> on 1.4.2015. */ public class StatisticsContextImpl implements StatisticsContext { - private final List requestContexts = new ArrayList(); + private static final Logger LOG = LoggerFactory.getLogger(StatisticsContextImpl.class); + private static final String CONNECTION_CLOSED = "Connection closed."; + + private final ItemLifecycleListener itemLifeCycleListener; + private final Collection> requestContexts = new HashSet<>(); private final DeviceContext deviceContext; + private final DeviceState devState; + private final ListenableFuture emptyFuture; + private final List collectingStatType; + private StatisticsGatheringService statisticsGatheringService; + private StatisticsGatheringOnTheFlyService statisticsGatheringOnTheFlyService; + private Timeout pollTimeout; - private final FlowStatisticsService flowStatisticsService; - private final FlowTableStatisticsService flowTableStatisticsService; - private final GroupStatisticsService groupStatisticsService; - private final MeterStatisticsService meterStatisticsService; - private final PortStatisticsService portStatisticsService; - private final QueueStatisticsService queueStatisticsService; + public StatisticsContextImpl(@CheckForNull final DeviceContext deviceContext) { + this.deviceContext = Preconditions.checkNotNull(deviceContext); + devState = Preconditions.checkNotNull(deviceContext.getDeviceState()); + emptyFuture = Futures.immediateFuture(new Boolean(false)); + statisticsGatheringService = new StatisticsGatheringService(this, deviceContext); + statisticsGatheringOnTheFlyService = new StatisticsGatheringOnTheFlyService(this, deviceContext); + final List statListForCollecting = new ArrayList<>(); + if (devState.isTableStatisticsAvailable()) { + statListForCollecting.add(MultipartType.OFPMPTABLE); + } + if (devState.isFlowStatisticsAvailable()) { + statListForCollecting.add(MultipartType.OFPMPFLOW); + } + if (devState.isGroupAvailable()) { + statListForCollecting.add(MultipartType.OFPMPGROUPDESC); + statListForCollecting.add(MultipartType.OFPMPGROUP); + } + if (devState.isMetersAvailable()) { + statListForCollecting.add(MultipartType.OFPMPMETERCONFIG); + statListForCollecting.add(MultipartType.OFPMPMETER); + } + if (devState.isPortStatisticsAvailable()) { + statListForCollecting.add(MultipartType.OFPMPPORTSTATS); + } + if (devState.isQueueStatisticsAvailable()) { + statListForCollecting.add(MultipartType.OFPMPQUEUE); + } + collectingStatType = ImmutableList.copyOf(statListForCollecting); + itemLifeCycleListener = new ItemLifecycleListenerImpl(deviceContext); + } - public StatisticsContextImpl(DeviceContext deviceContext) { - this.deviceContext = deviceContext; + @Override + public ListenableFuture gatherDynamicData() { + final ListenableFuture errorResultFuture = deviceConnectionCheck(); + if (errorResultFuture != null) { + return errorResultFuture; + } + final Iterator statIterator = collectingStatType.iterator(); + final SettableFuture settableStatResultFuture = SettableFuture.create(); + statChainFuture(statIterator, settableStatResultFuture); + return settableStatResultFuture; + } - flowStatisticsService = new FlowStatisticsService(this, deviceContext); - flowTableStatisticsService = new FlowTableStatisticsService(this, deviceContext); - groupStatisticsService = new GroupStatisticsService(this, deviceContext); - meterStatisticsService = new MeterStatisticsService(this, deviceContext); - portStatisticsService = new PortStatisticsService(this, deviceContext); - queueStatisticsService = new QueueStatisticsService(this, deviceContext); + private ListenableFuture chooseStat(final MultipartType multipartType) { + switch (multipartType) { + case OFPMPFLOW: + return collectFlowStatistics(multipartType); + case OFPMPTABLE: + return collectTableStatistics(multipartType); + case OFPMPPORTSTATS: + return collectPortStatistics(multipartType); + case OFPMPQUEUE: + return collectQueueStatistics(multipartType); + case OFPMPGROUPDESC: + return collectGroupDescStatistics(multipartType); + case OFPMPGROUP: + return collectGroupStatistics(multipartType); + case OFPMPMETERCONFIG: + return collectMeterConfigStatistics(multipartType); + case OFPMPMETER: + return collectMeterStatistics(multipartType); + default: + LOG.warn("Unsuported Statistics type {}", multipartType); + return Futures.immediateCheckedFuture(Boolean.TRUE); + } + } + @Override + public RequestContext createRequestContext() { + final AbstractRequestContext ret = new AbstractRequestContext(deviceContext.getReservedXid()) { + @Override + public void close() { + requestContexts.remove(this); + } + }; + requestContexts.add(ret); + return ret; } - private void pollFlowStatistics() { - final KeyedInstanceIdentifier nodeII = InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(deviceContext.getPrimaryConnectionContext().getNodeId())); - final NodeRef nodeRef = new NodeRef(nodeII); - final GetAllFlowsStatisticsFromAllFlowTablesInputBuilder builder = - new GetAllFlowsStatisticsFromAllFlowTablesInputBuilder(); - builder.setNode(nodeRef); - //TODO : process data from result + @Override + public void close() { + for (final RequestContext requestContext : requestContexts) { + RequestContextUtil.closeRequestContextWithRpcError(requestContext, CONNECTION_CLOSED); + } + if (null != pollTimeout && !pollTimeout.isExpired()) { + pollTimeout.cancel(); + } } @Override - public ListenableFuture gatherDynamicData() { - ListenableFuture flowStatistics = StatisticsGatheringUtils.gatherFlowStatistics(flowStatisticsService, deviceContext); - ListenableFuture tableStatistics = StatisticsGatheringUtils.gatherTableStatistics(flowTableStatisticsService, deviceContext); - ListenableFuture groupStatistics = StatisticsGatheringUtils.gatherGroupStatistics(groupStatisticsService, deviceContext); - ListenableFuture meterStatistics = StatisticsGatheringUtils.gatherMeterStatistics(meterStatisticsService, deviceContext); - ListenableFuture portStatistics = StatisticsGatheringUtils.gatherPortStatistics(portStatisticsService, deviceContext); - ListenableFuture queueStatistics = StatisticsGatheringUtils.gatherQueueStatistics(queueStatisticsService, deviceContext); - - ListenableFuture> allFutures = Futures.allAsList(Arrays.asList(flowStatistics, tableStatistics, groupStatistics, meterStatistics, portStatistics, queueStatistics)); - final SettableFuture resultingFuture = SettableFuture.create(); - Futures.addCallback(allFutures, new FutureCallback>() { + public void setPollTimeout(Timeout pollTimeout) { + this.pollTimeout = pollTimeout; + } + + @Override + public Optional getPollTimeout() { + return Optional.fromNullable(pollTimeout); + } + + void statChainFuture(final Iterator iterator, final SettableFuture resultFuture) { + if ( ! iterator.hasNext()) { + resultFuture.set(Boolean.TRUE); + return; + } + final ListenableFuture deviceStatisticsCollectionFuture = chooseStat(iterator.next()); + Futures.addCallback(deviceStatisticsCollectionFuture, new FutureCallback() { @Override - public void onSuccess(final List booleans) { - resultingFuture.set(null); + public void onSuccess(final Boolean result) { + statChainFuture(iterator, resultFuture); } - @Override - public void onFailure(final Throwable throwable) { - resultingFuture.setException(throwable); + public void onFailure(final Throwable t) { + resultFuture.setException(t); } }); - return resultingFuture; } - @Override - public void forgetRequestContext(final RequestContext requestContext) { - requestContexts.remove(requestContexts); + /** + * 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 + */ + @VisibleForTesting + ListenableFuture deviceConnectionCheck() { + if (!ConnectionContext.CONNECTION_STATE.WORKING.equals(deviceContext.getPrimaryConnectionContext().getConnectionState())) { + ListenableFuture resultingFuture = SettableFuture.create(); + switch (deviceContext.getPrimaryConnectionContext().getConnectionState()) { + case RIP: + final String errMsg = String.format("Device connection doesn't exist anymore. Primary connection status : %s", + deviceContext.getPrimaryConnectionContext().getConnectionState()); + resultingFuture = Futures.immediateFailedFuture(new Throwable(errMsg)); + break; + default: + resultingFuture = Futures.immediateCheckedFuture(Boolean.TRUE); + break; + } + return resultingFuture; + } + return null; } - @Override - public SettableFuture> storeOrFail(final RequestContext data) { - requestContexts.add(data); - return data.getFuture(); + private ListenableFuture collectFlowStatistics(final MultipartType multipartType) { + return devState.isFlowStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics( + statisticsGatheringOnTheFlyService, deviceContext, /*MultipartType.OFPMPFLOW*/ multipartType) : emptyFuture; + } + + private ListenableFuture collectTableStatistics(final MultipartType multipartType) { + return devState.isTableStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics( + statisticsGatheringService, deviceContext, /*MultipartType.OFPMPTABLE*/ multipartType) : emptyFuture; + } + + private ListenableFuture collectPortStatistics(final MultipartType multipartType) { + return devState.isPortStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics( + statisticsGatheringService, deviceContext, /*MultipartType.OFPMPPORTSTATS*/ multipartType) : emptyFuture; + } + + private ListenableFuture collectQueueStatistics(final MultipartType multipartType) { + return devState.isQueueStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics( + statisticsGatheringService, deviceContext, /*MultipartType.OFPMPQUEUE*/ multipartType) : emptyFuture; + } + + private ListenableFuture collectGroupDescStatistics(final MultipartType multipartType) { + return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics( + statisticsGatheringService, deviceContext, /*MultipartType.OFPMPGROUPDESC*/ multipartType) : emptyFuture; + } + + private ListenableFuture collectGroupStatistics(final MultipartType multipartType) { + return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics( + statisticsGatheringService, deviceContext, /*MultipartType.OFPMPGROUP*/ multipartType) : emptyFuture; + } + + private ListenableFuture collectMeterConfigStatistics(final MultipartType multipartType) { + return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics( + statisticsGatheringService, deviceContext, /*MultipartType.OFPMPMETERCONFIG*/ multipartType) : emptyFuture; + } + + private ListenableFuture collectMeterStatistics(final MultipartType multipartType) { + return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics( + statisticsGatheringService, deviceContext, /*MultipartType.OFPMPMETER*/ multipartType) : emptyFuture; + } + + @VisibleForTesting + protected void setStatisticsGatheringService(StatisticsGatheringService statisticsGatheringService) { + this.statisticsGatheringService = statisticsGatheringService; + } + + @VisibleForTesting + protected void setStatisticsGatheringOnTheFlyService(StatisticsGatheringOnTheFlyService + statisticsGatheringOnTheFlyService) { + this.statisticsGatheringOnTheFlyService = statisticsGatheringOnTheFlyService; } @Override - public RequestContext createRequestContext() { - return new RequestContextImpl<>(this); + public ItemLifecycleListener getItemLifeCycleListener() { + return itemLifeCycleListener; } }