X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=openflowplugin-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fopenflowplugin%2Fimpl%2Fstatistics%2FStatisticsContextImpl.java;h=68d349ad704af44855535dca37bb63887ba55646;hb=4bd43c307a24836ab1f7d6829d93d50e868e8ded;hp=3ef1a95eb753bc1d1179f0e0f45a4f0b931b66ef;hpb=513001ced86b008088b767994d0c83aacfa36863;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 3ef1a95eb7..68d349ad70 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 @@ -9,24 +9,20 @@ 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.collect.Iterators; 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 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.DeviceInfo; import org.opendaylight.openflowplugin.api.openflow.device.DeviceState; import org.opendaylight.openflowplugin.api.openflow.device.RequestContext; +import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor; import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener; import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext; import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext; @@ -38,10 +34,18 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev13 import org.slf4j.Logger; import org.slf4j.LoggerFactory; -/** - * Created by Martin Bobak <mbobak@cisco.com> on 1.4.2015. - */ -public class StatisticsContextImpl implements StatisticsContext { +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; + +class StatisticsContextImpl implements StatisticsContext { private static final Logger LOG = LoggerFactory.getLogger(StatisticsContextImpl.class); private static final String CONNECTION_CLOSED = "Connection closed."; @@ -51,57 +55,91 @@ public class StatisticsContextImpl implements StatisticsContext { private final DeviceContext deviceContext; private final DeviceState devState; private final ListenableFuture emptyFuture; - private final List collectingStatType; + private final boolean shuttingDownStatisticsPolling; + private final Object COLLECTION_STAT_TYPE_LOCK = new Object(); + @GuardedBy("COLLECTION_STAT_TYPE_LOCK") + private List collectingStatType; private StatisticsGatheringService statisticsGatheringService; private StatisticsGatheringOnTheFlyService statisticsGatheringOnTheFlyService; private Timeout pollTimeout; - public StatisticsContextImpl(@CheckForNull final DeviceContext deviceContext) { - this.deviceContext = Preconditions.checkNotNull(deviceContext); - devState = Preconditions.checkNotNull(deviceContext.getDeviceState()); - emptyFuture = Futures.immediateFuture(new Boolean(false)); + private volatile boolean schedulingEnabled; + + StatisticsContextImpl(@CheckForNull final DeviceInfo deviceInfo, final boolean shuttingDownStatisticsPolling, final LifecycleConductor lifecycleConductor) { + this.deviceContext = Preconditions.checkNotNull(lifecycleConductor.getDeviceContext(deviceInfo)); + this.devState = Preconditions.checkNotNull(deviceContext.getDeviceState()); + this.shuttingDownStatisticsPolling = shuttingDownStatisticsPolling; + emptyFuture = Futures.immediateFuture(false); statisticsGatheringService = new StatisticsGatheringService(this, deviceContext); statisticsGatheringOnTheFlyService = new StatisticsGatheringOnTheFlyService(this, deviceContext); + itemLifeCycleListener = new ItemLifecycleListenerImpl(deviceContext); + statListForCollectingInitialization(); + } - 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); + @Override + public void statListForCollectingInitialization() { + synchronized (COLLECTION_STAT_TYPE_LOCK) { + 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); } - collectingStatType = ImmutableList.copyOf(statListForCollecting); - itemLifeCycleListener = new ItemLifecycleListenerImpl(deviceContext); } @Override public ListenableFuture gatherDynamicData() { + if (shuttingDownStatisticsPolling) { + LOG.debug("Statistics for device {} is not enabled.", deviceContext.getDeviceInfo().getNodeId()); + return Futures.immediateFuture(Boolean.TRUE); + } final ListenableFuture errorResultFuture = deviceConnectionCheck(); if (errorResultFuture != null) { return errorResultFuture; } - final Iterator statIterator = collectingStatType.iterator(); - final SettableFuture settableStatResultFuture = SettableFuture.create(); - statChainFuture(statIterator, settableStatResultFuture); - return settableStatResultFuture; + synchronized (COLLECTION_STAT_TYPE_LOCK) { + final Iterator statIterator = collectingStatType.iterator(); + final SettableFuture settableStatResultFuture = SettableFuture.create(); + + // write start timestamp to state snapshot container + StatisticsGatheringUtils.markDeviceStateSnapshotStart(deviceContext); + + statChainFuture(statIterator, settableStatResultFuture); + + // write end timestamp to state snapshot container + Futures.addCallback(settableStatResultFuture, new FutureCallback() { + @Override + public void onSuccess(@Nullable final Boolean result) { + StatisticsGatheringUtils.markDeviceStateSnapshotEnd(deviceContext, true); + } + @Override + public void onFailure(final Throwable t) { + StatisticsGatheringUtils.markDeviceStateSnapshotEnd(deviceContext, false); + } + }); + return settableStatResultFuture; + } } - private ListenableFuture chooseStat(final MultipartType multipartType) { + private ListenableFuture chooseStat(final MultipartType multipartType){ switch (multipartType) { case OFPMPFLOW: return collectFlowStatistics(multipartType); @@ -125,9 +163,10 @@ public class StatisticsContextImpl implements StatisticsContext { } } + @Override public RequestContext createRequestContext() { - final AbstractRequestContext ret = new AbstractRequestContext(deviceContext.getReservedXid()) { + final AbstractRequestContext ret = new AbstractRequestContext(deviceContext.reserveXidForDeviceMessage()) { @Override public void close() { requestContexts.remove(this); @@ -139,8 +178,10 @@ public class StatisticsContextImpl implements StatisticsContext { @Override public void close() { - for (final RequestContext requestContext : requestContexts) { - RequestContextUtil.closeRequestContextWithRpcError(requestContext, CONNECTION_CLOSED); + schedulingEnabled = false; + for (final Iterator> iterator = Iterators.consumingIterator(requestContexts.iterator()); + iterator.hasNext();) { + RequestContextUtil.closeRequestContextWithRpcError(iterator.next(), CONNECTION_CLOSED); } if (null != pollTimeout && !pollTimeout.isExpired()) { pollTimeout.cancel(); @@ -148,24 +189,41 @@ public class StatisticsContextImpl implements StatisticsContext { } @Override - public void setPollTimeout(Timeout pollTimeout) { + public void setSchedulingEnabled(final boolean schedulingEnabled) { + this.schedulingEnabled = schedulingEnabled; + } + + @Override + public boolean isSchedulingEnabled() { + return schedulingEnabled; + } + + @Override + public void setPollTimeout(final Timeout pollTimeout) { this.pollTimeout = pollTimeout; } @Override public Optional getPollTimeout() { - return Optional.fromNullable(pollTimeout); + return Optional.ofNullable(pollTimeout); } - void statChainFuture(final Iterator iterator, final SettableFuture resultFuture) { + private void statChainFuture(final Iterator iterator, final SettableFuture resultFuture) { + if (ConnectionContext.CONNECTION_STATE.RIP.equals(deviceContext.getPrimaryConnectionContext().getConnectionState())) { + final String errMsg = String.format("Device connection is closed for Node : %s.", + deviceContext.getDeviceInfo().getNodeId()); + LOG.debug(errMsg); + resultFuture.setException(new IllegalStateException(errMsg)); + return; + } if ( ! iterator.hasNext()) { resultFuture.set(Boolean.TRUE); - LOG.debug("Stats collection successfully finished for node {}", deviceContext.getDeviceState().getNodeId()); + LOG.debug("Stats collection successfully finished for node {}", deviceContext.getDeviceInfo().getNodeId()); return; } final MultipartType nextType = iterator.next(); - LOG.debug("Stats iterating to next type for node {} of type {}", deviceContext.getDeviceState().getNodeId(), nextType); + LOG.debug("Stats iterating to next type for node {} of type {}", deviceContext.getDeviceInfo().getNodeId(), nextType); final ListenableFuture deviceStatisticsCollectionFuture = chooseStat(nextType); Futures.addCallback(deviceStatisticsCollectionFuture, new FutureCallback() { @@ -174,7 +232,7 @@ public class StatisticsContextImpl implements StatisticsContext { statChainFuture(iterator, resultFuture); } @Override - public void onFailure(final Throwable t) { + public void onFailure(@Nonnull final Throwable t) { resultFuture.setException(t); } }); @@ -205,59 +263,101 @@ public class StatisticsContextImpl implements StatisticsContext { return null; } + //TODO: Refactor twice sending deviceContext into gatheringStatistics private ListenableFuture collectFlowStatistics(final MultipartType multipartType) { return devState.isFlowStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics( - statisticsGatheringOnTheFlyService, deviceContext, /*MultipartType.OFPMPFLOW*/ multipartType) : emptyFuture; + statisticsGatheringOnTheFlyService, + deviceContext.getDeviceInfo(), + /*MultipartType.OFPMPFLOW*/ multipartType, + deviceContext, + deviceContext, + devState) : emptyFuture; } private ListenableFuture collectTableStatistics(final MultipartType multipartType) { return devState.isTableStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics( - statisticsGatheringService, deviceContext, /*MultipartType.OFPMPTABLE*/ multipartType) : emptyFuture; + statisticsGatheringService, + deviceContext.getDeviceInfo(), + /*MultipartType.OFPMPTABLE*/ multipartType, + deviceContext, + deviceContext, + devState) : emptyFuture; } private ListenableFuture collectPortStatistics(final MultipartType multipartType) { return devState.isPortStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics( - statisticsGatheringService, deviceContext, /*MultipartType.OFPMPPORTSTATS*/ multipartType) : emptyFuture; + statisticsGatheringService, + deviceContext.getDeviceInfo(), + /*MultipartType.OFPMPPORTSTATS*/ multipartType, + deviceContext, + deviceContext, + devState) : emptyFuture; } private ListenableFuture collectQueueStatistics(final MultipartType multipartType) { - return devState.isQueueStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics( - statisticsGatheringService, deviceContext, /*MultipartType.OFPMPQUEUE*/ multipartType) : emptyFuture; + return !devState.isQueueStatisticsAvailable() ? emptyFuture : StatisticsGatheringUtils.gatherStatistics( + statisticsGatheringService, + deviceContext.getDeviceInfo(), + /*MultipartType.OFPMPQUEUE*/ multipartType, + deviceContext, + deviceContext, + devState); } private ListenableFuture collectGroupDescStatistics(final MultipartType multipartType) { return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics( - statisticsGatheringService, deviceContext, /*MultipartType.OFPMPGROUPDESC*/ multipartType) : emptyFuture; + statisticsGatheringService, + deviceContext.getDeviceInfo(), + /*MultipartType.OFPMPGROUPDESC*/ multipartType, + deviceContext, + deviceContext, + devState) : emptyFuture; } private ListenableFuture collectGroupStatistics(final MultipartType multipartType) { return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics( - statisticsGatheringService, deviceContext, /*MultipartType.OFPMPGROUP*/ multipartType) : emptyFuture; + statisticsGatheringService, + deviceContext.getDeviceInfo(), + /*MultipartType.OFPMPGROUP*/ multipartType, + deviceContext, + deviceContext, + devState) : emptyFuture; } private ListenableFuture collectMeterConfigStatistics(final MultipartType multipartType) { return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics( - statisticsGatheringService, deviceContext, /*MultipartType.OFPMPMETERCONFIG*/ multipartType) : emptyFuture; + statisticsGatheringService, + deviceContext.getDeviceInfo(), + /*MultipartType.OFPMPMETERCONFIG*/ multipartType, + deviceContext, + deviceContext, + devState) : emptyFuture; } private ListenableFuture collectMeterStatistics(final MultipartType multipartType) { return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics( - statisticsGatheringService, deviceContext, /*MultipartType.OFPMPMETER*/ multipartType) : emptyFuture; + statisticsGatheringService, + deviceContext.getDeviceInfo(), + /*MultipartType.OFPMPMETER*/ multipartType, + deviceContext, + deviceContext, + devState) : emptyFuture; } @VisibleForTesting - protected void setStatisticsGatheringService(StatisticsGatheringService statisticsGatheringService) { + void setStatisticsGatheringService(final StatisticsGatheringService statisticsGatheringService) { this.statisticsGatheringService = statisticsGatheringService; } @VisibleForTesting - protected void setStatisticsGatheringOnTheFlyService(StatisticsGatheringOnTheFlyService + void setStatisticsGatheringOnTheFlyService(final StatisticsGatheringOnTheFlyService statisticsGatheringOnTheFlyService) { this.statisticsGatheringOnTheFlyService = statisticsGatheringOnTheFlyService; } @Override - public ItemLifecycleListener getItemLifeCycleListener() { + public ItemLifecycleListener getItemLifeCycleListener () { return itemLifeCycleListener; } + }