Java tutorial
/* * 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; 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 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.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 static final Logger LOG = LoggerFactory.getLogger(StatisticsContextImpl.class); private static final String CONNECTION_CLOSED = "Connection closed."; private final ItemLifecycleListener itemLifeCycleListener; private final Collection<RequestContext<?>> requestContexts = new HashSet<>(); private final DeviceContext deviceContext; private final DeviceState devState; private final ListenableFuture<Boolean> emptyFuture; private final List<MultipartType> 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)); statisticsGatheringService = new StatisticsGatheringService(this, deviceContext); statisticsGatheringOnTheFlyService = new StatisticsGatheringOnTheFlyService(this, deviceContext); final List<MultipartType> 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.<MultipartType>copyOf(statListForCollecting); itemLifeCycleListener = new ItemLifecycleListenerImpl(deviceContext); } @Override public ListenableFuture<Boolean> gatherDynamicData() { final ListenableFuture<Boolean> errorResultFuture = deviceConnectionCheck(); if (errorResultFuture != null) { return errorResultFuture; } final Iterator<MultipartType> statIterator = collectingStatType.iterator(); final SettableFuture<Boolean> settableStatResultFuture = SettableFuture.create(); statChainFuture(statIterator, settableStatResultFuture); return settableStatResultFuture; } private ListenableFuture<Boolean> 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 <T> RequestContext<T> createRequestContext() { final AbstractRequestContext<T> ret = new AbstractRequestContext<T>(deviceContext.getReservedXid()) { @Override public void close() { requestContexts.remove(this); } }; requestContexts.add(ret); return ret; } @Override public void close() { for (final RequestContext<?> requestContext : requestContexts) { RequestContextUtil.closeRequestContextWithRpcError(requestContext, CONNECTION_CLOSED); } if (null != pollTimeout && !pollTimeout.isExpired()) { pollTimeout.cancel(); } } @Override public void setPollTimeout(Timeout pollTimeout) { this.pollTimeout = pollTimeout; } @Override public Optional<Timeout> getPollTimeout() { return Optional.fromNullable(pollTimeout); } void statChainFuture(final Iterator<MultipartType> iterator, final SettableFuture<Boolean> resultFuture) { if (!iterator.hasNext()) { resultFuture.set(Boolean.TRUE); LOG.debug("Stats collection successfully finished for node {}", deviceContext.getDeviceState().getNodeId()); return; } final MultipartType nextType = iterator.next(); LOG.debug("Stats iterating to next type for node {} of type {}", deviceContext.getDeviceState().getNodeId(), nextType); final ListenableFuture<Boolean> deviceStatisticsCollectionFuture = chooseStat(nextType); Futures.addCallback(deviceStatisticsCollectionFuture, new FutureCallback<Boolean>() { @Override public void onSuccess(final Boolean result) { statChainFuture(iterator, resultFuture); } @Override public void onFailure(final Throwable t) { resultFuture.setException(t); } }); } /** * 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<Boolean> deviceConnectionCheck() { if (!ConnectionContext.CONNECTION_STATE.WORKING .equals(deviceContext.getPrimaryConnectionContext().getConnectionState())) { ListenableFuture<Boolean> 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; } private ListenableFuture<Boolean> collectFlowStatistics(final MultipartType multipartType) { return devState.isFlowStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(statisticsGatheringOnTheFlyService, deviceContext, /*MultipartType.OFPMPFLOW*/ multipartType) : emptyFuture; } private ListenableFuture<Boolean> collectTableStatistics(final MultipartType multipartType) { return devState.isTableStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(statisticsGatheringService, deviceContext, /*MultipartType.OFPMPTABLE*/ multipartType) : emptyFuture; } private ListenableFuture<Boolean> collectPortStatistics(final MultipartType multipartType) { return devState.isPortStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(statisticsGatheringService, deviceContext, /*MultipartType.OFPMPPORTSTATS*/ multipartType) : emptyFuture; } private ListenableFuture<Boolean> collectQueueStatistics(final MultipartType multipartType) { return devState.isQueueStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(statisticsGatheringService, deviceContext, /*MultipartType.OFPMPQUEUE*/ multipartType) : emptyFuture; } private ListenableFuture<Boolean> collectGroupDescStatistics(final MultipartType multipartType) { return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics(statisticsGatheringService, deviceContext, /*MultipartType.OFPMPGROUPDESC*/ multipartType) : emptyFuture; } private ListenableFuture<Boolean> collectGroupStatistics(final MultipartType multipartType) { return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics(statisticsGatheringService, deviceContext, /*MultipartType.OFPMPGROUP*/ multipartType) : emptyFuture; } private ListenableFuture<Boolean> collectMeterConfigStatistics(final MultipartType multipartType) { return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics(statisticsGatheringService, deviceContext, /*MultipartType.OFPMPMETERCONFIG*/ multipartType) : emptyFuture; } private ListenableFuture<Boolean> 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 ItemLifecycleListener getItemLifeCycleListener() { return itemLifeCycleListener; } }