2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.openflowplugin.impl.statistics;
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.ImmutableList;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import com.google.common.util.concurrent.SettableFuture;
17 import io.netty.util.Timeout;
18 import java.util.ArrayList;
19 import java.util.Collection;
20 import java.util.HashSet;
21 import java.util.Iterator;
22 import java.util.List;
23 import javax.annotation.CheckForNull;
24 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
25 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
26 import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
27 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
28 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
29 import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext;
30 import org.opendaylight.openflowplugin.impl.services.RequestContextUtil;
31 import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.StatisticsGatheringOnTheFlyService;
32 import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.StatisticsGatheringService;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
38 * Created by Martin Bobak <mbobak@cisco.com> on 1.4.2015.
40 public class StatisticsContextImpl implements StatisticsContext {
42 private static final Logger LOG = LoggerFactory.getLogger(StatisticsContextImpl.class);
43 private static final String CONNECTION_CLOSED = "Connection closed.";
44 private final Collection<RequestContext<?>> requestContexts = new HashSet<>();
45 private final DeviceContext deviceContext;
46 private final DeviceState devState;
47 private final ListenableFuture<Boolean> emptyFuture;
48 private final List<MultipartType> collectingStatType;
50 private final StatisticsGatheringService statisticsGatheringService;
51 private final StatisticsGatheringOnTheFlyService statisticsGatheringOnTheFlyService;
52 private Timeout pollTimeout;
54 public StatisticsContextImpl(@CheckForNull final DeviceContext deviceContext) {
55 this.deviceContext = Preconditions.checkNotNull(deviceContext);
56 devState = Preconditions.checkNotNull(deviceContext.getDeviceState());
57 emptyFuture = Futures.immediateFuture(new Boolean(false));
58 statisticsGatheringService = new StatisticsGatheringService(this, deviceContext);
59 statisticsGatheringOnTheFlyService = new StatisticsGatheringOnTheFlyService(this, deviceContext);
61 final List<MultipartType> statListForCollecting = new ArrayList<>();
62 if (devState.isTableStatisticsAvailable()) {
63 statListForCollecting.add(MultipartType.OFPMPTABLE);
65 if (devState.isFlowStatisticsAvailable()) {
66 statListForCollecting.add(MultipartType.OFPMPFLOW);
68 if (devState.isGroupAvailable()) {
69 statListForCollecting.add(MultipartType.OFPMPGROUPDESC);
70 statListForCollecting.add(MultipartType.OFPMPGROUP);
72 if (devState.isMetersAvailable()) {
73 statListForCollecting.add(MultipartType.OFPMPMETERCONFIG);
74 statListForCollecting.add(MultipartType.OFPMPMETER);
76 if (devState.isPortStatisticsAvailable()) {
77 statListForCollecting.add(MultipartType.OFPMPPORTSTATS);
79 if (devState.isQueueStatisticsAvailable()) {
80 statListForCollecting.add(MultipartType.OFPMPQUEUE);
82 collectingStatType = ImmutableList.<MultipartType>copyOf(statListForCollecting);
86 public ListenableFuture<Boolean> gatherDynamicData() {
87 final ListenableFuture<Boolean> errorResultFuture = deviceConnectionCheck();
88 if (errorResultFuture != null) {
89 return errorResultFuture;
91 final Iterator<MultipartType> statIterator = collectingStatType.iterator();
92 final SettableFuture<Boolean> settableStatResultFuture = SettableFuture.create();
93 statChainFuture(statIterator, settableStatResultFuture);
94 return settableStatResultFuture;
97 private ListenableFuture<Boolean> chooseStat(final MultipartType multipartType) {
98 switch (multipartType) {
100 return collectFlowStatistics(multipartType);
102 return collectTableStatistics(multipartType);
104 return collectPortStatistics(multipartType);
106 return collectQueueStatistics(multipartType);
108 return collectGroupDescStatistics(multipartType);
110 return collectGroupStatistics(multipartType);
111 case OFPMPMETERCONFIG:
112 return collectMeterConfigStatistics(multipartType);
114 return collectMeterStatistics(multipartType);
116 LOG.warn("Unsuported Statistics type {}", multipartType);
117 return Futures.immediateCheckedFuture(Boolean.TRUE);
122 public <T> RequestContext<T> createRequestContext() {
123 final AbstractRequestContext<T> ret = new AbstractRequestContext<T>(deviceContext.getReservedXid()) {
125 public void close() {
126 requestContexts.remove(this);
129 requestContexts.add(ret);
134 public void close() {
135 for (final RequestContext<?> requestContext : requestContexts) {
136 RequestContextUtil.closeRequestContextWithRpcError(requestContext, CONNECTION_CLOSED);
138 if (null != pollTimeout && !pollTimeout.isExpired()) {
139 pollTimeout.cancel();
144 public void setPollTimeout(Timeout pollTimeout) {
145 this.pollTimeout = pollTimeout;
148 void statChainFuture(final Iterator<MultipartType> iterator, final SettableFuture<Boolean> resultFuture) {
149 if ( ! iterator.hasNext()) {
150 resultFuture.set(Boolean.TRUE);
153 final ListenableFuture<Boolean> deviceStatisticsCollectionFuture = chooseStat(iterator.next());
154 Futures.addCallback(deviceStatisticsCollectionFuture, new FutureCallback<Boolean>() {
156 public void onSuccess(final Boolean result) {
157 statChainFuture(iterator, resultFuture);
160 public void onFailure(final Throwable t) {
161 resultFuture.setException(t);
167 * Method checks a device state. It returns null for be able continue. Otherwise it returns immediateFuture
168 * which has to be returned from caller too
172 private ListenableFuture<Boolean> deviceConnectionCheck() {
173 if (!ConnectionContext.CONNECTION_STATE.WORKING.equals(deviceContext.getPrimaryConnectionContext().getConnectionState())) {
174 ListenableFuture<Boolean> resultingFuture = SettableFuture.create();
175 switch (deviceContext.getPrimaryConnectionContext().getConnectionState()) {
177 final String errMsg = String.format("Device connection doesn't exist anymore. Primary connection status : %s",
178 deviceContext.getPrimaryConnectionContext().getConnectionState());
179 resultingFuture = Futures.immediateFailedFuture(new Throwable(errMsg));
182 resultingFuture = Futures.immediateCheckedFuture(Boolean.TRUE);
185 return resultingFuture;
190 private ListenableFuture<Boolean> collectFlowStatistics(final MultipartType multipartType) {
191 return devState.isFlowStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
192 statisticsGatheringOnTheFlyService, deviceContext, /*MultipartType.OFPMPFLOW*/ multipartType) : emptyFuture;
195 private ListenableFuture<Boolean> collectTableStatistics(final MultipartType multipartType) {
196 return devState.isTableStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
197 statisticsGatheringService, deviceContext, /*MultipartType.OFPMPTABLE*/ multipartType) : emptyFuture;
200 private ListenableFuture<Boolean> collectPortStatistics(final MultipartType multipartType) {
201 return devState.isPortStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
202 statisticsGatheringService, deviceContext, /*MultipartType.OFPMPPORTSTATS*/ multipartType) : emptyFuture;
205 private ListenableFuture<Boolean> collectQueueStatistics(final MultipartType multipartType) {
206 return devState.isQueueStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
207 statisticsGatheringService, deviceContext, /*MultipartType.OFPMPQUEUE*/ multipartType) : emptyFuture;
210 private ListenableFuture<Boolean> collectGroupDescStatistics(final MultipartType multipartType) {
211 return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics(
212 statisticsGatheringService, deviceContext, /*MultipartType.OFPMPGROUPDESC*/ multipartType) : emptyFuture;
215 private ListenableFuture<Boolean> collectGroupStatistics(final MultipartType multipartType) {
216 return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics(
217 statisticsGatheringService, deviceContext, /*MultipartType.OFPMPGROUP*/ multipartType) : emptyFuture;
220 private ListenableFuture<Boolean> collectMeterConfigStatistics(final MultipartType multipartType) {
221 return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics(
222 statisticsGatheringService, deviceContext, /*MultipartType.OFPMPMETERCONFIG*/ multipartType) : emptyFuture;
225 private ListenableFuture<Boolean> collectMeterStatistics(final MultipartType multipartType) {
226 return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics(
227 statisticsGatheringService, deviceContext, /*MultipartType.OFPMPMETER*/ multipartType) : emptyFuture;